php - 具有通用类的独白实现

标签 php oop logging monolog

我成功地实现了用于测试目的的 Monolog 记录器。现在我正试图在一个项目中使用它。该项目不使用任何 MVC 框架。

我正在尝试编写一个通用类文件来包装对 Monolog 实例的访问。

常用类文件:文件: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

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' 在日志中。

示例:

[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"} []

你们能帮忙解决这部分吗?

最佳答案

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

与其在每次需要记录时都实例化一个新的 Logger,不如创建一个 $logger 作为应用程序周围的服务。

在不了解您的应用程序的更多信息的情况下(并且必须重写您的应用程序会使问题太宽泛),很难猜测如何在此处实现依赖注入(inject)

但是一个简单而天真的方法是:

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);

如果您在需要它的对象中注入(inject) Logger 实例,您可以直接使用它而无需创建您自己的“包装器”(在您的示例中设计不当),并且输出日志文件中的内容将符合您的期望。

请注意,您没有使用 IntrospectionProcessor ,您需要捕获文件名和文件行号。在上面的示例中,我还将它推送到 $logger 中,Logger 实例。

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

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

我不知道你系统的所有细节,无论如何也不能为你构建它,但如果依赖注入(inject)对你来说仍然太多,你可以暂时用全局状态方法作弊。

例如:

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 的文件中,在每个你需要访问记录器的地方你可以简单地做:

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

这不是我赞同的东西,而是一个糟糕的解决方法,可以让您在对其他 OOP 主题的理解有所进步之前继续前进。这不过是个穷人singleton ,这通常是无论如何都要避免的模式;但这现在可以帮助你..

关于php - 具有通用类的独白实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50751195/

相关文章:

gnome - gnome vino-server 的日志在哪里?

php - 每 x 秒自动刷新一个 Html 表

php - 如何在服务器端脚本可以访问的同时将敏感数据安全地存储在共享主机提供商上?

ios - Swift:如何实现协议(protocol)(接口(interface))的部分类实现?

c++ - 找不到最新插入 std::map 的 key

php - 关于stackify-api,数据未显示在stackify日志中

node.js - 为什么根据生产/开发状态使用不同的调试模块?

php - 选择排除数组值的值

PHP/mySQL 准备好的语句

c# - 工厂模式困惑