Adding the config provider
- Open
config/config.php. - If there's no entry for the dot-log config provider, add
\Dot\Log\ConfigProvider::class. - Make sure it's added before application-specific components, e.g.
Frontend\App\ConfigProvider::class,Admin\App\ConfigProvider::class,MyProject\ConfigProvider::class. - Inside
Dot\Log\ConfigProvider, the dependencies section registers an abstract factory,LoggerAbstractServiceFactory::class. This class responds to "selectors" instead of class names - instead of requestingZend\Log\Logger::classfrom the container, you requestdot-log.my_logger(or justmy_loggerif using zend-log). - Create a
log.global.phpfile within/config/autoload, returning an empty array to start.
Configuring the logger
For this tutorial, the created logger is named my_logger (the name is the developer's choice and should reflect its purpose, e.g. db_error_logger).
In log.global.php:
- Add a top-level key
dot-log(orlogif using zend-log) with an array value. - Inside it, add a
loggerskey. - Inside that, add the logger name key (
my_logger) with an empty array.
For the logger to actually log somewhere, a writer is required - without one, log calls are received but there's nowhere to write the message.
Configuring the writer(s)
Loggers must have at least one writer.
A writer is an object that inherits from Zend\Log\Writer\AbstractWriter, responsible for recording log data to a storage backend (see the zend-log writer documentation).
It's possible to separate logs into multiple files using writers and filters (e.g. warnings.log, errors.log, all_messages.log).
In the simplest example, all log messages are written to one file, e.g. /data/logs/dk.log, under a writers key inside my_logger.
Notes on writer configuration:
- The writer key name (e.g.
FileWriter) is optional - otherwise the writers array would be enumerative instead of associative. - The writer's
namekey is a developer-provided name for that writer and is mandatory. - The writer's
prioritykey doesn't affect which errors get written - it's only a way to organize writers (e.g. 1 - FILE, 2 - SQL, 3 - E-mail), reflecting that writing to a file is the most reliable since SQL or e-mail servers can be external and offline. The priority key is optional. - To write to a file, the
streamkey must be present in the writer'soptionsarray (required only when writing to streams/files).
More writer examples: Streams, Databases, FirePHP, ChromePHP, Mail, MongoDB, Syslog, Zend Monitor.
(Optional) Configuring the filters
A filter prevents a message from being written to the log (see the zend-log filters documentation).
Per PSR-3, the log levels, in order of priority/importance, are:
| Level | Priority number |
|---|---|
| emergency | 0 |
| alert | 1 |
| critical | 2 |
| error | 3 |
| warn | 4 |
| notice | 5 |
| info | 6 |
| debug | 7 |
Although the plain Logger in Zend Log is not fully PSR-3 compatible, it provides a way to log all of these message types.
The developer can optionally use keys to name filters.
Important: the operator for "more important" messages is <=, because a smaller number represents a more important message.
More on filters: zend-log filters documentation.
(Optional) Configuring the formatter
The logged value isn't limited to a string - arrays can be logged too, and for readability they can be serialized. Zend Log provides String, XML, JSON and FirePHP formatting.
The formatter config accepts:
name- the formatter class (must implementZend\Log\Formatter\FormatterInterface)options- options passed to the formatter constructor, if required
More on formatters: Simple, JSON, XML, FirePHP.
Full example (described)
A complete configuration, as described in the article, does the following:
- Uses the log through dot-log
- Names the logger my_logger
- Writes to file: data/logs/dk.log
- Explicitly allows all messages to be written
- Formats the message as JSON
Usage
Basic usage of the logger:
use Zend\Log\Logger;
$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()');
Frequently Asked Questions
How do I register dot-log's config provider? +
In config/config.php, add `\Dot\Log\ConfigProvider::class` if it's not already there, making sure it is added before application-specific components such as Frontend\App\ConfigProvider or Admin\App\ConfigProvider.
How is a logger retrieved from the container instead of using the plain class name? +
Dot\Log\ConfigProvider registers an abstract factory, LoggerAbstractServiceFactory, that responds to "selectors" instead of class names. Instead of requesting Zend\Log\Logger::class from the container, you request dot-log.my_logger (or just my_logger if using zend-log).
What is a writer, and how many does a logger need? +
A writer is an object that inherits from Zend\Log\Writer\AbstractWriter and is responsible for recording log data to a storage backend. Loggers must have at least one writer, and the writer's "name" key is mandatory while its "priority" key is optional and only used to organize writers, not to affect which errors get written.
What does a filter do, and how are log levels ordered? +
A filter prevents a message from being written to the log. Per PSR-3, the log levels in order of priority/importance are emergency (0), alert (1), critical (2), error (3), warn (4), notice (5), info (6), and debug (7) - the operator for "more important" messages is `<=` because a smaller number represents a more important message.
What does the formatter configuration control? +
The formatter accepts a "name" (a class implementing Zend\Log\Formatter\FormatterInterface) and "options" to pass to that formatter's constructor. Zend Log provides String, XML, JSON and FirePHP formatting, and arrays can be serialized this way for better readability.
How do you actually write log messages once the logger is configured? +
Fetch the logger from the container, e.g. `$logger = $container->get('dot-log.my_logger');`, then call methods such as emerg(), alert(), crit(), err(), warn(), notice(), info(), debug(), or the generic log(Logger::NOTICE, 'message').