Manual:MonologSpi.php

(Redirected from Manual:MWLoggerMonologSpi)

MediaWiki\Logger\MonologSpi is a service provider interface for use with $wgMWLoggerDefaultSpi that creates Monolog loggers. MonologSpi enables Structured logging, which means you can record an arbitrary array of data with your log events instead of just a string.

Details

edit

Monolog allows a large amount of flexibility in configuring the destination, format and contents of log events. The basic building blocks of a Monolog configuration are:

$wgMWLoggerDefaultSpi = [
	'class' => \MediaWiki\Logger\MonologSpi::class,
	'args' => [ [
		'loggers' => [
			'@default' => [ /* Template for any log channel without explicit config */ ],
			'some-special-log-channel' => [ /*...*/ ],
		],
		'processors' => [ /*...*/ ],
		'handlers' => [ /*...*/ ],
		'formatters' => [ /*...*/ ],
	] ],
];
Loggers
A logger is a named logging channel. The name of the channel is used to determine what configuration to apply to messages sent to that channel.
Since MediaWiki 1.33, if no logger @default is defined, it is defined with the handler @default; if there is no handler @default it is defined as a stream handler to php://stderr with minimum level ERROR (T196906).
Since MediaWiki 1.35.1, a logger configured as [] or false is silenced (T196906).
Processors
A processor adds or modifies contextual information of a log event.
  • Including the Monolog\Processor\PsrLogMessageProcessor handler is recommended to make Monolog expand PSR-3 {name} placeholders in the message body.
  • The MediaWiki provided MediaWiki\Logger\Monolog\WikiProcessor processor will add 'host' => wfHostname(), 'wiki' => wfWikiID(), 'mwversion' => $wgVersion, 'reqId' => \WebRequest::getRequestId() and if running from CLI 'cli_argv' => implode( ' ', $_SERVER['argv'] ) to the log event.
Handlers
Each logger should have one or more handlers attached to it.
  • Monolog\Handler\StreamHandler writes log events to a file or PHP stream.
  • MediaWiki's MediaWiki\Logger\Monolog\LegacyHandler can take the same file or UDP endpoint syntax as used by $wgDebugLogGroups.
Formatters
The formatters normalize and format incoming records for the handlers. If not specified in the config, a default formatter will be selected by the handler.
  • MediaWiki\Logger\Monolog\LegacyFormatter mimics the legacy log message formatting of wfDebug, wfDebugLog, wfLogDBError and wfErrorLog global functions by delegating the formatting to MediaWiki\Logger\LegacyLogger.

Usage

edit

Minimal example

edit

This configuration logs everything to a single file, /var/log/mediawiki/log. The file should be writable by MediaWiki (e. g. sudo mkdir -p /var/log/mediawiki && sudo chown www-data /var/log/mediawiki). Each log entry corresponds to a single line, and the structured data is appended to the message.

$wgMWLoggerDefaultSpi = [
    'class' => '\\MediaWiki\\Logger\\MonologSpi',
    'args' => [ [
        'loggers' => [
            '@default' => [
                'processors' => [ 'wiki', 'psr' ],
                'handlers' => [ 'stream' ]
            ],
        ],
        'processors' => [
            'wiki' => [ 'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor' ],
            'psr' => [ 'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor' ],
        ],
        'handlers' => [
            'stream' => [
                'class' => '\\Monolog\\Handler\\StreamHandler',
                'args' => [ '/var/log/mediawiki/log' ],
                'formatter' => 'line'
            ],
        ],
        'formatters' => [
            'line' => [ 'class' => '\\Monolog\\Formatter\\LineFormatter' ],
        ]
    ] ]
];

Example from the MediaWiki\Logger\MonologSpi PHP doc comments

edit
$wgMWLoggerDefaultSpi = array(
    'class' => '\\MediaWiki\\Logger\\MonologSpi',
    'args' => array( array(
        'loggers' => array(
           '@default' => array(
               'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
               'handlers'   => array( 'stream' ),
           ),
           'runJobs' => array(
               'processors' => array( 'wiki', 'psr', 'pid' ),
               'handlers'   => array( 'stream' ),
           )
       ),
       'processors' => array(
           'wiki' => array(
               'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor',
           ),
           'psr' => array(
               'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
           ),
           'pid' => array(
               'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
           ),
           'uid' => array(
               'class' => '\\Monolog\\Processor\\UidProcessor',
           ),
           'web' => array(
               'class' => '\\Monolog\\Processor\\WebProcessor',
           ),
       ),
       'handlers' => array(
           'stream' => array(
               'class'     => '\\Monolog\\Handler\\StreamHandler',
               'args'      => array( 'path/to/your.log' ),
               'formatter' => 'line',
           ),
       ),
       'formatters' => array(
           'line' => array(
               'class' => '\\Monolog\\Formatter\\LineFormatter',
            ),
       ),
    ) ),
);

Example from MediaWiki-Vagrant's "elk" role

edit

You can setup logging to an Elasticsearch, Logstash and Kibana (ELK) log aggregation stack in MediaWiki-Vagrant by enabling the elk role:

vagrant roles enable elk; vagrant provision

This role configures the wiki to log to local files and also to feed Logstash via an intermediate Redis queue.

$wgMWLoggerDefaultSpi = array(
    'class' => '\\MediaWiki\\Logger\\MonologSpi',
    'args' => array( array(
        'loggers' => array(
            '@default' => array(
                'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
                'handlers'   => array( 'default', 'redis' ),
            ),
            'wfDebug' => array(
                'handlers'   => array( 'default' ),
                'processors' => array( 'psr' ),
            ),
            'profileoutput' => array(
                'handlers'   => array( 'profiler' ),
                'processors' => array( 'psr' ),
            ),
        ),

        'processors' => array(
            'wiki' => array(
                'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor',
            ),
            'psr' => array(
                'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
            ),
            'pid' => array(
                'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
            ),
            'uid' => array(
                'class' => '\\Monolog\\Processor\\UidProcessor',
            ),
            'web' => array(
                'class' => '\\Monolog\\Processor\\WebProcessor',
            ),
        ),

        'handlers' => array(
            'default' => array(
                'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler',
                'args' => array( '/vagrant/logs/monolog-'.date('Ymd').'.log' ),
                'formatter' => 'line',
            ),
            'redis' => array(
                'class' => '\\Monolog\\Handler\\RedisHandler',
                'args' => array(
                    function() {
                        $redis = new Redis();
                        $redis->connect( '127.0.0.1', 6379 );
                        return $redis;
                    },
                    'logstash'
                ),
                'formatter' => 'logstash',
            ),
            'profiler' => array(
                'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler',
                'args' => array( '/vagrant/logs/profiler-'.date('Ymd').'.log' ),
                'formatter' => 'profiler',
            ),
        ),

        'formatters' => array(
            'line' => array(
                'class' => '\\Monolog\\Formatter\\LineFormatter',
            ),
            'logstash' => array(
                'class' => '\\Monolog\\Formatter\\LogstashFormatter',
                'args'  => array( 'mediawiki', php_uname( 'n' ), null, '', 1 ),
            ),
            'profiler' => array(
                'class' => '\\Monolog\\Formatter\\LineFormatter',
                'args' => array( "%datetime% %message%\n\n", null, true, true ),
            ),
        ),
    ) ),
);