Hyperf打印日志,原始方法比较长,可以封装一下使用。
我的日志文件配置如下:config/autoload/logger.php
<?php
declare(strict_types=1);
use App\Log;
return [
Log::Default->value => [
'handler' => [
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => Monolog\Level::Debug,
],
],
'processors' => [
['class' => App\Kernel\Log\AppendFlowIdProcessor::class,],
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
'format' => null,
'dateFormat' => 'Y-m-d H:i:s',
'allowInlineLineBreaks' => true,
],
],
],
Log::Business->value => [
'handler' => [
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/business.log',
'level' => Monolog\Level::Debug,
],
],
'processors' => [
['class' => App\Kernel\Log\AppendFlowIdProcessor::class,],
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
'format' => null,
'dateFormat' => 'Y-m-d H:i:s',
'allowInlineLineBreaks' => true,
],
],
],
Log::Request->value => [
'handler' => [
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
'filename' => BASE_PATH . '/runtime/logs/request/request.log',
'level' => Monolog\Level::Debug,
],
],
'processors' => [
['class' => App\Kernel\Log\AppendFlowIdProcessor::class,],
],
],
Log::Error->value => [
'handler' => [
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
'filename' => BASE_PATH . '/runtime/logs/error/error.log',
'level' => Monolog\Level::Debug,
],
],
'processors' => [
['class' => App\Kernel\Log\AppendFlowIdProcessor::class,],
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
'batchMode' => Monolog\Formatter\JsonFormatter::BATCH_MODE_NEWLINES,
'appendNewline' => true,
],
],
],
];
上下文类:app/Kernel/Log/AppendFlowIdProcessor.php
<?php
declare(strict_types=1);
namespace App\Kernel\Log;
use Hyperf\Context\Context;
use Hyperf\Coroutine\Coroutine;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
class AppendFlowIdProcessor implements ProcessorInterface
{
public const FLOW_ID = 'flow_id';
public function __invoke(array|LogRecord $record): array|LogRecord
{
$record ['extra'] ['flow_id'] = Context::getOrSet(self::FLOW_ID, uniqid());
$record ['extra'] ['coroutine_id'] = Coroutine::id();
return $record;
}
}
方式一:封装一个Enum类打印日志,可按需输出日志到控制台,文件路径:app/Log.php
<?php
declare(strict_types=1);
namespace App;
use App\Kernel\Log\AppendFlowIdProcessor;
use BadMethodCallException;
use Hyperf\Context\Context;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Logger\LoggerFactory;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
enum Log: string
{
case Default = "default";
case Request = "request";
case Business = "business";
case Error = "error";
public const DEBUG = 1;
public const INFO = 2;
public const WARNING = 3;
public const ERROR = 4;
public function init(string $name = 'app'): LoggerInterface
{
return di(LoggerFactory::class)->get($name, $this->value);
}
public function __call($method, $arguments)
{
foreach ($arguments as $argument) {
$msg_arr [] = is_string($argument) ? $argument : json_encode($argument, JSON_UNESCAPED_UNICODE);
}
$messages = implode("|", $msg_arr ?? []);
if (method_exists(LoggerInterface::class, $method)) {
if ($this instanceof LoggerInterface) {
$this->$method($messages);
} else {
$this->init('app')->$method($messages);
}
if (!is_prod()) {
$func = [
'debug' => self::DEBUG,
'info' => self::INFO,
'warning' => self::WARNING,
'error' => self::ERROR,
'notice' => self::INFO,
];
$level = $func [$method] ?? 0;
['color' => $color, 'back' => $back] = [
self::DEBUG => ['color' => 35, 'back' => ""],
self::WARNING => ['color' => 31, 'back' => ""],
self::ERROR => ['color' => 37, 'back' => "\033 [41m"],
] [$level] ?? ['color' => 32, 'back' => ""];
$title = " [\033 [0;{$color}m{$back}{$this->value}-{$method}\033 [0m]";
$context = ['flow_id' => Context::get(AppendFlowIdProcessor::FLOW_ID), 'coroutine_id' => Coroutine::id()];
printf(" [%s] %s %s %s\n", di(\DateTime::class)->format('Y-m-d H:i:s.u'), $title, json_encode($context), $messages);
}
} else {
throw new BadMethodCallException("Method {$method} does not exist.");
}
}
}
上面的使用方式如下(支持多参数输入):
<?php
Log::Default->info("Hello~",1,'sadfsa', [1,2,3]);
Log::Default->info("Hello~");
方式二:简单封装一个帮助函数(app/Functions.php),不过帮助函数不支持传入多参数
<?php
declare(strict_types=1);
if (!function_exists('is_prod')) {
function is_prod(): bool
{
return config('app_env', 'dev') == 'prod';
}
}
if (!function_exists('container')) {
function container(): ContainerInterface
{
return ApplicationContext::getContainer();
}
}
if (!function_exists('di')) {
function di($id = null): mixed
{
$container = container();
if ($id) {
return $container->get($id);
}
return $container;
}
}
if (!function_exists('logger')) {
function logger(string $name = 'app', string $group = 'default'): LoggerInterface
{
return di(LoggerFactory::class)->get($name, $group);
}
}
最后于 9月前
被admin编辑
,原因: