接口日志不全主因是关键字段缺失、时机错误、被跳过或覆盖,核心在于中间件顺序、请求/响应体单次读取限制、日志通道未隔离及敏感内容静默丢弃;需将日志中间件置全局首位、统一结构化输出、安全读取请求响应体、补全失败场景日志。

接口日志记录不全,通常不是“没写日志”,而是关键字段缺失、时机不对、被跳过或被覆盖。核心问题集中在中间件执行顺序、请求体读取限制、响应体不可重复读、日志通道未隔离、以及敏感/大体积内容被静默丢弃这几个环节。
确保中间件在正确时机捕获完整上下文
很多日志只记了 URI 和方法,却漏掉 IP、Header、参数或耗时,根本原因是中间件注册位置太靠后,或没覆盖全部入口。
- 把日志中间件放在全局中间件列表最前面(如 app/middleware.php 中排第一),避免被 CORS、Token 验证等中间件提前终止流程
- 确认它对所有 HTTP 方法生效:GET/POST/PUT/DELETE/HEAD 都要进中间件,不能只绑定到某类路由分组
- 若使用多模块 API(如 adminapi、mobileapi),检查中间件是否注册到对应模块的 middleware.php,而非仅全局
安全读取请求体与响应体
POST/JSON 请求体只可读一次;响应体流($response->getBody())同理。直接调用 getContents() 后业务层就拿不到原始数据,导致日志有、接口却报错。
- 对请求体:用
$request->param()(自动解析 JSON/表单)替代$request->getContent(),既安全又结构化 - 对文件上传请求:先用
$request->hasFile()判断,是则跳过 body 记录,防止日志暴涨 - 对响应体:若需记录原始响应内容,用
stream_get_contents($response->getBody())读取后,再用fopen('php://temp', 'r+')重建流供后续使用
启用独立日志通道并强制结构化输出
默认日志通道混入系统日志,且 Log::info('xxx') 写字符串会导致检索困难、字段无法过滤。
- 在 config/log.php 新增
'api'通道,驱动设为file或think,路径指向runtime/log/api/ - 日志写入必须构造数组:
Log::channel('api')->info(['method'=>'POST','uri'=>'/login','ip'=>'1.2.3.4','status'=>200,'cost_ms'=>128]) - 中文字段确保可读:写入前统一
json_encode($data, JSON_UNESCAPED_UNICODE),避免乱码
补全易被忽略的失败场景
401/403/500 等状态码常被记录,但真正难排查的是“200 响应里的业务错误”和“HTTP 客户端超时/解析失败”。
- 在全局中间件
after阶段,除状态码外,增加$response->getStatusCode() >= 400判断,并记录$response->getReasonPhrase() - 对第三方接口调用(如 Http::get),封装装饰器,在返回后主动校验 JSON 解析结果与业务 code 字段,失败时显式触发
Log::channel('thirdparty')->error() - 未授权访问统计不要依赖
Auth::check(),而应在中间件中$next($request)后检查$response->getCode()是否为 401/403,并提取$request->header('authorization')脱敏存储
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











