PHP Monolog 教程展示了如何使用 Monolog 在 PHP 中进行日志记录。
记录
日志记录是将信息写入日志文件的过程。 日志文件包含有关在操作系统,软件或通信中发生的各种事件的信息。
记录目的
完成记录是出于以下目的:
- 信息收集
- 故障排除
- 产生统计数据
- 审计
- 性能分析
记录不仅限于识别软件开发中的错误。 它还可用于检测安全事件,监视策略违规,在出现问题时提供信息,查找应用瓶颈或生成使用情况数据。
要记录的事件
应记录的事件包括输入验证失败,认证和授权失败,应用错误,配置更改以及应用启动和关闭。
不记录的事件
不应记录的事件包括应用源代码,会话标识值,访问令牌,敏感的个人数据,密码,数据库连接字符串,加密密钥,银行帐户和持卡人数据。
记录最佳做法
以下是一些日志记录最佳做法:
- 日志记录应该有意义。
- 日志应包含上下文。
- 日志应保持平衡; 它不应包含过多或过多的信息。
- 记录消息应该是人类可以理解的,并且可以被机器解析。
- 日志记录应在不同级别进行结构化和完成。
- 日志应适应开发和生产。
- 记录更复杂的应用应产生几个日志文件。
PHP Monolog
Monolog 是流行的 PHP 日志记录库。 它允许将日志发送到文件,套接字,收件箱,数据库和各种 Web 服务。 它实现了 PSR-3 接口。
$ composer req monolog/monolog
我们用 Composer 安装 Monolog。
Monolog 结构
Monolog 记录器实例具有通道(名称)和处理器的栈。 处理器负责将消息保存到文件,数据库或将其发送到邮件。
记录的消息在处理器栈中传播。 最后一个处理器首先执行。 消息的进一步传播由bubble
变量控制,该变量默认设置为true
。
消息记录是一条将要写入日志的信息。 消息记录包含以下部分:
键 | 类型 | 描述 |
---|---|---|
info |
string |
日志消息。 |
level |
integer |
日志消息的严重性。 |
level_name |
string |
日志级别的字符串表示形式。 |
context |
array |
随消息的构造传递任意数据。 |
channel |
string |
此消息被登录到的频道。 |
datetime |
Monolog /DateTimeImmutable |
消息记录的日期和时间。 |
extra |
array |
处理器可在其中放置其他数据的占位符数组。 |
处理器是可用于处理日志消息的任何 PHP 可调用对象。 它可以向记录中添加一些额外的数据。
context
是数组数据,其中包含的附加信息不太适合主字符串。 上下文是日志记录方法的参数(例如info()
或warn()
)。
格式化程序用于格式化消息记录。
Monolog 日志级别
日志记录级别用于按紧急程度对日志消息进行分类。 Monolog 具有以下日志级别:
DEBUG
- 详细的调试信息INFO
- 有趣的事件NOTICE
- 正常但重要的事件WARNING
- 并非错误的特殊情况ERROR
- 不需要立即采取措施的运行时错误CRITICAL
- 关键条件ALERT
- 必须立即采取措施的事件EMERGENCY
- 紧急事件
日志级别较低的处理器将不处理不太严重的日志。 通过将日志级别设置为ERROR
,我们将获得ERROR
级别及更高级别的消息。
每个处理器都指定了一个日志级别; 默认值为DEBUG
。 为了产生具有特定日志级别的消息,我们有包括info()
,warn()
,error()
和critical()
的方法。 由于 Monolog 早于 PSR-3,因此它包含重复的方法(例如addInfo()
或addWarning()
)。
Monolog 简单示例
在第一个示例中,我们使用Streamhandler
将消息记录到文件中。
simple.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
$logger = new Logger('main');
$logger->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG));
$logger->info('First message');
该示例将信息消息写入logs/app.log
文件。
$logger = new Logger('main');
创建了一个名为main
的新记录器。
$logger->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG));
我们使用pushHandler()
将StreamHandler
添加到记录器。 处理器以DEBUG
严重性将消息写入指定的文件。
$logger->info('First message');
我们使用info()
方法记录一条信息消息。
$ cat logs\app.log
[2019-05-15 15:49:48] main.INFO: First message [] []
这是书面信息。 日志消息以当前日期时间开头。 后面是日志通道名称和级别。 然后是消息记录。 两对方括号是我们可以指定上下文和额外数据的位置。 我们可以使用 Monolog 格式化程序自定义此输出。
Monolog 控制台日志记录
我们可以将日志消息写入终端。
console_log.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('stderr');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::WARNING));
$logger->warn('A warning message');
我们通过向StreamHandler
指定php://stderr
来写入控制台。
Monolog 上下文数组
Monolog 上下文数组允许在用户级级别将信息添加到消息记录中。
context_array.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
$logger = new Logger('main');
$logger->pushHandler(new StreamHandler('php://stderr'));
$logger->info('Information message', ['user' => get_current_user()]);
info()
方法的第二个参数是上下文数组。 我们将当前用户添加到消息中。
$ php context_array.php
[2019-05-15 15:37:56] main.INFO: Information message {"user":"Jano"} []
这是输出。
Monolog 记录器处理器栈
我们可以将多个处理器添加到栈中。 最后添加的处理器将首先执行。
handler_stack.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
$main = new Logger('main');
$main->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log'));
$main->pushHandler(new StreamHandler('php://stdout', $level = Logger::DEBUG,
$bubble = true));
$main->info('Information message');
在示例中,我们有两个记录器处理器:一个文件和一个控制台处理器。 如果将$bubble
更改为false
,则消息将不会写入logs/app.log
文件。
Monolog 定制处理器
可以向pushProcessor()
添加自定义处理器。
custom_processor.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
$logger = new Logger('main');
$logger->pushHandler(new StreamHandler('php://stderr'));
$logger->pushProcessor(function ($record) {
$record['extra']['user'] = get_current_user();
return $record;
});
$logger->info('Information message');
在示例中,我们向处理器中的消息记录添加了一些额外的信息。 根据文档,上下文和额外数据之间的区别在于上下文是在用户区域中提供的,而额外数据仅是内部的,可以由处理器填充。
$ php custom_processor.php
[2019-05-15 17:24:48] main.INFO: Information message [] {"user":"Jano"}
额外的信息将添加到输出的末尾。
Monolog JsonFormatter
JsonFormatter
以 JSON 格式写入记录。
json_formatter.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Formatter\JsonFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
$logger = new Logger('main');
$formatter = new JsonFormatter();
$stream = new StreamHandler(__DIR__ . '/logs/app-json.log');
$stream->setFormatter($formatter);
$logger->pushHandler($stream);
$logger->info('Information message', ['user' => get_current_user()]);
该示例使用JsonFormatter
将信息消息以 JSON 格式写入文件。
$ cat logs\app-json.log
{"message":"Information message","context":{"user":"Jano"},"level":200,"level_name":"INFO",
"channel":"main","datetime":{"date":"2019-05-15 17:37:40.433222","timezone_type":3,
"timezone":"Europe/Berlin"},"extra":[]}
这是记录的消息。
Monolog LineFormatter
LineFormatter
将日志记录格式化为单行字符串。
line_format.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\ProcessIdProcessor;
$output = "[%datetime%] %channel%.%level_name%: %message% %context.user%\n";
$formatter = new LineFormatter($output);
$streamHandler = new StreamHandler('php://stdout');
$streamHandler->setFormatter($formatter);
$logger = new Logger('main');
$logger->pushHandler($streamHandler);
$logger->info('Information message from', ['user' => get_current_user()]);
在示例中,我们使用LineFormatter
自定义消息记录。
$output = "[%datetime%] %channel%.%level_name%: %message% %context.user%\n";
$formatter = new LineFormatter($output);
我们创建一个自定义记录消息。 它包含日期时间,频道名称,级别名称,消息和上下文数据。
$streamHandler->setFormatter($formatter);
我们使用setFormatter()
将格式化程序添加到处理器中。
$ php line_format.php
[2019-05-15 17:43:36] main.INFO: Information message from Jano
这是一个示例输出。
Monolog 邮件日志消息
可以使用SwiftMailerHandler
发送电子邮件
$ composer req swiftmailer/swiftmailer
对于此示例,我们需要安装swiftmailer/swiftmailer
包。
注意:Gmail 不是理想的测试应用。 我们应该使用诸如 Mailtrap 或 Mailgun 之类的在线服务,或者使用由网络托管公司提供的 SMTP 服务器。
在我们的示例中,我们使用 Mailtrap 服务。
mail_log.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Handler\SwiftMailerHandler;
$transporter = new Swift_SmtpTransport('smtp.mailtrap.io', 2525, 'tls');
$transporter->setUsername('3178491df14b6d');
$transporter->setPassword('7c1d6fa59a5v08');
$mailer = new Swift_Mailer($transporter);
$message = new Swift_Message('Critical message');
$message->setFrom(['approot@example.com' => 'App root']);
$message->setTo(['support@example.com' => 'Support']);
$logger = new Logger('main');
$logger->pushHandler(new SwiftMailerHandler($mailer, $message, Logger::CRITICAL));
$logger->critical('Could not connect to the database');
在示例中,我们使用SwiftMailerHandler
将消息记录发送到邮件收件箱。
$transporter = new Swift_SmtpTransport('smtp.mailtrap.io', 2525, 'tls');
$transporter->setUsername('3178491df14b6d');
$transporter->setPassword('7c1d6fa59a5v08');
使用 Mailtrap 连接详细信息,我们构建了传输器。
$mailer = new Swift_Mailer($transporter);
创建了Swinf_Mailer
。
$message = new Swift_Message('Critical message');
$message->setFrom(['approot@example.com' => 'App root']);
$message->setTo(['support@example.com' => 'Support']);
创建了Swift_Message
。 它包含从到字段。
$logger = new Logger('main');
$logger->pushHandler(new SwiftMailerHandler($mailer, $message, Logger::CRITICAL));
$logger->critical('Could not connect to the database');
我们将SwiftMailerHandler
添加到记录器,并使用critical()
创建关键消息。
您可能也对以下相关教程感兴趣: PHP Rakit 验证教程, PHP PDO 教程, PHP 教程或列出所有 PHP 教程。
在本教程中,我们使用 Monolog 在 PHP 中进行日志记录。