Skip to content

Commit 39976b4

Browse files
author
苏青安
committed
增加日志记录
1 parent c973642 commit 39976b4

9 files changed

+364
-1
lines changed

README.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,29 @@ $data = $cache->set('key','value')
192192

193193
---
194194

195-
该库后续将持续更新,添加更多实用功能。欢迎大家提供建议和反馈,我会根据大家的意见实现新的功能,共同提升开发效率。
195+
该库后续将持续更新,添加更多实用功能。欢迎大家提供建议和反馈,我会根据大家的意见实现新的功能,共同提升开发效率。
196+
197+
198+
### 日志记录
199+
200+
不同框架通常自带日志系统,但要么强绑定到框架,更换框架就要重构日志方案,要么像 Monolog 这类强大的日志系统功能过于庞大。而为了在不同框架中保持通用性,同时避免过度复杂,我基于责任链模式实现了一个轻量级的日志模块
201+
202+
使用方法:
203+
204+
```php
205+
<?php
206+
207+
$log = new \Hejunjie\Tools\Log\Logger([
208+
new \Hejunjie\Tools\Log\Handlers\ConsoleHandler(), // 打印到控制台
209+
new \Hejunjie\Tools\Log\Handlers\FileHandler('日志存储文件夹路径'), // 存储到文件
210+
new \Hejunjie\Tools\Log\Handlers\RemoteApiHandler('请求url') // 发送到某个地址
211+
]);
212+
213+
$log->info('标题','内容',['上下文']); // INFO 级
214+
$log->warning('标题','内容',['上下文']); // WARNING 级
215+
$log->error('标题','内容',['上下文']); // ERROR 级
216+
217+
$log->log('自定义级别','标题','内容',['上下文']);
218+
219+
```
220+
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log\Formatters;
4+
5+
use Hejunjie\Tools\Log\LogFormatterInterface;
6+
7+
/**
8+
* 默认日志格式化器(文本格式)
9+
*
10+
* @package Hejunjie\Tools\Log\Formatters
11+
*/
12+
class DefaultFormatter implements LogFormatterInterface
13+
{
14+
/**
15+
* 格式化日志
16+
*
17+
* @param string $level 日志级别
18+
* @param string $message 日志内容
19+
* @param array $context 上下文
20+
*
21+
* @return string
22+
*/
23+
public function format(string $level, string $message, array $context = []): string
24+
{
25+
return sprintf("[%s] %s: %s %s\n", date('Y-m-d H:i:s'), $level, $message, json_encode($context));
26+
}
27+
}

src/Log/Formatters/JsonFormatter.php

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log\Formatters;
4+
5+
use Hejunjie\Tools\Log\LogFormatterInterface;
6+
7+
/**
8+
* Json格式化器
9+
*
10+
* @package Hejunjie\Tools\Log\Formatters
11+
*/
12+
class JsonFormatter implements LogFormatterInterface
13+
{
14+
/**
15+
* 格式化日志
16+
*
17+
* @param string $level 日志级别
18+
* @param string $message 日志内容
19+
* @param array $context 上下文
20+
*
21+
* @return string
22+
*/
23+
public function format(string $level, string $message, array $context = []): string
24+
{
25+
return json_encode([
26+
'time' => date('Y-m-d H:i:s'),
27+
'level' => $level,
28+
'message' => $message,
29+
'context' => $context
30+
], JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES + JSON_PRESERVE_ZERO_FRACTION);
31+
}
32+
}

src/Log/Handlers/ConsoleHandler.php

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log\Handlers;
4+
5+
use Hejunjie\Tools\Log\LogHandlerInterface;
6+
7+
/**
8+
* 控制台日志处理器
9+
*
10+
* @package Hejunjie\Tools\Log\Handlers
11+
*/
12+
class ConsoleHandler implements LogHandlerInterface
13+
{
14+
/**
15+
* 日志处理
16+
*
17+
* @param string $level 日志级别
18+
* @param string $title 日志标题
19+
* @param string $message 日志内容
20+
* @param array $context 上下文
21+
*
22+
* @return void
23+
*/
24+
public function handle(string $level, string $title, string $message, array $context = []): void
25+
{
26+
echo sprintf("[%s] %s: %s-%s %s\n", date('Y-m-d H:i:s'), $level, $title, $message, json_encode($context));
27+
}
28+
}

