日志记录和写入由`\think\Log`类完成,通常我们使用`think\facade\Log`类进行静态调用。
由于日志记录了所有的运行错误,因此养成经常查看日志文件的习惯,可以避免和及早发现很多的错误隐患。
>[info] 5.1的日志遵循`PSR-3`规范
[TOC=2,3]
## 日志配置
日志的配置文件是配置文件目录下的`log.php`文件,如果需要针对不同的模块设置不同的日志类型,则需要在模块配置目录下的`log.php`中配置,系统在进行日志写入之前会读取该配置文件进行初始化。
日志配置参数根据不同的日志类型有所区别,内置的日志类型包括:`file`、`socket`,日志类型使用`type`参数配置即可。
日志的全局配置参数包含(无论使用什么日志类型都支持):
参数|描述
---|---
type|日志类型(或者驱动类名称)
level|允许记录的日志级别
allow_key|允许日志写入的授权key
close|是否关闭日志写入(`V5.1.8+`)
>[danger] 默认的日志类型是`File`方式,可以通过驱动的方式来扩展支持更多的记录方式。
文件类型日志的话,还支持下列配置参数:
参数|描述
---|---
path|日志存储路径
file_size|日志文件大小限制(超出会生成多个文件)
apart_level|独立记录的日志级别
time_format|时间记录格式
single|是否单一文件日志
max_files|最大日志文件数(超过自动清理 `V5.1.6+`)
>[danger] 为了避免同一个目录下面的日志文件过多的性能问题,日志文件会自动生成日期子目录。
下面是一个`log.php`配置示例:
~~~
return [
// 日志记录方式,支持 file socket 或者自定义驱动类
'type' => 'File',
//日志保存目录
'path' => '../logs/',
//单个日志文件的大小限制,超过后会自动记录到第二个文件
'file_size' =>2097152,
//日志的时间格式,默认是` c `
'time_format' =>'c'
],
~~~
>[danger] 系统并未提供关闭日志的方法,但有两种方式可以关闭日志的写入,第一种方式是设置日志类型为test,即不写入任何日志。第二种方式是设置日志记录级别,只记录需要的日志。`V5.1.8+`版本开始,支持配置`close`参数关闭全局日志写入(但不影响`write`方法写入日志)。
## 日志写入
### 手动记录
一般情况下,系统的日志记录是自动的,无需手动记录,但是某些时候也需要手动记录日志信息,Log类提供了3个方法用于记录日志。
| 方法 | 描述 |
| --- | --- |
| record() | 记录日志信息到内存 |
| save() | 把保存在内存中的日志信息(用指定的记录方式)写入,并清空内存中的日志 |
| write() | 实时写入一条日志信息,会触发save操作 |
>[danger] `V5.1.15+`版本开始,`write`方法不会触发`save`操作
由于系统在请求结束后会自动调用`Log::save`方法,所以通常,你只需要调用`Log::record`记录日志信息即可。
record方法用法如下:
~~~
Log::record('测试日志信息');
~~~
默认记录的日志级别是`info`,也可以指定日志级别:
~~~
Log::record('测试日志信息,这是警告级别','notice');
~~~
采用`record`方法记录的日志信息不是实时保存的,如果需要实时记录的话,可以采用`write`方法,例如:
~~~
Log::write('测试日志信息,这是警告级别,并且实时写入','notice');
~~~
>[danger] 为避免内存溢出,在命令行下面执行的话日志信息会实时写入。
`V5.1.6+`版本开始,可以使用`close`方法临时关闭当前请求的日志写入。
~~~
// 关闭当前日志写入
Log::close();
~~~
不过,关闭日志并不会影响`write`方法的写入。
`V5.1.18+`版本开始,取消了原来的Test驱动,改为设置close参数关闭全局日志写入。
### 日志级别
ThinkPHP对系统的日志按照级别来分类记录,按照`PSR-3`日志规范,日志的级别从低到高依次为: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`,ThinkPHP额外增加了一个`sql`日志级别仅用于记录`SQL`日志(并且仅当开启数据库调试模式有效)。
>[danger] 系统发生异常后记录的日志级别是`error`
系统提供了不同日志级别的快速记录方法,例如:
~~~
Log::error('错误信息');
Log::info('日志信息');
// 和下面的用法等效
Log::record('错误信息','error');
Log::record('日志信息','info');
~~~
还封装了一个助手函数用于日志记录,例如:
~~~
trace('错误信息','error');
trace('日志信息','info');
~~~
事实上,你可以增加自定义的日志类型,例如:
~~~
Log::record('自定义错误信息','diy');
trace('自定义错误信息','diy');
~~~
也支持指定级别日志的输入,需要配置信息:
~~~
return [
'type' => 'File',
// 日志记录级别,使用数组表示
'level' => ['error','alert'],
],
~~~
上面的配置表示只记录`error`和`alert`级别的日志信息。
>[danger] 默认情况下是不会记录HTTP异常日志(避免受一些攻击的影响写入大量日志),除非你接管了系统的异常处理,重写了report方法。
### 上下文信息
日志可以传入上下文信息(数组),并且被替换到日志内容中,例如:
~~~
Log::info('日志信息{user}', ['user'=>'流年']);
~~~
实际写入日志的时候,`{user}`会被替换为流年。
### 独立日志
为了便于分析,`File`类型的日志还支持设置某些级别的日志信息单独文件记录,例如:
~~~
return [
'type' => 'file',
// error和sql日志单独记录
'apart_level' => ['error','sql'],
],
~~~
设置后,就会单独生成`error` 和 `sql`两个类型的日志文件,主日志文件中将不再包含这两个级别的日志信息。
> `V5.1.17+`版本开始,如果`apart_level`设置为`true`,则表示所有的日志类型都会独立记录。
### 单文件日志
默认情况下,日志是按照日期为目录,按天为文件生成的,但如果希望仅生成单个文件(方便其它的工具或者服务读取以及分析日志)。
~~~
return [
'single' => true,
'file_size' => 1024*1024*10,
];
~~~
开启生成单个文件后,`file_size`和`apart_level`参数依然有效,超过文件大小限制后,系统会自动生成备份日志文件。
默认的单文件日志名是`single.log`,如果需要更改日志文件名,可以设置
~~~
return [
'single' => 'single_file',
'file_size' => 1024*1024*10,
];
~~~
那么实际生成的日志文件名是 `single_file.log`,如果设置了`apart_level`的话,可能还会生成 `single_file.error.log`之类的日志。
>[info] `V5.1.25+`版本开始,单文件日志也支持`max_files`参数设置,因为单文件日志同样会生成多个日志备份文件而导致日志文件数据过大。
### 写入授权
日志支持写入授权,我们可以设置某个请求的日志授权Key,然后设置允许授权写入的配置`Key`,实现个别用户日志记录的功能,从而提高高负载下的日志记录性能。
首先需要在应用配置文件或者应用公共文件中添加当前访问的授权Key定义,例如:
~~~
// 设置IP为授权Key
Log::key(Request::ip());
~~~
然后在日志配置参数中增加`allow_key`参数,如下:
~~~
return [
// 日志类型为File
'type' => 'File',
// 授权只有202.12.36.89 才能记录日志
'allow_key' => ['202.12.36.89'],
]
~~~
### 清空日志
一旦执行`save`方法后,内存中的日志信息就会被自动清空,如果需要手动清空可以使用:
~~~
Log::clear();
~~~
在清空日志方法之前,你可以使用`getLog`方法获取内存中的日志。
~~~
// 获取错误类型日志
$error = Log::getLog('error');
// 获取全部日志
$logs = Log::getLog();
~~~
>[danger] 日志清空仅仅是清空内存中的日志。
### 日志自动清理(`V5.1.6+`)
从`V5.1.6+`版本开始,文件类型的日志支持自动清理。可以设置`max_files`参数,超过数量的最早日志将会自动删除。
例如,下面设置日志最多保存数量为30个
~~~
return [
'type' => 'File',
'max_files' => 30,
];
~~~
>[info] 设置`max_files`参数后,日志文件将不会分日期子目录存放。
>
### JSON格式日志(`V5.1.15+`)
从`V5.1.15+`版本开始,可以支持`JSON`格式记录文件日志,更加方便一些第三方日志分析工具进行日志分析。
在日志配置文件中,添加
~~~
'json' => true
~~~
即可开启`JSON`格式记录,CLI命令行的日志记录同样有效。
使用JSON格式记录后,每次请求是一行JSON数据,但如果使用`Log::write`记录的日志是例外的单独一行JSON数据。
> JSON格式记录日志的时候,独立记录日志级别参数`apart_level`无效。
- 序言
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 架构
- 架构总览
- 入口文件
- URL访问
- 模块设计
- 命名空间
- 容器和依赖注入
- Facade
- 钩子和行为
- 中间件
- 路由
- 路由定义
- 变量规则
- 路由地址
- 闭包支持
- 路由参数
- 路由缓存
- 跨域请求
- 注解路由
- 路由分组
- MISS路由
- 资源路由
- 快捷路由
- 路由别名
- 路由绑定
- 域名路由
- URL生成
- 控制器
- 控制器定义
- 前置操作
- 跳转和重定向
- 空操作和空控制器
- 分层控制器
- 资源控制器
- 控制器中间件
- 请求
- 请求对象
- 请求信息
- 输入变量
- 请求类型
- HTTP头信息
- 伪静态
- 参数绑定
- 请求缓存
- 响应
- 响应输出
- 响应参数
- 重定向
- 文件下载
- 数据库
- 连接数据库
- 查询构造器
- 查询数据
- 添加数据
- 更新数据
- 删除数据
- 查询表达式
- 链式操作
- where
- table
- alias
- field
- strict
- limit
- page
- order
- group
- having
- join
- union
- distinct
- lock
- cache
- comment
- fetchSql
- force
- partition
- failException
- sequence
- 聚合查询
- 时间查询
- 高级查询
- 视图查询
- JSON字段
- 子查询
- 原生查询
- 查询事件
- 获取器
- 事务操作
- 监听SQL
- 存储过程
- 数据集
- 分布式数据库
- 模型
- 定义
- 新增
- 更新
- 删除
- 查询
- JSON字段
- 获取器
- 修改器
- 搜索器
- 数据集
- 自动时间戳
- 只读字段
- 软删除
- 类型转换
- 数据完成
- 查询范围
- 模型输出
- 模型事件
- 模型关联
- 一对一关联
- 一对多关联
- 远程一对多
- 多对多关联
- 多态关联
- 关联预载入
- 关联统计
- 关联输出
- 视图
- 视图渲染
- 视图赋值
- 视图过滤
- 模板引擎
- 模板
- 变量输出
- 使用函数
- 运算符
- 原样输出
- 模板注释
- 模板布局
- 模板继承
- 包含文件
- 输出替换
- 标签库
- 内置标签
- 循环标签
- 比较标签
- 条件判断
- 资源文件加载
- 标签嵌套
- 原生PHP
- 定义标签
- 标签扩展
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 调试模式
- Trace调试
- 性能调试
- SQL调试
- 变量调试
- 远程调试
- 验证
- 验证器
- 验证规则
- 错误信息
- 验证场景
- 路由验证
- 内置规则
- 独立验证
- 静态调用
- 表单令牌
- 杂项
- 缓存
- Session
- Cookie
- 多语言
- 分页
- 上传
- 命令行
- 启动内置服务器
- 查看版本
- 自动生成目录结构
- 创建类库文件
- 生成类库映射文件
- 清除缓存文件
- 生成配置缓存文件
- 生成数据表字段缓存
- 生成路由映射缓存
- 输出路由定义
- 自定义指令
- 扩展库
- 验证码
- 图像处理
- Time
- 数据库迁移工具
- Swoole
- Workerman
- MongoDb
- 单元测试
- 安全和性能
- 安全建议
- 优化建议
- 附录
- 助手函数
- 升级指导
- 更新日志