具有通用类的Monolog实现 [英] Monolog implementation with common class

查看:161
本文介绍了具有通用类的Monolog实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我成功实现了用于测试目的的Monolog记录器.现在,我正在尝试在项目中使用它.该项目不使用任何MVC框架.

I succeeded in implementing a Monolog logger for test purposes. And now I'm trying to use it in a project. This project doesn't use any MVC framework.

我正在尝试编写一个公共类文件来包装对Monolog实例的访问.

I'm trying to write a common class file to wrap access to the Monolog instance.

公共类文件:文件:app_log.php

Common class file: File: app_log.php

require 'autoload.php';
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Processor\UidProcessor;
use Monolog\Processor\WebProcessor;
use Monolog\Processor\MemoryUsageProcessor;
use Monolog\Processor\ProcessIdProcessor;
use Monolog\Formatter\LineFormatter;

class app_log {
  public function info(){
    $logger = new Logger('applog');
    $handler = new RotatingFileHandler('useractivity.log', 0, Logger::INFO);
    $handler->setFormatter(new LineFormatter("[%datetime%] %extra.process_id% %channel%.%level_name%: %message% %extra% %context% \n"));
    $logger->pushHandler($handler);
    $logger->pushProcessor(new WebProcessor);
  }  
}

其他文件:users.php

Other File: users.php

include_once 'app_log.php';
class users extends dbconnector{
    function login(){
      // Some project code. 
      $logger = new app_log();
      $logger->info('User logged successfully');
    }
}

到此为止效果很好,我想包括文件名,方法名,请求参数.但是我在日志中得到的是app_log.php文件名而不是users.php,而方法名是'info'而不是'login'.

Up to this works well and i want to include filename, method name, request parameters. But i am getting app_log.php file name instead users.php and Method name is 'info' instead 'login' in the logs.

示例:

[2018-06-07 20:55:50] 4410 applog.INFO: User logged successfully {"file":"/var/www/portal/lib/app_log.php","line":59,"class":"app_log","function":"info"} []

在这方面你们可以帮忙吗?

Could you guys help on this part?

推荐答案

恐怕您的整个设计都是错误的.

I'm afraid your whole design is simply wrong.

代替每次需要登录时都实例化新的Logger,您应该创建一个单独的$logger作为应用程序周围的服务.

Instead of instantiating a new Logger every time you need to log, you should be creating a single $logger to use as a service around your application.

在不了解有关您的应用程序的更多信息的情况下(无论如何必须重写应用程序都会使问题太宽泛),因此很难在这里猜测如何实现依赖注入.

Without knowing more about your application (and having to rewrite your application would make the question too broad anyway), it's hard to guess how to implement dependency injection here.

但是简单而幼稚的方法是:

But a simplistic and naive approach would be:

class users extends dbconnector {

    protected $logger;

    public function _construct(Logger $logger) {
       $this->logger = $logger;
    }

    function login() {
      $this->logger->info('User logged successfully');
    }
}

然后:

$logger  = new Logger('applog');
$handler = new RotatingFileHandler('useractivity.log', 0, Logger::INFO);
$handler->setFormatter(new LineFormatter("[%datetime%] %extra.process_id% %channel%.%level_name%: %message% %extra% %context% \n"));
$logger->pushHandler($handler);
$logger->pushProcessor(new WebProcessor);
$logger->pushProcessor(new IntrospectionProcessor);

$users = new users($logger);

如果将Logger实例注入需要它的对象中,则可以直接使用它,而不必创建自己的包装器"(在您的示例中设计不当),日志文件中的输出将符合您的期望.

If you inject that Logger instance in the objects that need it, you can use it directly without having to create your own "wrapper" (which in your example was poorly designed), and the output in the log files will match your expectations.

请注意,您没有使用

Notice that you are not using the IntrospectionProcessor, which you'd need to capture the filename and file line number. In the above example I'm also pushing it in $logger, the Logger instance.

(还要注意,仅在代码中添加此处理器并不能解决您的问题,因为对Logger::info()的调用将始终在app_log::info()中发生.)

(And also note that simply adding this processor to your code won't solve your issue, since the call to Logger::info() would always happen in app_log::info()).

请记住,您需要添加相应的use语句:use Monolog\Processor\IntrospectionProcessor;

Remember that you'll need to add the corresponding use statement: use Monolog\Processor\IntrospectionProcessor;

我不知道您系统的所有细节,也无法为您构建所有细节,但是如果依赖项注入仍然对您来说太多了,您可以使用全局状态方法暂时作弊.

I do not know all the details of your system, and can't build it all for you anyway, but if dependency injection is still too much for you, you could just cheat temporarily with a global-state approach.

例如:

function get_logger() {
   static $logger;

   if ($logger !== null) {
      return $logger;
   }

   $logger  = new Logger('applog');
   $handler = new RotatingFileHandler('useractivity.log', 0, Logger::INFO);
   $handler->setFormatter(new LineFormatter("[%datetime%] %extra.process_id% %channel%.%level_name%: %message% %extra% %context% \n"));
   $logger->pushHandler($handler);
   $logger->pushProcessor(new WebProcessor);
   $logger->pushProcessor(new IntrospectionProcessor);

   return $logger;
}

您可以将其放入您的文件require_once中,并且在需要访问记录器的每个位置中,只需执行以下操作即可:

You could put this in a file that you require_once, and in each of these places where you need access to the logger you can simply do:

 get_logger()->info('write to the log!');

我不赞成这样做,但是这是一个笨拙的解决方法,可让您动起来,直到您对其他OOP主题的理解有所提高.这只不过是一个穷人的人单身,通常这是避免的一种方式反正;但这现在可以为您提供帮助.

This is not something I'd endorse, but a crummy workaround for you to get moving until you advance somewhat in your understanding of other OOP topics. This is nothing else than a poor's man singleton, which more often than not is a pattern to avoid anyway; but that could help you right now..

这篇关于具有通用类的Monolog实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