【问题标题】:Yii2 logger not exporting messages from log targetsYii2 记录器不从日志目标导出消息
【发布时间】:2017-03-24 11:39:24
【问题描述】:

我正在收紧我们的 Yii2 应用程序的日志记录,并且正在努力让 Logger 在处理特定类别时将消息实际写入日志文件。

我们的项目由以下 Yii2 'Applications' 组成:控制台、通用、前端、后端和每个组件的日志记录对于 Yii 生成的异常和一般 PHP 异常都可以正常工作。但是,当我在 console 部分(我通过通过 SHH 运行命令执行)中为特定类别添加一些 info 消息时,将创建文件应该位于的目录,但文件本身不是。当我对其进行 var_dump 时,我看到新指定的日志消息位于正确的“FileTarget”内。

我已将“log”组件的flushInterval 设置为1,将logTarget 的exportInterval 设置为1,以确保将消息直接写入目标。我知道这应该在某个时候设置为更大的值,但现在我想确保日志确实被保存了。更改间隔值似乎没有任何效果。

我想出的解决方法是为特定的 FileTarget 手动调用 target->export()。这是我目前确保正在写入日志的方式:

在我想要记录消息的控制器中

Yii::info('Report created succesfully.', 'reports-create'); 
UtilitiesController::forceLogExport('reports-create');

forceLogExport 方法这样做:

public function forceLogExport($categoryName = ''){
        $logger = \Yii::getLogger();
        foreach($logger->dispatcher->targets as $target){
                if(!empty($categoryName)){
                    foreach($target->categories as $category){
                        if($category == $categoryName){ 
                            $target->export();
                        }    
                    }    
                }
        }
        $logger->flush(true);
    }

这确实将日志写入 .log 文件,但是现在日志中似乎有重复的条目,并且在每条消息之后调用导出是完全错误的。

正如我在文档中所读到的,日志的实际写入仅在满足这些间隔或应用程序结束时发生。我可以想象应用程序没有正确结束,所以我尝试在记录消息后直接调用Yii:$app->end() 来强制执行此操作,但文件保持为空。

因为问题既不是应用程序没有结束(我可以看到它确实结束了)也不是正在满足的时间间隔(我在目标中看到至少一条消息并且时间间隔是设置为 1) 我有点不知所措,为什么不导出日志。如果有人可以进一步详细说明 Yii 何时/何地调用 ->export() 方法本身,那将是一个很大的帮助。

编辑: 添加了 console/config/main.php 设置。稍微改变了我的故事,最初我写道“正在创建日志文件,但没有将消息写入其中。”但实际上只创建了应该包含文件的目录,而不是日志文件本身。

<?php
return [
    'id' => 'console',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'console\controllers',
    'components' => [
        'user' => [
            'class' => 'yii\web\User',
            'identityClass' => 'app\models\User',
            //'enableAutoLogin' => true,
        ],
        'session' => [ // for use session in console application
            'class' => 'yii\web\Session'
        ],
        'log' => [
            'flushInterval' => 1,
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error','info', 'warning'],
                    'categories' => ['reports-schedule'], 
                    'exportInterval' => 1,
                    'logVars' => [null],
                    'logFile' => '@app/../logs/console/'. date('Y') . '/' . date('m') . '/reports-schedule/' . 'reports-schedule_' . date('d-m-Y') . '.log'
                ],
        [ 
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error','info', 'warning'],
                    'categories' => ['reports-create'], 
                    'exportInterval' => 1,
                    'logVars' => [null],
                    'logFile' => '@app/../logs/console/'. date('Y') . '/' . date('m') . '/reports-create/' . 'reports-create_' . date('d-m-Y') . '.log'
                ],
        // and 6 other similarly structured targets
        [...],
        [...],
        [...],
        [...],
        [...],
        [...],
        ],
    ]
];

更新:看来我必须坚持在所需的日志目标上手动调用 -&gt;export()。我在写入重复日志条目(相同的消息,相同的时间戳)时遇到的问题是因为我已将目标的 exportInterval 属性设置为 1(我最初这样做是为了确保完全导出消息)。我想记录器会存储消息,直到满足 exportInterval 的值,然后期望将这些消息写入目标。我通过删除exportInterval 属性修复了重复条目,因此Yii 采用默认值(1000)。就我而言,这已经足够了,因为我不会遇到这些数字,但对于阅读本文的任何人,请考虑您的用例并检查您是否会在单个周期内遇到任何接近该数字的情况。

【问题讨论】:

  • 控制台命令是否完成处理?
  • 是的,但强制结束(通过使用$app-&gt;end()exit())不会改变结果。
  • 在控制台配置中有'bootstrap' =&gt; ['log']吗?
  • 是的。我想如果我不这样做,我的解决方法也不会奏效。
  • 那么,请向我们展示您的控制台日志配置。

标签: php yii yii2


【解决方案1】:

我在某些时候遇到过类似的问题,我认为这对于您的情况应该足够了。

    Yii::$app->log->targets['reports-schedule']->logFile = $logPath;
    Yii::info($message, $category);
    Yii::getLogger()->flush();

通过这种方式,您可以在计划目标内指定动态日志路径,并在刷新后继续记录器。

【讨论】:

  • 谢谢!但这对我提出了几个问题。对我来说,目标是一个数字数组,我不能像你一样通过调用它的类别名称来访问目标,但我想这不是你想要说明的重点。此外,当我对目标对象进行 var_dump 时,-&gt;logFile 已经有了正确的路径,所以我看不到设置路径有任何用处。并调用flush() 将消息发送到目标,而不是导出它们对吗?我之前尝试过调用flush()来解决这个问题,但是没有任何效果。
  • 我猜我一开始并没有阅读整个故事:P 我最好的选择是,如果您运行控制台操作,则您没有创建文件的权限。因为刷新应该强制注销文件并从头开始。你可以通过尝试在前端/后端记录一些东西然后在控制台操作中做同样的事情来测试这个理论
猜你喜欢
  • 2012-05-24
  • 2011-10-07
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 2021-01-16
  • 2018-09-20
  • 1970-01-01
  • 2017-06-04
相关资源
最近更新 更多