-
Notifications
You must be signed in to change notification settings - Fork 1.6k
日志处理
日志的配置文件是配置文件目录下的log.php
文件,系统在进行日志写入之前会读取该配置文件进行初始化
return [
// 默认日志记录通道
'default' => 'file',
// 日志记录级别
'level' => [],
// 日志类型记录的通道 ['error'=>'email',...]
'type_channel' => [],
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
],
// 其它日志通道配置
],
];
可以添加多个日志通道,每个通道可以设置不同的日志类型。日志配置参数根据不同的日志类型有所区别,内置的日志类型包括:file
,日志类型使用type
参数配置即可。
如果是自定义驱动,
type
的值则为自定义驱动的类名(包含命名空间)
日志全局配置参数:
参数 | 描述 |
---|---|
default | 默认的日志通道 |
level | 允许记录的日志级别 |
type_channel | 日志类型记录的通道 |
默认的日志类型是
File
方式,可以通过驱动的方式来扩展支持更多的记录方式。
文件类型日志的话,还支持下列配置参数:
参数 | 描述 |
---|---|
path | 日志存储路径 |
file_size | 日志文件大小限制(超出会生成多个文件) |
apart_level | 独立记录的日志级别 |
time_format | 时间记录格式 |
single | 是否单一文件日志 |
max_files | 最大日志文件数(超过自动清理 ) |
format | 日志输出格式 |
realtime_write | 是否实时写入 |
为了避免同一个目录下面的日志文件过多的性能问题,日志文件会自动生成日期子目录。
一般日志是自动写入的,手动写入日志使用这两个方法
record 方法(记录日志信息到内存)
Log::record('日志信息');
//默认日志级别是info,也可以手动指定
Log::record('这是一条警告日志','notice');
write方法(实时记录)
Log::write('测试日志信息,这是警告级别,并且实时写入','notice');
配置文件中开启实时写入
// 实时写入
'realtime_write' => true,
Log::close();
日志的级别从低到高依次为:debug
,info
,notice
,warning
,error
,critical
,alert
,emergency
,ThinkPHP额外增加了一个sql
日志级别仅用于记录SQL
日志(并且仅当开启数据库调试模式有效)
系统发生异常后记录的日志级别是
error
Log::error('错误信息');
Log::info('日志信息');
提供助手函数
trace('错误信息', 'error');
trace('日志信息', 'info');
默认情况下是不会记录HTTP异常日志(避免受一些攻击的影响写入大量日志),除非你接管了系统的异常处理,重写了
report
方法
日志可以传入上下文信息(数组),并且被替换到日志内容中
Log::info('日志信息{user}',['user'=>'张三']);
为了便于分析,File
类型的日志还支持设置某些级别的日志信息单独文件记录:
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
// error和sql日志单独记录
'apart_level' => ['error','sql'],
],
],
];
设置后,就会单独生成error
和sql
两个类型的日志文件,主日志文件中将不再包含这两个级别的日志信息
如果
apart_level
设置为true
,则表示所有的日志类型都会独立记录
默认情况下,日志是按照日期为目录,按天为文件生成的,但如果希望仅生成单个文件(方便其它的工具或者服务读取以及分析日志)
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'single' => true,
'file_size' => 1024*1024*10,
],
],
];
开启生成单个文件后,file_size
和apart_level
参数依然有效,超过文件大小限制后,系统会自动生成备份日志文件。
默认的单文件日志名是single.log
,如果需要更改日志文件名,可以设置
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'single' => 'single_file',
'file_size' => 1024*1024*10,
],
],
];
那么实际生成的日志文件名是single_file.log
,如果设置了apart_level
的话,可能还会生成single_file_error.log
之类的日志
单文件日志也支持
max_files
参数设置,因为单文件日志同样会生成多个日志备份文件而导致日志文件数据过大
日志支持写入回调处理,通过事件的方式处理。
Event::listen('think\event\LogWrite', function($event) {
if('file' == $event->channel) {
$event->log['info'][] = 'test info';
}
});
系统提供了两个参数用于日志信息的格式化,第一个是用于自定义时间显示格式的time_format
,第二个是调整日志输出格式的format
参数
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'json' => true
'file_size' => 1024*1024*10,
'time_format' => 'Y-m-d H:i:s',
'format' => '[%s][%s]:%s',
],
],
];
一旦执行save
方法后,内存中的日志信息就会被自动清空,如果需要手动清空可以使用:
Log::clear();
在清空日志方法之前,你可以使用getLog
方法获取内存中的日志。
// 获取全部日志
$logs = Log::getLog();
日志清空仅仅是清空内存中的日志。
文件类型的日志支持自动清理。可以设置max_files
参数,超过数量的最早日志将会自动删除。
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'max_files' => 30,
'file_size' => 1024*1024*10,
],
],
];
设置
max_files
参数后,日志文件将不会分日期子目录存放。
可以支持JSON
格式记录文件日志,更加方便一些第三方日志分析工具进行日志分析。
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'json' => true
'file_size' => 1024*1024*10,
],
],
];
即可开启JSON
格式记录,CLI命令行的日志记录同样有效。
使用JSON格式记录后,每次请求是一行JSON数据,但如果使用Log::write
记录的日志是例外的单独一行JSON数据。
你可以配置不同的日志通道,并且把不同的日志记录到不同的通道。
Log::channel('email')->info('一条测试日志');
Log::channel('socket')->error('记录错误日志');
你可以配置不同的日志类型,记录到不同的日志通道,这样在记录日志的时候会自动选择对应的通道写入。
return [
'default' => 'file',
'type_channel' => [
'error' => 'email',
'sql' => 'sql',
],
'channels' => [
'file' => [
'type' => 'file',
],
'email' => [
'type' => 'email',
],
'sql' => [
'type' => 'sql',
],
],
];
表示如果是error
日志和sql
日志,会分别记录到指定的通道。同时你还需要在日志配置文件中,添加email
和sql
日志通道的配置。核心只有file
日志类型,其它的可能需要自己扩展或者安装扩展。
如果需要获取内存中的通道日志信息,可以使用
// 获取某个日志通道的日志
$error = Log::getLog('file');
可以单独关闭某个通道的日志写入,只需要把日志通道的close
配置参数设置为true
,或者使用方法关闭。
Log::close('file');
可以单独清空某个通道的日志(如果没有开启实时写入的话)
Log::clear('file');
如果需要自定义日志驱动,你需要实现think\contract\LogHandlerInterface
接口。
interface LogHandlerInterface
{
/**
* 日志写入接口
* @access public
* @param array $log 日志信息
* @return bool
*/
public function save(array $log): bool;
}