使用 Monolog 记录整个数组的日志

11

不确定为什么StackOverflow决定关闭这个问题!这是答案:只需使用LineFormatter和以下选项:$formatter = new LineFormatter(null, null, true, true);,然后设置$formatter->setJsonPrettyPrint(true);,然后像往常一样定义您的处理程序$handler = new StreamHandler( $path, $level );,最后将格式化程序应用于处理程序:$handler->setFormatter($formatter);。如果您使用上下文参数调用记录器$logger->info("Short message", $anyArray);,则会以人类可读的形式在日志中获取$anyArray :-) - coccoinomane
1个回答

15

如果您检查记录器接口(https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php),你会发现所有的日志记录方法都将消息作为字符串传递,因此如果您尝试使用除字符串以外的变量类型进行日志记录,就会收到警告。

我尝试使用处理器以自定义方式格式化数组,但是如预期的那样,处理器在将变量发送到记录器接口之后触发。

记录数组最简单的方式可能是以下任何一种:

$logger->info(json_encode($array));
$logger->info(print_r($array, true));
$logger->info(var_export($array, true));

另一方面,您可能希望在单个处理器中格式化数组,以便使用DRY原则集中格式化逻辑。

Json编码数组 -> 以Json字符串形式发送 -> Json解码为数组 -> 格式化 -> 再次进行Json编码

CustomRequestProcessor.php

<?php
namespace Acme\WebBundle;


class CustomRequestProcessor
{


    public function __construct()
    {
    }

    public function processRecord(array $record)
    { 
        try {
            //parse json as object and cast to array
            $array = (array)json_decode($record['message']);
            if(!is_null($array)) {
                //format your message with your desired logic
                ksort($array);
                $record['message'] = json_encode($array);
            }
        } catch(\Exception $e) {
            echo $e->getMessage();
        }
        return $record;
    }
}

在您的config.yml或services.yml中注册请求处理器,查看标记节点以为自定义通道注册处理器。

services:
monolog.formatter.session_request:
    class: Monolog\Formatter\LineFormatter
    arguments:
        - "[%%datetime%%] %%channel%%.%%level_name%%: %%message%%\n"

monolog.processor.session_request:
    class: Acme\WebBundle\CustomRequestProcessor
    arguments:  []
    tags:
        - { name: monolog.processor, method: processRecord, channel: testchannel }

并且在控制器日志中将您的数组作为 JSON 字符串记录,

<?php

namespace Acme\WebBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    public function indexAction()
    {

        $logger = $this->get('monolog.logger.testchannel');
        $array = array(3=>"hello" , 1=>"world", 2=>"sf2");
        $logger->info(json_encode($array));

        return $this->render('AcmeWebBundle:Default:index.html.twig');
    }
}

现在你可以在中央请求处理器中按照自己的意愿格式化和记录你的数组,而无需在每个控制器中对数组进行排序/格式化/遍历。


2
我刚花了两天时间试图弄清楚如何做到这一点。谢谢。 在我看来,一个更好的解决方案是根本不使用monolog。 - ochitos
我能够使用 $logger->info(var_export($arrayName, true)); 让 mined 正常工作。虽然 json_encode 很厉害 :) - frostshoxx
8
你们误解了重点。Monolog是为结构化日志记录而设计的。任何Monolog日志记录器方法的第一个参数都应该是一个简单的消息字符串——事实上,Monolog明确将其转换为这样。然而,日志记录器方法确实支持额外的$context参数,它会在消息之后打印出来。因此,例如尝试使用$logger->info("My array", $array); - alexw
1
@fuximusfoe 我同意。我刚刚从 monolog 转而使用老旧的 file_get_contents()FILE_APPEND 标志。 - kjdion84
@alexw 那很有道理...你知道如何格式化打印$context吗?默认情况下,它是一个单行字符串中的JSON,这不太易读。 - coccoinomane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接