php怎么记录日志信息_php error_log与自定义日志类【监控】

1次阅读

Error_log() 默认写入 php 配置的 error_log 路径而非自定义文件,仅当显式传入文件路径或使用模式 3/4 时才改变行为;自定义日志需处理并发、换行、权限、轮转及监控对接。

php怎么记录日志信息_php error_log与自定义日志类【监控】

error_log() 写日志时为什么没出现在预期文件里

默认情况下 error_log() 不写入自定义文件,而是走 PHP 的错误日志配置路径(error_log ini 指令值),常被误以为“不生效”。它只在参数明确指定文件路径时才绕过全局配置。

  • 不带参数或传 false:写入 error_log ini 设置的路径(如 apacheerror.log
  • 字符串路径(如 '/var/log/myapp.log'):直接写入该文件,但需确保 PHP 进程有写权限且目录存在
  • 3(整数):等价于 error_log($msg, 3, $file),是写文件的显式模式
  • 常见坑:路径用相对路径(如 'logs/app.log'),实际写到 webserver 工作目录(未必是项目根目录)

用 file_put_contents() 自建日志函数要注意什么

error_log() 更可控,但得自己处理并发、格式、换行和权限。PHP 默认不保证文件写入原子性,高并发下易丢日志或内容错乱。

  • 必须加 FILE_APPEND | LOCK_EX 标志:file_put_contents($file, $line, FILE_APPEND | LOCK_EX)
  • 每条日志末尾手动加 n,否则所有内容挤在一行
  • 避免频繁打开/关闭文件:不要在循环里反复调用;单次请求多次写入可接受,但高频服务建议用缓冲+定时刷盘或切到 syslog
  • 注意时区:date('Y-m-d H:i:s') 依赖 date_default_timezone_set(),否则可能用 UTC 时间,和系统日志对不上

自定义日志类里要不要支持 rotate(日志轮转)

线上环境必须支持,否则单个日志文件会无限增长,直到磁盘写满或触发运维告警。PHP 本身不提供自动 rotate,得自己判断并归档。

  • 简单方案:每天检查 filemtime($log_file),若跨天则重命名成 app.log.2024-05-20,再新建空文件
  • 更稳做法:用 is_file($log_file) && filesize($log_file) > 10 * 1024 * 1024 判断是否超 10MB,再 rotate
  • 别用 rename() 直接覆盖旧归档名——如果同名已存在,会被覆盖丢失;应先 if (is_file($backup)) { unlink($backup); }
  • rotate 操作本身要尽量轻量,避免在每次写日志时都检查,可设为“首次写入当天第一条日志时检查”

监控场景下 error_log() 和自定义类哪个更适合

监控需要稳定、可采集、低侵入——error_log() 写 syslog(error_log($msg, 4))最省事;自定义类适合结构化日志(如 json),但得额外对接日志采集器。

立即学习PHP免费学习笔记(深入)”;

  • error_log($msg, 4) 把日志发给系统 syslog,linux 下自动进 /var/log/messages/var/log/syslog,Logstash/Filebeat 天然能抓
  • 自定义类输出 JSON 格式(如 ['level'=>'warn','msg'=>'timeout','time'=>...]),方便 elk 做字段提取,但需确保无非法字符(如未转义的双引号)
  • 避免在日志里拼接敏感数据(如 $_SERVER['HTTP_AUTHORIZATION']),监控系统可能长期留存,合规风险高
  • 如果用 Monolog 等第三方库,注意其默认 handler 在 CLI 和 FPM 下行为不同(比如 StreamHandler 可能复用 fd,FPM worker 复用时出问题)

日志路径权限、并发写入、rotate 时机、输出格式与监控链路的衔接——这几个点不提前想清楚,上线后查问题反而更费劲。

text=ZqhQzanResources