src/Log/Handlers/FileHandler.php

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log\Handlers;
4+
5+
use Hejunjie\Tools\Log\LogFormatterInterface;
6+
use Hejunjie\Tools\Log\LogHandlerInterface;
7+
use Hejunjie\Tools\Log\Formatters\DefaultFormatter;
8+
9+
/**
10+
* 文件日志处理器
11+
*
12+
* @package Hejunjie\Tools\Log\Handlers
13+
*/
14+
class FileHandler implements LogHandlerInterface
15+
{
16+
private string $logDir; // 日志存放目录
17+
private int $maxFileSize; // 最大文件大小(单位:字节)
18+
private LogFormatterInterface $formatter;
19+
20+
/**
21+
* 构造函数
22+
*
23+
* @param string $logDir 日志路径
24+
* @param int $maxFileSize 最大文件大小
25+
* @param LogFormatterInterface $formatter 格式化器
26+
*
27+
* @return void
28+
*/
29+
public function __construct(string $logDir, int $maxFileSize = 5000000, LogFormatterInterface $formatter = new DefaultFormatter())
30+
{
31+
$this->logDir = rtrim($logDir, '/') . '/';
32+
$this->maxFileSize = $maxFileSize;
33+
$this->formatter = $formatter;
34+
}
35+
36+
/**
37+
* 日志处理
38+
*
39+
* @param string $level 日志级别
40+
* @param string $title 日志标题
41+
* @param string $message 日志内容
42+
* @param array $context 上下文
43+
*
44+
* @return void
45+
*/
46+
public function handle(string $level, string $title, string $message, array $context = []): void
47+
{
48+
$logFile = $this->getLogFile($title);
49+
$formattedMessage = $this->formatter->format($level, $message, $context);
50+
51+
// 检查文件大小,进行文件分割
52+
if (file_exists($logFile) && filesize($logFile) > $this->maxFileSize) {
53+
$this->rotateLogFiles($logFile);
54+
}
55+
56+
file_put_contents($logFile, $formattedMessage . PHP_EOL, FILE_APPEND);
57+
}
58+
59+
/**
60+
* 获取日志文件
61+
*
62+
* @param string $title 文件名
63+
*
64+
* @return string
65+
*/
66+
private function getLogFile(string $title): string
67+
{
68+
if (!is_dir($this->logDir)) {
69+
mkdir($this->logDir, 0777, true);
70+
}
71+
return "{$this->logDir}{$title}.log";
72+
}
73+
74+
/**
75+
* 滚动日志文件(log_1.log, log_2.log ...)
76+
*
77+
* @param string $logFile 日志文件
78+
*
79+
* @return void
80+
*/
81+
private function rotateLogFiles(string $logFile): void
82+
{
83+
$index = 1;
84+
while (file_exists("{$logFile}.{$index}")) {
85+
$index++;
86+
}
87+
rename($logFile, "{$logFile}.{$index}");
88+
}
89+
}

