Yii2记录器不从日志目标导出消息

时间:2017-03-24 11:39:25

标签: php yii yii2

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

我们的项目由以下Yii2'应用程序'组成:控制台,公共,前端,后端和每个组件的日志记录适用于Yii和常规PHP异常生成的异常。但是,当我在info部分(我通过SHH运行命令执行)中为特定类别添加一些console消息时,将创建该文件所在的目录,但文件本身不是。我看到当我执行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
        [...],
        [...],
        [...],
        [...],
        [...],
        [...],
        ],
    ]
];

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

1 个答案:

答案 0 :(得分:0)

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

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

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