This article will explain the usage of the dot-log component within DotKernel, Zend Expressive or in a project that uses Zend Service Manager.
Since dot-log extends zendframework/zend-log this tutorial mostly compatible with zend-log as well.
For a more detailed documentation about the zend-log visit the zend-log documentation.
Adding The Config Provider
- Enter config/config.php
- If there is no entry for the config provider below, add it:
- Make sure it is added before with the Application-Specific components, eg.:
- Open the
- In the dependencies section you will see an absctract factory (
- This class responds to “selectors” instead of class names
- Instead of requesting the
Zend\Log\Logger::classfrom the container,
dot-log.my_loggershould be requested (or just
my_loggerif using zend-log)
- In the dependencies section you will see an absctract factory (
- Next, create a log.global.php file within /config/autoload
- return an empty array for start
Configuring the logger
For compatibility between components and for the better understanding of this tutorial the name for the created logger will be my_logger.
The logger name is the developer’s choice and should reflect its purpose (eg.: db_error_logger – a logger that only writes the error messages in db).
Create a key-value pair, the key should be dot-log (or log if using zend-log) and the value should be an empty array.
In the newly created value add a key loggers, and the value should be an array with the key my_logger and an empty array as the value.
At this point your log.global.php should look like this:
return [ 'dot_log' => [ 'loggers' => [ 'my_logger' => [ ] ], ], ];
For this logger to actually log somewhere a writer is required, otherwise the log command will be received, but the logger will have no place to write the message in.
The next step will show you how to configure writing to a specific file.
Configuring the writer(s)
Loggers must have at least one writer.
A writer is an object that inherits from
Zend\Log\Writer\AbstractWriter. A writer’s responsibility is to record log data to a storage backend. (from zend-log’s writer documentation)
Writing to a file (stream)
It is possible separate logs into multiple files using writers and filters. For example warnings.log, errors.log, all_messages.log.
In this example all the log messages will be written in one file.
- In the my_logger key insert an empty array on key writers
- The writers will all be used when writing logs
- The following is the simplest example to write anything to /data/logs/dk.log
return [ 'dot_log' => [ 'loggers' => [ 'my_logger' => [ 'writers' => [ 'FileWriter' => [ 'name' => 'FileWriter', 'priority' => \Zend\Log\Logger::ALERT, // this is equal to 1 'options' => [ 'stream' => __DIR__.'/../../data/logs/dk.log', ], ], ], ] ], ], ];
The FileWriter key is optional, otherwise the writers array would be enumerative instead of associative.
The writer name key is a developer-provided name for that writer, the writer name key is mandatory.
The writer priority key is not affecting the errors that are written, it is a way to organize writers, for example:
- 1 – FILE
- 2 – SQL
- 3 – E-mail
It is the most important to write in the file, the sql or e-mail are more probably fail because the servers can be external and offline, the file is on the same server.
The writer priority key is optional.
To write into a file the key stream must be present in the writer options array. This is required only if writing into streams/files.
For more examples see the zend-log streams:
- Writing to Streams
- Writing to Databases
- Writing to FirePHP
- Writing to ChromePHP
- Writing to Mail
- Writing to MongoDB
- Writing to Syslog
- Writing to Zend Monitor
(Optional) Configuring the Filters
A filter prevents a message from being written to the log. (from zend-log filters documentation)
As per PSR-3 document.
The log levels are: emergency (0), alert (1), critical (2), error (3), warn (4), notice (5), info (6), debug (7) (in order of priority/importance)
Although the plain Logger in Zend Log is not fully compatible with PSR-3, it provides a way to log all of these message types.
Starting from the basic writer configuration, several configurations will be added for extra functionality.
<?php return [ 'dot_log' => [ 'loggers' => [ 'my_logger' => [ 'writers' => [ 'FileWriter' => [ 'name' => 'FileWriter', 'priority' => \Zend\Log\Logger::ALERT, 'options' => [ 'stream' => __DIR__.'/../../data/logs/dk.log', 'filters' => [ 'allMessages' => [ 'name' => 'priority', 'options' => [ 'operator' => '>=', 'priority' => \Zend\Log\Logger::EMERG, ] ], ], ], ], // Only warnings 'OnlyWarningsWriter' => [ 'name' => 'stream', 'priority' => \Zend\Log\Logger::ALERT, 'options' => [ 'stream' => __DIR__.'/../../data/logs/warnings_only.log', 'filters' => [ 'warningOnly' => [ 'name' => 'priority', 'options' => [ 'operator' => '==', 'priority' => \Zend\Log\Logger::WARN, ], ], ], ], ], // Warnings and more important messages 'WarningOrHigherWriter' => [ 'name' => 'stream', 'priority' => \Zend\Log\Logger::ALERT, 'options' => [ 'stream' => __DIR__.'/../../data/logs/important_messages.log', 'filters' => [ 'importantMessages' => [ 'name' => 'priority', 'options' => [ // note, the smaller the priority, the more important is the message // 0 - emergency, 1 - alert, 2- error, 3 - warn. .etc 'operator' => '<=', 'priority' => \Zend\Log\Logger::WARN, ], ], ], ], ], ], ], ], ], ];
As in the writer configuration, the developer can optionally use keys for associating the filters with a name.
IMPORTANT NOTE: the operator for more important messages is <=, this is because the number representation is smaller for a more important message type.
The filter added on the first writer is equal to not setting a filter, but it was been added to illustrate how to explicitly allow all messages.
It was added opposite to the others just to demonstrate the other operator is also an option.
More examples on filters: https://zendframework.github.io/zend-log/filters/
(Optional) Configuring the Formatter
When using dot-log or zend-log, the logged value is not limited to a string. Arrays can be logged as well.
For a better readability, these arrays can be serialized.
Zend Log provides String formatting, XML, JSON and FirePHP formatting.
The formatter accepts following parameters:
- name – the formatter class (it must implement Zend\Log\Formatter\FormatterInterface)
- options – options to pass to the formatter constructor if required
The following formats the message as JSON data:
'formatter' => [ 'name' => \Zend\Log\Formatter\Json::class, ],
Below an example which:
- The log is used through dot-log
- The logger name is my_logger
- Writes to file: data/logs/dk.log
- Explicitly allows all the messages to be written
- Formats the message as JSON
The key elements are bold.
<?php return [ 'dot_log' => [ 'loggers' => [ 'my_logger' => [ 'writers' => [ 'FileWriter' => [ 'name' => 'FileWriter', 'priority' => \Zend\Log\Logger::ALERT, 'options' => [ 'stream' => __DIR__.'/../../data/logs/dk.log', // explicitly log all messages 'filters' => [ 'allMessages' => [ 'name' => 'priority', 'options' => [ 'operator' => '>=', 'priority' => \Zend\Log\Logger::EMERG, ], ], ], 'formatter' => [ 'name' => \Zend\Log\Formatter\Json::class, ], ], ], ], ], ], ], ];
Basic usage of the logger is illustraded below.
The messages are written to see which logs are written and which are not written.
$logger = $container->get('dot-log.my_logger'); /** @var Logger $logger */ $logger->emerg('0 EMERG'); $logger->alert('1 ALERT'); $logger->crit('2 CRITICAL'); $logger->err('3 ERR'); $logger->warn('4 WARN'); $logger->notice('5 NOTICE'); $logger->info('6 INF'); $logger->debug('7 debug'); $logger->log(Logger::NOTICE, 'NOTICE from log()');
This article will be continued in a different article that treats the error handling in middleware applications.