日志
6.0的日志类比之前版本完善了很多,主要特性包括:
支持JSON日志
日志信息格式化
多通道写入支持
延时/实时写入
日志信息处理机制
日志级别指定通道写入
支持关闭日志/通道
新版的日志类最大的变化就是支持多通道写入,也就是说你可以同时或者给部分日志类型增加另外的日志通道写入,例如对于一些异常日志可以选择发送错误到邮件通知。
日志的相关配置可以在config/log.php文件中设置。
日志级别
ThinkPHP对系统的日志按照级别来分类记录(也称为日志类型),按照PSR-3日志规范,日志的级别从低到高依次为: debug, info, notice, warning, error, critical, alert, emergency。
ThinkPHP额外增加了一个sql日志级别仅用于记录SQL日志(并且仅当开启数据库调试模式有效)。
事实上,除了这些内置的日志级别之外,你可以根据业务需求增加自定义的日志级别。
系统发生异常后记录的日志级别是error
如果你只允许写入部分日志级别的日志,可以在日志配置文件中设置
'level' => ['error', 'alert' , 'info'],
level参数的设置是一个数组,包含了所有允许被记录的日志级别,其它级别的日志信息将直接被忽略。设置该参数的时候需要谨慎,避免出了问题不好排查。
日志记录
系统的日志记录是自动的,在项目里面你可以利用record方法来记录日志。
Log::record('这是一条日志信息');
record方法默认记录的日志级别是info类型,为了方便,系统给每个日志级别提供了快捷方法,所以上面的日志记录用下面的用法也是等效的:
Log::info('这是一条日志信息');
同样的,你可以使用
Log::error('错误信息');
Log::alert('警告信息');
所有的日志级别都可以使用单独的方法记录,方法名就是日志级别名称。
对于你自定义的日志级别(例如diy级别)则可以使用
Log::diy(‘自定义日志类型信息');
上下文信息
利用上下文功能便于通过日志模板来动态生成日志信息,例如:
Log::info('日志信息{user}', ['user' => '流年']);
实际写入日志的时候,{user}会被替换为流年。
实时写入
如果你需要实时写入一条日志信息,可以通过write方法实时写入。
Log::write('这是一条实时写入的日志信息');
你可以在第二个参数中传入要实时写入的日志级别,默认依然是info级别日志。
允许写入的日志级别设置对write方法写入日志依然有效。
日志处理
日志写入支持事件监听,例如。
Event::listen('think\event\LogWrite', function($event) {
if('file' == $event->channel) {
$event->log['info'][] = 'test info';
}
});
闭包的参数是LogWrite事件类对象实例,你可以获取两个属性:
属性名 描述
channel 写入日志的通道名
log 写入的日志信息
日志信息是一个二维数组,包含了当前日志通道下(允许记录的)所有级别的日志信息。
日志通道
日志通道的概念相当于给日志信息做了一个日志空间,每个日志通道的日志信息采用独立的写入机制或者配置参数,你可以给日志信息指定默认的日志通道,也可以动态切换通道写入,并且支持同一个日志信息同时写入多个日志通道。
你可以在日志配置文件的channels配置中定义通道,默认仅定义了一个file通道
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 使用JSON格式记录
'json' => false,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => false,
],
// 其它日志通道配置
],
每个日志通道必须指定type参数,该参数决定了日志的写入方式是什么,file就表示文件日志方式写入,如果需要指定其它的写入方式需要安装额外的扩展。但你也可以给不同的日志通道指定相同的type,只是其它的配置参数不同,例如写入的路径不同之类。
无论使用什么日志写入类型,每个日志通道可以支持的通用配置如下:
参数 说明
level 日志通道记录的日志级别
realtime_write 日志是否实时写入
level参数的用法和全局日志配置一致,除了在命令行模式下,默认的日志都是在请求结束后统一一次性写入,如果需要实时写入日志信息需要设置。
'realtime_write' => true,
默认通道
通过设置default参数定义日志的默认通道,例如:
'default' => 'file',
级别通道
可以设置不同的日志级别使用不同的日志通道
'type_channel' => [
// 对于error日志级别 同时写入file和email两个日志通道
'error' => ['file','email'],
]
设置了级别通道后,该级别的日志不会记录到默认通道,请注意。
日志通道需要日志驱动的配合,你也可以自定义日志驱动。
切换通道
你也可以手动切换当前的日志的默认写入通道,例如:
Log::channel('email')->info('这是日志信息');
支持切换使用多个通道记录,例如:
Log::channel(['email', 'file'])->info('这是日志信息');
如果需要切换回默认的日志通道,可以使用
Log::channel();
文件日志
文件类型日志的话,除了通道的通用配置参数外,还支持下列配置参数:
参数 描述
path 日志存储路径
file_size 日志文件大小限制(超出会生成多个文件)
apart_level 独立记录的日志级别
time_format 时间记录格式
single 是否单一文件日志
max_files 最大日志文件数(超过自动清理 )
format 日志输出格式
为了避免同一个目录下面的日志文件过多的性能问题,日志文件会自动生成月份子目录,然后下面按天生成日志,如果超出设置的大小则会生成备份日志文件。
独立日志
为了便于分析,File类型的日志还支持设置某些级别的日志信息单独文件记录,例如:
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
// error和sql日志单独记录
'apart_level' => ['error','sql'],
],
],
];
设置后,就会单独生成error 和 sql两个类型的日志文件,主日志文件中将不再包含这两个级别的日志信息。
如果apart_level设置为true,则表示所有的日志类型都会独立记录。
单文件日志
默认情况下,日志是按照日期(年月)为目录,按天为文件生成的,但如果希望仅生成单个文件(方便其它的工具或者服务读取以及分析日志)。
'channels' => [
'file' => [
'type' => 'file',
'single' => true,
'file_size' => 1024102410,
],
],
开启生成单个文件后,file_size和apart_level参数依然有效,超过文件大小限制后,系统会自动生成备份日志文件。
默认的单文件日志名是single.log,如果需要更改日志文件名,可以设置
'channels' => [
'file' => [
'type' => 'file',
'single' => 'single_file',
'file_size' => 1024102410,
],
],
那么实际生成的日志文件名是 single_file.log,如果设置了apart_level的话,可能还会生成 single_file_error.log之类的日志。
单文件日志也支持max_files参数设置,因为单文件日志同样会生成多个日志备份文件而导致日志文件数据过大。
格式化日志信息
系统提供了两个参数用于日志信息的格式化,第一个是用于自定义时间显示格式的time_format,第二个是调整日志输出格式的format参数。
'channels' => [
'file' => [
'type' => 'file',
'json' => true
'file_size' => 1024102410,
'time_format' => 'Y-m-d H:i:s',
'format' => '[%s][%s]:%s',
],
],
format参数的第一个%s是日志记录时间(日志时间的格式化由time_format参数定义) 第二个%s是日志级别 第三个%s是日志信息,顺序不能调整。
日志自动清理
文件类型的日志支持自动清理。可以设置max_files参数,超过数量的最早日志将会自动删除。
例如,下面设置日志最多保存数量为30个
'channels' => [
'file' => [
'type' => 'file',
'max_files' => 30,
'file_size' => 1024102410,
],
],
设置max_files参数后,日志文件将不会分日期子目录存放。
JSON格式日志
可以支持JSON格式记录文件日志,更加方便一些第三方日志分析工具进行日志分析。
在日志配置文件中,添加
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'json' => true
'file_size' => 1024102410,
],
],
];
即可开启JSON格式记录,CLI命令行的日志记录同样有效。
使用JSON格式记录后,每次请求是一行JSON数据,但如果使用Log::write记录的日志是例外的单独一行JSON数据。
关闭日志
你可以通过调用close方法动态关闭日志写入。
// 关闭全局日志写入
Log::close();
// 关闭某个通道日志写入
Log::close('file');
如果调用close方法动态关闭日志,会自动调用clear方法清空日志。
清空日志
一旦执行save方法后,内存中的日志信息就会被自动清空,如果需要提前清空日志可以使用:
// 清空所有日志
Log::clear();
//清空通道日志可以使用
Log::clear('file');
在清空日志方法之前,你可以使用getLog方法获取内存中的日志。
// 获取(默认通道)日志
$logs = Log::getLog();
// 获取指定通道日志
$logs = Log::getLog('file');
日志清空仅仅是清空内存中的日志。
自定义驱动
如果需要自定义日志驱动,你需要实现think\contract\LogHandlerInterface接口。
interface LogHandlerInterface
{
/**
- 日志写入接口
- @access public
- @param array $log 日志信息
- @return bool
*/
public function save(array $log): bool;
}
发表评论