src/Log/Handlers/RemoteApiHandler.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log\Handlers;
4+
5+
use Hejunjie\Tools\HttpClient;
6+
use Hejunjie\Tools\Log\LogFormatterInterface;
7+
use Hejunjie\Tools\Log\LogHandlerInterface;
8+
use Hejunjie\Tools\Log\Formatters\JsonFormatter;
9+
10+
/**
11+
* 远程接口日志处理器
12+
*
13+
* @package Hejunjie\Tools\Log\Handlers
14+
*/
15+
class RemoteApiHandler implements LogHandlerInterface
16+
{
17+
private string $endpoint;
18+
private LogFormatterInterface $formatter;
19+
20+
/**
21+
* 构造函数
22+
*
23+
* @param string $endpoint 远程接口地址
24+
* @param LogFormatterInterface $formatter 格式化器
25+
*
26+
* @return void
27+
*/
28+
public function __construct(string $endpoint, LogFormatterInterface $formatter = new JsonFormatter())
29+
{
30+
$this->endpoint = $endpoint;
31+
$this->formatter = $formatter;
32+
}
33+
34+
/**
35+
* 日志处理
36+
*
37+
* @param string $level 日志级别
38+
* @param string $title 日志标题
39+
* @param string $message 日志内容
40+
* @param array $context 上下文
41+
*
42+
* @return void
43+
*/
44+
public function handle(string $level, string $title, string $message, array $context = []): void
45+
{
46+
$payload = $this->formatter->format($level, $message, $context);
47+
HttpClient::sendPostRequest($this->endpoint, ['Content-Type: application/json'], $payload);
48+
}
49+
}

src/Log/LogFormatterInterface.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log;
4+
5+
/**
6+
* 日志格式化器接口
7+
*
8+
* @package Hejunjie\Tools\Log
9+
*/
10+
interface LogFormatterInterface
11+
{
12+
public function format(string $level, string $message, array $context = []): string;
13+
}

src/Log/LogHandlerInterface.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log;
4+
5+
/**
6+
* 日志处理器接口
7+
*
8+
* @package Hejunjie\Tools\Log
9+
*/
10+
interface LogHandlerInterface
11+
{
12+
/**
13+
* 日志处理
14+
*
15+
* @param string $level 日志级别
16+
* @param string $title 日志标题
17+
* @param string $message 日志内容
18+
* @param array $context 上下文
19+
*
20+
* @return void
21+
*/
22+
public function handle(string $level, string $title, string $message, array $context = []): void;
23+
}

src/Log/Logger.php

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Hejunjie\Tools\Log;
4+
5+
/**
6+
* 日志处理器接口
7+
*
8+
* @package Hejunjie\Tools\Log
9+
*/
10+
class Logger
11+
{
12+
private array $handlers = [];
13+
14+
public function __construct(array $handlers = [])
15+
{
16+
$this->handlers = $handlers;
17+
}
18+
19+
/**
20+
* 添加日志处理器
21+
*
22+
* @param string $level 日志级别
23+
* @param string $title 日志标题
24+
* @param string $message 日志内容
25+
* @param array $context 上下文
26+
*
27+
* @return void
28+
*/
29+
public function log(string $level, string $title, string $message, array $context = []): void
30+
{
31+
foreach ($this->handlers as $handler) {
32+
$handler->handle($level, $title, $message, $context);
33+
}
34+
}
35+
36+
/**
37+
* 记录调试信息
38+
*
39+
* @param string $title 日志标题
40+
* @param string $message 日志内容
41+
* @param array $context 上下文
42+
*
43+
* @return void
44+
*/
45+
public function info(string $title, string $message, array $context = []): void
46+
{
47+
$this->log('INFO', $title, $message, $context);
48+
}
49+
50+
/**
51+
* 记录错误信息
52+
*
53+
* @param string $title 日志标题
54+
* @param string $message 日志内容
55+
* @param array $context 上下文
56+
*
57+
* @return void
58+
*/
59+
public function error(string $title, string $message, array $context = []): void
60+
{
61+
$this->log('ERROR', $title, $message, $context);
62+
}
63+
64+
/**
65+
* 记录警告信息
66+
*
67+
* @param string $title 日志标题
68+
* @param string $message 日志内容
69+
* @param array $context 上下文
70+
*
71+
* @return void
72+
*/
73+
public function warning(string $title, string $message, array $context = []): void
74+
{
75+
$this->log('WARNING', $title, $message, $context);
76+
}
77+
}

0 commit comments

Comments
 (0)