第二层内功 - 日志

  • 作者:KK

  • 发表日期:2017.3.11


基本使用

@runtime/logs目录就是日志目录

要产生日志就需要配置log组件,简单的配置示例如下:

'log' => [
	'targets' => [
		[
			'class' => 'yii\log\FileTarget', //日志处理器的类
			'levels' => ['error', 'warning'], //要记录的级别
			'logFile' => '@runtime/logs/app.log', //日志文件名
		],
	],
]

其中logFile是@runtime开头,底层会拿去做别名解析,所以会得到一个完整路径

添加以上组件配置后还要给app的bootstrap至少配置['log']这个值(不懂的菜鸟请参考了解组件 - 预启动组件

接下来在控制器里试着执行Yii::error('错误日志消息')这个代码,然后就能在@runtime/logs目录看到日志文件了,打开一看就懂里面的内容,我就不介绍先了


日志级别

级别的介绍

日志有级别的区分,其实主要跟PHP的错误级别对应吧,日志组件并不是所有级别的都会收集的,需要在配置里声明要收集的级别

怎么声明呢,很简单,就像上面的配置一样,在levels里声明,常见的level有4个,分别是:

  1. debug:调试级别

  2. info:消息级别

  3. warning:警告级别

  4. error:调错误级别

而上面例子中的配置就是只收集了warning和error两个级别而已


记录日志的快捷方法

Yii要实现写日志的手段挺多的,但它也提供了4个快捷方法:

Yii::debug('调试信息');

Yii::info('消息日志信息:后台用户 admin 于2012-12-12 12:12-12进行了登录');

Yii::warning('XXX产品库存小于30,请补仓');

Yii::error('支付接口通讯失败:相关的通讯数据……');

显然这4个方法的名称就是级别的名称,参数是一模一样的,就是要记录到日志里面的字符串


配置里没声明的级别,用了快捷方法也不会记录

就像上面的例子,如果配置说'levels' => ['warning', 'error']说明只要warning和error两个级别的日志

那如果你在代码中执行Yii::info('消息日志~~~')会发现logs目录根本不会产生任何日志,除非你在levels加入info的级别


日志分类

首先日志划分了不同级别,然后在不同级别中又可以再进一步进行划分,这个维度就是分类

Yii::error('无日志分类的');

//接下来重点
Yii::error('日志消息', 'category111');
Yii::error('日志消息', 'category222');

就这样,快捷日志方法里传入的第2个字符串参数就是日志分类的名称了,也意味着日志分类是自定义的,得到的日志内容是这样显示的:

红框所示的地方就是日志分类的名称了,其实默认的分类名称就叫application


日志分类过滤

关于日志分类有毛用呢?乍看之下也就只是在日志文件里多了个不同的标识吧?

其实日志分类也能参与到日志收集规则里的,可以定义要收集的日志分类:

'log' => [
	'targets' => [
		[
			'class' => 'yii\log\FileTarget',
			'levels' => ['error', 'warning'],
			'categories' => ['category111', 'application'], //这里定义收集的分类
			'logFile' => '@runtime/logs/app.log',
		],
	],
]

定义分类后之前的代码中category222这个分类是不会被记录到日志里的

于是就能从级别分类两个角度对日志进行过滤收集了


日志处理器

我们可以在log组件的targets中定义多个日志处理器:

'log' => [
	'targets' => [
		[
			//处理器1,用于收集错误级别的日志
			'class' => 'yii\log\FileTarget',
			'levels' => ['error'],
			'logFile' => '@runtime/logs/error.log',
		],
		
		[
			//处理器2,用于收集警告级别的日志
			'class' => 'yii\log\FileTarget',
			'levels' => ['warning'],
			'logFile' => '@runtime/logs/warning.log',
		],
		
		[
			//处理器3,用于收集调试级别的日志
			'class' => 'yii\log\FileTarget',
			'levels' => ['debug'],
			'logFile' => '@runtime/logs/debug.log',
		],
		
		[
			//处理器4,收集执行过的SQL
			'class' => 'yii\log\FileTarget',
			'levels' => ['info'],
			'categories' => [
				'yii\db\Command::query', //查询语句的分类
				'yii\db\Command::execute', //增删改语句的分类
			],
			'logFile' => '@runtime/logs/sql.log',
		],
	],
]

要注意targets是一个数组,每一个元素就是一个处理器的配置,实际上最基本的使用就是将不同级别的日志收集到不同的日志文件中

每个处理器都是一个实现了yii\log\Target的类,比如上面的yii\log\FileTarget是将日志收集到文件中的

其实处理器还有其它种类,比如yii\log\EmailTarget可以实现将日志收集到邮件中并发送给指定的邮箱

则甚至还有DbTarget可以将日志存入数据库等等,本节不对这些进行介绍

如果要自定义日志处理器请看我的Yii经验分享文章《自定义日志处理器


附注

关于上面示例有个处理器4是收集执行过的SQL,因为框架底层执行SQL的时候会调用Yii::info将这条SQL记录到消息级别的日志里面,所以我们只要定义info级别的收集器就能将这些SQL收集出来

相关代码请参考yii\db\Command类源代码的queryInternal方法里的Yii::info($rawSql, 'yii\db\Command::query')这些代码,或在这个类里搜索一下其它Yii::info关键字的代码