stubbles / log
Stubbles Log 提供了写入日志数据的支持。
Requires
- php: ^7.0
Requires (Dev)
- bovigo/assert: ^2.0
- bovigo/callmap: ^3.0
- mikey179/vfsstream: ^1.6
- phpunit/phpunit: ^5.4
- stubbles/ioc: ^8.0
- stubbles/reflect: ^8.0
Suggests
- stubbles/ioc: To use the IoC bindings so that Logger instances are created automatically.
README
提供与业务相关的日志数据的写入支持。对于更技术性的日志记录方法,请检查符合PSR-3的包。
构建状态
安装
stubbles/log 以 Composer 包的形式分发。要将其安装为包的依赖项,请使用以下命令
composer require "stubbles/log": "^6.0"
要求
stubbles/log 至少需要 PHP 7.0。
用法
在您想写入日志的类中,简单地将对 stubbles\log\Logger
的依赖项创建好,并使用此实例来写入日志数据
namespace example; use stubbles\log\Logger; class ExampleClass { private $logger; /** * @param Logger $logger */ public function __construct(Logger $logger) { $this->logger = $logger; } public function doSomething() { // maybe some code here that does something $this->logger->createLogEntry('myapp') ->addData('foo', 'bar', 'baz') ->log(); // maybe some code afterwards that does something } }
在 doSomething()
方法中,我们使用日志记录器实例来创建日志条目,并将其添加到其中。我们可以一次性完成,也可以添加任意多的 addData()
调用来完成所需的所有数据添加。完成所有要记录的数据添加后,我们调用 log()
方法,它将负责实际的日志记录过程。
传递给 createLogEntry()
的字符串是日志条目应该结束的目标。在实践中的具体含义取决于添加到日志记录器的日志附加器。例如,文件日志附加器将使用该目标创建一个具有此名称的日志文件,在这种情况下是 myapp.log。
延迟记录
有时您想记录数据,但不是所有创建基本日志条目所需的数据都已可用。这就是延迟记录发挥作用的地方。您不是调用 log()
,而是简单地调用 logDelayed()
namespace example; use stubbles\log\Logger; class ExampleClass { private $logger; /** * @param Logger $logger */ public function __construct(Logger $logger) { $this->logger = $logger; } public function doSomething() { // maybe some code here that does something $this->logger->createLogEntry('myapp') ->addData('foo', 'bar', 'baz') ->logDelayed(); // maybe some code afterwards that does something } }
这将导致延迟记录数据,它将在 PHP 进程关闭时最新记录,因此如果您在 Web 环境中,这很可能是在请求结束时。现在,所有预填充日志条目的数据都可以由日志条目工厂更新。
日志条目工厂
目的
当创建新的日志数据时,您不希望在每个应该记录数据的地方都关心标准日志数据。日志条目工厂负责创建预先填充数据的日志条目。这可以是时间戳、会话 ID 或您想在所有日志条目中拥有的任何其他数据。然后,特定的日志数据创建只需关心添加特定的日志数据。
使用时间戳创建日志条目
日志数据的常见用途是第一个字段包含创建特定日志数据时的时间戳。为此,stubbles\log\entryfactory\TimedLogEntryFactory
创建具有当前时间戳(格式为 Y-m-d H:i:s)作为第一个字段的日志条目。
创建非预填充的日志条目
有时需要创建非预填充的日志条目,在写入日志数据后仅包含业务日志数据,例如在测试用例中。这就是 stubbles\log\entryfactory\EmptyLogEntryFactory
可以使用的时候。
自定义日志条目工厂
如果提供的日志条目工厂不能满足您的需求,您可以创建自己的日志条目工厂。为此,您必须扩展 stubbles\log\entryfactory\LogEntryFactory
类,它包含两个方法
public function create($target, Logger $logger) public function recreate(LogEntry $logEntry, Logger $logger)
create()
方法应创建新的 stubbles\log\LogEntry
实例。需要将两个参数传递给 stubbles\log\LogEntry
构造函数。创建后,你的实现可以向所有日志条目添加任何想要的日志数据。在预填充创建的日志条目实例后,必须返回该实例。
对于所有延迟记录的日志条目,都会调用 recreate()
方法。如果在日志条目的初始创建过程中没有所有数据可用,此功能非常有用,现在可以将日志条目中的所有数据替换为现在最可能可用的数据。如果你的实现没有这样的用例,则不需要实现此方法,基类已经有一个基本的实现,该方法简单地返回给定的 LogEntry 实例。
日志追加器
目的
stubbles\log\Logger
类本身并不知道日志数据是如何存储的。存储日志数据是 stubbles\log\appender\LogAppender
的任务。日志追加器接收日志数据并将其写入目标。目标可以是文件、数据库或任何适合日志数据的其他任何东西。作为一个具体的例子,stubbles/log 提供了一个 stubbles\log\appender\FileLogAppender
,它将日志数据写入硬盘上的日志文件。
文件日志追加器
文件日志追加器接收日志数据并将其写入日志文件。如果未指定其他追加器,并且在不进行任何更改的情况下使用日志绑定模块(见下文),它是 stubbles/log 默认使用的追加器。
它将日志文件写入特定的目录。对于默认配置,这意味着使用绑定常量 stubbles.log.path 指定的目录。如果目录不存在,则事先创建它。新创建的目录权限为 0700。如果您想要不同的权限,则需要指定一个名为 stubbles.log.filemode 的常量绑定,并指定权限值。
日志文件的名称将包括日志条目目标,以及当前日期(格式为 YYYY-MM-DD)和附加的文件扩展名 .log。假设今天是 2012 年 2 月 4 日,并创建以下日志数据:
$logger->create('example')->addData('foo','bar')->log();
这将创建一个名为 example-2012-02-04.log 的日志文件,其中至少包含内容 foo|bar。
内存日志追加器
内存日志追加器可用于测试创建日志数据的类。它不将日志条目写入文件或数据库,而是简单地将它们保留在内存中,以便稍后检索以对写入的日志数据进行断言。假设我们有以下类:
namespace example; use stubbles\log\Logger; class ExampleClass { private $logger; /** * @param Logger $logger */ public function __construct(Logger $logger) { $this->logger = $logger; } public function doSomething() { ... $this->logger->createLogEntry('myapp') ->addData('foo', 'bar', 'baz') ->log(); ... } }
我们如何确保创建正确的日志数据,例如在测试中?答案是使用内存日志追加器
public function testLogging() { $logger = new Logger(new EmptyLogEntryFactory()); $memoryLogAppender = new MemoryLogAppender(); $logger->addLogAppender($memoryLogAppender); $exampleClasss = new ExampleClass($logger); $exampleClass->doSomething(); $this->assertEquals(1, $memoryLogAppender->countLogEntries('myapp')); $this->assertEquals( ['foo', 'bar', 'baz'], $memoryLogAppender->getLogEntryData('myapp', 0) ); }
内存日志追加器提供三种方法来检查已记录的数据
countLogEntries($target)
返回给定目标的创建的日志条目数量。
getLogEntryData($target, $position)
返回给定目标的已记录数据作为数组。位置表示日志条目写入此目标的顺序。如果有两个针对目标的 myapp 的条目,第一个可以在位置 0 找到,第二个可以在位置 1 找到。
getLogEntries($target)
返回给定目标的全部 stubbles\log\LogEntry
实例列表。
自定义日志追加器
可以通过实现 stubbles\log\appender\LogAppender
接口来创建其他日志追加器。此接口包含两个方法
append(LogEntry $logEntry); finalize();
虽然 append(LogEntry $logEntry)
接收日志条目,日志追加器可以随意处理它。当 PHP 进程结束时调用 finalize()
方法,这意味着在 Web 环境中的请求结束。finalize()
方法的目的是执行之前无法完成的任何必要的持久化操作。
可以通过addLogAppender()
方法将日志附加器添加到具体的stubbles\log\Logger
实例。
$myLogAppender = new MyLogAppender('/path/to/dir'); $logger->addLogAppender($myLogAppender);
与来自stubbles/ioc的Stubbles应用的集成
只需将stubbles\log\ioc\Logfiles
绑定模块添加到由您的应用程序类返回的绑定列表中。
namespace example; use stubbles\App; class MyApplication extends App { /** * returns a list of binding modules used to wire the object graph * * @return array */ public static function __bindings() { return [ new Logfiles(), new StuffRequiredForExampleApplicationBindingModule() ]; } // application methods here }
日志绑定模块提供了三种方式来进一步配置日志的创建方式。
createEntriesWith($logEntryFactory)
接受一个类名或实例,用作日志条目工厂,以代替默认设置。如果不进行更改,默认使用stubbles\log\entryfactory\TimedLogEntryFactory
。loggerProvidedBy($loggerProvider)
将默认的日志实例提供者更改为提供的类或实例。- 如果希望完全自由地命名日志路径,可以使用
writeTo($logPath)
。您可以使用此方法将stubbles.log.path常量绑定到任何您喜欢的路径,例如/var/log/yourapp。