用 error_log($msg, 3, $file) 直接写日志最轻量,需指定路径、过滤敏感字段、用 $_server['request_time_float'] 计时、响应体限长;file_put_contents + file_append | lock_ex 更安全;取真实ip须校验 x-forwarded-for;按天切分日志并自动清理。

怎么用 error_log 记录 API 请求的入参、响应和耗时
直接写日志最轻量,error_log 不依赖框架或扩展,PHP 默认就支持。但要注意它默认写到 error_log 配置路径(可能是系统 syslog 或 /var/log/apache2/error.log),不是你想写的文件。
实操建议:
- 用
error_log($msg, 3, '/path/to/api.log')指定文件路径,确保 PHP 进程有写权限 - 入参记录前先
json_encode($_REQUEST, JSON_UNESCAPED_UNICODE),避免乱码;敏感字段(如password、token)必须提前 unset - 耗时不能靠
microtime(true)两次相减完事——中间若有ob_start()或输出缓冲操作,实际响应时间会被拉长;建议在fastcgi_finish_request()后再记日志,或改用$_SERVER['REQUEST_TIME_FLOAT']做基准 - 响应体如果很大(比如导出接口返回 MB 级 CSV),别全记,加个长度限制:
substr(json_encode($response), 0, 2048)
为什么 file_put_contents 加 FILE_APPEND 比 fopen+fwrite 更稳妥
file_put_contents 是原子写入(底层调用 open(O_APPEND)),并发请求多时不会出现日志错行或覆盖;而手写 fopen 容易漏掉 flock,一并发就串行。
常见错误现象:多条日志挤在同一行,比如 {"uri":"/api/user","time":123}{"uri":"/api/order","time":456},根本没法解析。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 固定用
file_put_contents('/path/to/api.log', $log_line . "\n", FILE_APPEND | LOCK_EX),LOCK_EX虽然稍慢,但能防竞态 - 不要拼接大数组再写——
print_r($GLOBALS, true)可能含资源句柄或递归引用,直接卡死;只取确定结构的字段 - 日志行尽量单行、无换行符,否则
tail -f或 ELK 收集时会断行
Apache / Nginx 下怎么拿到真实客户端 IP 和请求路径
直接读 $_SERVER['REMOTE_ADDR'] 在反代后全是 127.0.0.1 或内网地址;不处理就导致日志里所有请求都显示同一个 IP,失去追踪意义。
使用场景:风控、限流、调试用户行为,都依赖准确来源信息。
实操建议:
- 优先看
$_SERVER['HTTP_X_FORWARDED_FOR'],但必须校验可信代理链——只信任你自己的 Nginx 或 SLB 的 IP 段,不能无条件取第一个值(防伪造) - 路径别用
$_SERVER['REQUEST_URI'],它带 query string;用parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)提纯 - 如果用了 Cloudflare,要读
$_SERVER['HTTP_CF_CONNECTING_IP'],且需在 Web 服务器配置中显式透传(Nginx 加set_real_ip_from)
日志体积失控了怎么办:按天切分 + 自动清理
不切分的话,单个 api.log 几天就上 G,grep 慢、vim 打不开、磁盘爆满都是分分钟的事。
性能影响:每次写日志都 file_put_contents 到大文件末尾,PHP 会反复 fseek,IO 延迟明显上升。
实操建议:
- 文件名带上日期:
/path/to/api-2024-06-15.log,每天凌晨用date('Y-m-d')动态生成 - 清理别靠 crontab 删除旧文件——万一脚本挂了就积压;用
glob('/path/to/api-*.log')在写日志前扫描,删掉filemtime超过 7 天的 - 别用
gzcompress实时压缩日志——CPU 占用高,且压缩失败会导致整条日志丢失;等轮转后再用系统gzip批量处理
最麻烦的其实是日志格式统一——不同接口用不同字段名(req_time / duration_ms / cost),后面查起来得写三段正则。一开始定好字段,比后期清洗省十倍力气。











