如何使用cakephp 3.6数据库和文件日志

时间:2018-05-07 11:02:37

标签: cakephp logging cakephp-3.x

如何在cakephp 3.6中包含数据库和文件日志?

日志文件的功能已经存在,这里是(ProjectLog.php):

<?php

namespace Project\Util;

use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

class ProjectLog
{
    /** @var Logger $logger */
    private static $logger;

    /** @var string $filePath */
    private static $filePath;

    /** @var string $key */
    private static $key;

    /**
     * @return string
     */
    public static function getFilePath(): string
    {
        return self::$filePath;
    }

    /**
     * @param string $name
     * @param string $category
     * @param string $client
     * @param string $mall
     * @param bool|null $stdoutFlag
     * @throws \Exception
     */
    public static function setConfig(
        string $name,
        string $category = 'client',
        string $client = 'etc',
        string $mall = 'etc',
        ?bool $stdoutFlag = false
    ) {
        if (empty($name) || empty($category) || empty($client) || empty($mall)) {
            $message = "Logger setting value is incomplete. name:{$name}, category:{$category}, client:{$client}, mall:{$mall}";
            throw new \Exception($message);
        }

        $dir = LOGS . $category . DS . $client . DS . $mall;
        if (!is_dir($dir)) {
            if (!mkdir($dir, 0777, true)) {
                throw new \Exception("Log directory creation failed. dir:{$dir}");
            }
        }

        self::$filePath = $dir . DS . $name . '_' . date('Ymd') . '.log';

        // monolog
        self::$key = self::$key ?? uniqid(mt_rand(10000000, 99999999)); // It looks like a key to be output to a log file. A different number for each process is numbered
        self::$logger = new Logger(self::$key);
        $logLevel = constant('Monolog\Logger::' . OUTPUT_LOG_LEVEL[KEY_ENVIRONMENT]);
        $stream = new StreamHandler(self::$filePath, $logLevel);
        $stream->setFormatter(new LineFormatter(null, null, true, true)); // Set monolog setting to have line feed
        self::$logger->pushHandler($stream);
        if ($stdoutFlag === true) {
            $stream = new StreamHandler("php://stdout", $logLevel);
            $stream->setFormatter(new LineFormatter(null, null, true, true)); // Set monolog setting to have line feed
            self::$logger->pushHandler($stream);
        }
    }

    /**
     * Grant user name to log
     *
     * @param string $userName
     */
    public static function addUserNameProcessor(string $userName): void
    {
        $handlers = self::$logger->getHandlers();

        foreach ($handlers as $handler) {
            $format = "[%extra.user_name%] [%datetime%] %channel%.%level_name%: %message% %context%\n";
            $handler->setFormatter(new LineFormatter($format, null, true, true)); // Set monolog setting to have line feed
        }

        self::$logger->pushProcessor(function ($record) use ($userName) {
            $record['extra']['user_name'] = $userName;
            return $record;
        });
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function emergency(string $message, $param = null): void
    {
        self::write(Logger::EMERGENCY, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function critical(string $message, $param = null): void
    {
        self::write(Logger::CRITICAL, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function alert(string $message, $param = null): void
    {
        self::write(Logger::ALERT, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function error(string $message, $param = null): void
    {
        self::write(Logger::ERROR, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function warning(string $message, $param = null): void
    {
        self::write(Logger::WARNING, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function notice(string $message, $param = null): void
    {
        self::write(Logger::NOTICE, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function info(string $message, $param = null): void
    {
        self::write(Logger::INFO, $message, $param);
    }

    /**
     * @param string $message
     * @param mixed $param
     */
    public static function debug(string $message, $param = null): void
    {
        self::write(Logger::DEBUG, $message, $param);
    }

    /**
     * @param int $level
     * @param string $message
     * @param null|array $param
     * @throws \LogicException
     */
    private static function write(int $level, string $message, $param = null): void
    {
        if (!self::$logger) {
            throw new \LogicException('Logger is not set.');
        }

        // Adjust so that $param can be passed to monolog if it is not an array
        if (is_null($param)) {
            $param = [];
        } elseif (is_object($param)) {
            $param = (array)$param;
        } elseif (!is_array($param)) {
            $param = [$param];
        }

        // Caller file and number of lines
        $backtrace = debug_backtrace();
        $file = $backtrace[1]['file'];
        $line = $backtrace[1]['line'];
        $context = ['file' => $file, 'line' => $line, 'param' => $param];

        self::$logger->addRecord($level, $message, $context);
    }
}

我现在需要的是做数据库日志。

我在网上看到了一些例子,但它使用的是插件,我不想这样做。

我想要的是为日志创建自定义表(result_log)。

可能吗?

有人可以分享他的想法或将我链接到一些有关创建数据库日志的指南吗?

2 个答案:

答案 0 :(得分:2)

您可以创建自己的日志适配器,然后使用它而不是CakePHP提供的日志适配器。

如果要将日志写入数据库,请创建表,烘焙模型并在日志适配器中使用它,就像保存“普通”实体一样。然后,您可以将其保存到文件中。

有关创建日志适配器的详细信息,请参阅文档:Creating Log Adapters

您还可以查看其中一个插件的制作方式,例如dereuromark/CakePHP-DatabaseLog

答案 1 :(得分:1)

Cake Szymon said是什么样的做法,我同意他们的回答。

我写这篇文章是因为您有自己的日志记录实现,而不遵循CakePHP日志记录配置。

在您的情况下,最简单的方法可能是更改您的static::write()功能,并在末尾添加添加一些代码,以便将日志保存在数据库中。

有些事情:

$ResultLog = TableRegistry::get('ResultLog');

$data = []; //add here data relevant to your logs and the db structure you are using

$logEntry = $ResultLogs->newEntity($data);

if(!($ResultLog->save($logEntry)){
    throw new \LogicException('Could not store the log into the DB.');
}

在导致ResultLog之前,您需要拥有像这样调用的Model \ Table。如果您已经有一个名为result_log的数据库表,则可以尝试使用

烘焙模型

bin/cake bake model ResultLog

(蛋糕的方式是调用表ResultLogs - 复数形式,但如果你想要的话,你可以用一些配置单数形式。

祝你好运!