PHP日志系统从入门到精通日志是排查问题的第一手段。好的日志系统能让你快速定位线上问题。PHP内置的error_log函数可以写日志但生产环境需要更完善的日志方案。从最简单的error_log开始。它可以直接写文件、发送邮件或写入系统日志。php// PHP内置日志error_log(用户登录成功);// 写日志到指定文件error_log(数据库连接失败, 3, /var/log/app.log);// 发送邮件// error_log(严重错误, 1, adminexample.com);// 写入系统日志error_log(应用启动, 4);?用Monolog库可以实现结构化的日志记录支持多种处理器和格式phprequire vendor/autoload.php;use Monolog\Logger;use Monolog\Handler\StreamHandler;use Monolog\Handler\RotatingFileHandler;use Monolog\Handler\FirePHPHandler;use Monolog\Formatter\LineFormatter;use Monolog\Processor\IntrospectionProcessor;use Monolog\Processor\WebProcessor;use Monolog\Processor\MemoryUsageProcessor;// 创建日志通道$log new Logger(app);// 文件处理器每天轮转保留30天$rotating new RotatingFileHandler(/var/log/app.log, 30, Logger::WARNING);$formatter new LineFormatter([%datetime%] %channel%.%level_name%: %message% %context% %extra%\n,Y-m-d H:i:s);$rotating-setFormatter($formatter);$log-pushHandler($rotating);// 调试日志处理器$debugHandler new StreamHandler(/var/log/app_debug.log, Logger::DEBUG);$debugFormatter new LineFormatter(null, null, true, true);$debugHandler-setFormatter($debugFormatter);$log-pushHandler($debugHandler);// 处理器$log-pushProcessor(new IntrospectionProcessor());$log-pushProcessor(new WebProcessor());$log-pushProcessor(new MemoryUsageProcessor());// 记录日志$log-debug(调试信息, [query SELECT * FROM users]);$log-info(用户登录, [user_id 123, ip 192.168.1.1]);$log-warning(磁盘空间不足, [free_space 500MB]);$log-error(数据库连接失败, [error Connection refused]);$log-critical(服务不可用);?结构化的日志记录格式便于分析和查询phpclass StructuredLogger{private string $logDir;private string $channel;private array $processors [];public function __construct(string $channel, string $logDir /var/log/app){$this-channel $channel;$this-logDir rtrim($logDir, /);if (!is_dir($this-logDir)) mkdir($this-logDir, 0755, true);}public function debug(string $message, array $context []): void{$this-log(debug, $message, $context);}public function info(string $message, array $context []): void{$this-log(info, $message, $context);}public function warning(string $message, array $context []): void{$this-log(warning, $message, $context);}public function error(string $message, array $context []): void{$this-log(error, $message, $context);}public function critical(string $message, array $context []): void{$this-log(critical, $message, $context);$this-sendAlert($message, $context);}private function log(string $level, string $message, array $context): void{$entry [timestamp date(Y-m-d\TH:i:s.vP),channel $this-channel,level $level,message $message,context $context,extra [pid getmypid(),memory round(memory_get_usage(true) / 1024 / 1024, 2) . MB,uri $_SERVER[REQUEST_URI] ?? cli,method $_SERVER[REQUEST_METHOD] ?? CLI,ip $_SERVER[REMOTE_ADDR] ?? 127.0.0.1,],];$logLine json_encode($entry, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);$logFile $this-logDir . / . $this-channel . - . date(Y-m-d) . .log;file_put_contents($logFile, $logLine . \n, FILE_APPEND | LOCK_EX);}private function sendAlert(string $message, array $context): void{$subject [CRITICAL] . $this-channel . : . substr($message, 0, 100);$body json_encode([message $message, context $context], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);error_log($body, 1, adminexample.com, Subject: $subject\n);}}$log new StructuredLogger(payment);$log-info(支付成功, [order_id ORD-001, amount 99.99]);$log-error(支付失败, [order_id ORD-002, error 余额不足]);?日志级别的使用场景phpclass LogLevelGuide{public static function getExamples(): array{return [debug [desc 详细的调试信息,examples [SQL查询语句和参数,API请求和响应内容,变量值的变化过程,],],info [desc 正常运行的记录,examples [用户登录/注册,订单创建/支付,定时任务执行,],],notice [desc 正常但值得注意的事件,examples [使用了已废弃的API,配置使用了默认值,达到了某个阈值,],],warning [desc 潜在的问题,examples [数据库查询速度超过1秒,磁盘使用率超过80%,重试操作成功,],],error [desc 运行时错误,examples [数据库连接失败,第三方API返回错误,数据验证失败,],],critical [desc 严重错误需要立即处理,examples [主数据库不可用,磁盘空间耗尽,安全漏洞被利用,],],];}}$guide LogLevelGuide::getExamples();foreach ($guide as $level $info) {echo str_pad($level, 10) . : {$info[desc]}\n;foreach ($info[examples] as $ex) {echo - $ex\n;}echo \n;}?日志的集中管理在大项目中很重要。可以用ELKElasticsearch、Logstash、Kibana或Loki来集中收集和分析日志。PHP应用只需要把日志以JSON格式写到文件由Filebeat或Fluentd收集后发送到日志中心。好的日志系统能让线上问题定位变得很容易。关键是要在正确的地方用正确的级别记录日志信息太少不行信息太多同样不行。
PHP日志系统从入门到精通
PHP日志系统从入门到精通日志是排查问题的第一手段。好的日志系统能让你快速定位线上问题。PHP内置的error_log函数可以写日志但生产环境需要更完善的日志方案。从最简单的error_log开始。它可以直接写文件、发送邮件或写入系统日志。php// PHP内置日志error_log(用户登录成功);// 写日志到指定文件error_log(数据库连接失败, 3, /var/log/app.log);// 发送邮件// error_log(严重错误, 1, adminexample.com);// 写入系统日志error_log(应用启动, 4);?用Monolog库可以实现结构化的日志记录支持多种处理器和格式phprequire vendor/autoload.php;use Monolog\Logger;use Monolog\Handler\StreamHandler;use Monolog\Handler\RotatingFileHandler;use Monolog\Handler\FirePHPHandler;use Monolog\Formatter\LineFormatter;use Monolog\Processor\IntrospectionProcessor;use Monolog\Processor\WebProcessor;use Monolog\Processor\MemoryUsageProcessor;// 创建日志通道$log new Logger(app);// 文件处理器每天轮转保留30天$rotating new RotatingFileHandler(/var/log/app.log, 30, Logger::WARNING);$formatter new LineFormatter([%datetime%] %channel%.%level_name%: %message% %context% %extra%\n,Y-m-d H:i:s);$rotating-setFormatter($formatter);$log-pushHandler($rotating);// 调试日志处理器$debugHandler new StreamHandler(/var/log/app_debug.log, Logger::DEBUG);$debugFormatter new LineFormatter(null, null, true, true);$debugHandler-setFormatter($debugFormatter);$log-pushHandler($debugHandler);// 处理器$log-pushProcessor(new IntrospectionProcessor());$log-pushProcessor(new WebProcessor());$log-pushProcessor(new MemoryUsageProcessor());// 记录日志$log-debug(调试信息, [query SELECT * FROM users]);$log-info(用户登录, [user_id 123, ip 192.168.1.1]);$log-warning(磁盘空间不足, [free_space 500MB]);$log-error(数据库连接失败, [error Connection refused]);$log-critical(服务不可用);?结构化的日志记录格式便于分析和查询phpclass StructuredLogger{private string $logDir;private string $channel;private array $processors [];public function __construct(string $channel, string $logDir /var/log/app){$this-channel $channel;$this-logDir rtrim($logDir, /);if (!is_dir($this-logDir)) mkdir($this-logDir, 0755, true);}public function debug(string $message, array $context []): void{$this-log(debug, $message, $context);}public function info(string $message, array $context []): void{$this-log(info, $message, $context);}public function warning(string $message, array $context []): void{$this-log(warning, $message, $context);}public function error(string $message, array $context []): void{$this-log(error, $message, $context);}public function critical(string $message, array $context []): void{$this-log(critical, $message, $context);$this-sendAlert($message, $context);}private function log(string $level, string $message, array $context): void{$entry [timestamp date(Y-m-d\TH:i:s.vP),channel $this-channel,level $level,message $message,context $context,extra [pid getmypid(),memory round(memory_get_usage(true) / 1024 / 1024, 2) . MB,uri $_SERVER[REQUEST_URI] ?? cli,method $_SERVER[REQUEST_METHOD] ?? CLI,ip $_SERVER[REMOTE_ADDR] ?? 127.0.0.1,],];$logLine json_encode($entry, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);$logFile $this-logDir . / . $this-channel . - . date(Y-m-d) . .log;file_put_contents($logFile, $logLine . \n, FILE_APPEND | LOCK_EX);}private function sendAlert(string $message, array $context): void{$subject [CRITICAL] . $this-channel . : . substr($message, 0, 100);$body json_encode([message $message, context $context], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);error_log($body, 1, adminexample.com, Subject: $subject\n);}}$log new StructuredLogger(payment);$log-info(支付成功, [order_id ORD-001, amount 99.99]);$log-error(支付失败, [order_id ORD-002, error 余额不足]);?日志级别的使用场景phpclass LogLevelGuide{public static function getExamples(): array{return [debug [desc 详细的调试信息,examples [SQL查询语句和参数,API请求和响应内容,变量值的变化过程,],],info [desc 正常运行的记录,examples [用户登录/注册,订单创建/支付,定时任务执行,],],notice [desc 正常但值得注意的事件,examples [使用了已废弃的API,配置使用了默认值,达到了某个阈值,],],warning [desc 潜在的问题,examples [数据库查询速度超过1秒,磁盘使用率超过80%,重试操作成功,],],error [desc 运行时错误,examples [数据库连接失败,第三方API返回错误,数据验证失败,],],critical [desc 严重错误需要立即处理,examples [主数据库不可用,磁盘空间耗尽,安全漏洞被利用,],],];}}$guide LogLevelGuide::getExamples();foreach ($guide as $level $info) {echo str_pad($level, 10) . : {$info[desc]}\n;foreach ($info[examples] as $ex) {echo - $ex\n;}echo \n;}?日志的集中管理在大项目中很重要。可以用ELKElasticsearch、Logstash、Kibana或Loki来集中收集和分析日志。PHP应用只需要把日志以JSON格式写到文件由Filebeat或Fluentd收集后发送到日志中心。好的日志系统能让线上问题定位变得很容易。关键是要在正确的地方用正确的级别记录日志信息太少不行信息太多同样不行。