Merge "Make showDiffPage() protected"
[lhc/web/wiklou.git] / includes / debug / logger / monolog / Spi.php
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21 /**
22 * MWLoggerFactory service provider that creates loggers implemented by
23 * Monolog.
24 *
25 * Configured using an array of configuration data with the keys 'loggers',
26 * 'processors', 'handlers' and 'formatters'.
27 *
28 * The ['loggers']['@default'] configuration will be used to create loggers
29 * for any channel that isn't explicitly named in the 'loggers' configuration
30 * section.
31 *
32 * Configuration will most typically be provided in the $wgMWLoggerDefaultSpi
33 * global configuration variable used by MWLoggerFactory to construct its
34 * default SPI provider:
35 * @code
36 * $wgMWLoggerDefaultSpi = array(
37 * 'class' => 'MWLoggerMonologSpi',
38 * 'args' => array( array(
39 * 'loggers' => array(
40 * '@default' => array(
41 * 'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
42 * 'handlers' => array( 'stream' ),
43 * ),
44 * 'runJobs' => array(
45 * 'processors' => array( 'wiki', 'psr', 'pid' ),
46 * 'handlers' => array( 'stream' ),
47 * )
48 * ),
49 * 'processors' => array(
50 * 'wiki' => array(
51 * 'class' => 'MWLoggerMonologProcessor',
52 * ),
53 * 'psr' => array(
54 * 'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
55 * ),
56 * 'pid' => array(
57 * 'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
58 * ),
59 * 'uid' => array(
60 * 'class' => '\\Monolog\\Processor\\UidProcessor',
61 * ),
62 * 'web' => array(
63 * 'class' => '\\Monolog\\Processor\\WebProcessor',
64 * ),
65 * ),
66 * 'handlers' => array(
67 * 'stream' => array(
68 * 'class' => '\\Monolog\\Handler\\StreamHandler',
69 * 'args' => array( 'path/to/your.log' ),
70 * 'formatter' => 'line',
71 * ),
72 * 'redis' => array(
73 * 'class' => '\\Monolog\\Handler\\RedisHandler',
74 * 'args' => array( function() {
75 * $redis = new Redis();
76 * $redis->connect( '127.0.0.1', 6379 );
77 * return $redis;
78 * },
79 * 'logstash'
80 * ),
81 * 'formatter' => 'logstash',
82 * ),
83 * 'udp2log' => array(
84 * 'class' => 'MWLoggerMonologHandler',
85 * 'args' => array(
86 * 'udp://127.0.0.1:8420/mediawiki
87 * ),
88 * 'formatter' => 'line',
89 * ),
90 * ),
91 * 'formatters' => array(
92 * 'line' => array(
93 * 'class' => '\\Monolog\\Formatter\\LineFormatter',
94 * ),
95 * 'logstash' => array(
96 * 'class' => '\\Monolog\\Formatter\\LogstashFormatter',
97 * 'args' => array( 'mediawiki', php_uname( 'n' ), null, '', 1 ),
98 * ),
99 * ),
100 * ) ),
101 * );
102 * @endcode
103 *
104 * @see https://github.com/Seldaek/monolog
105 * @since 1.25
106 * @author Bryan Davis <bd808@wikimedia.org>
107 * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
108 */
109 class MWLoggerMonologSpi implements MWLoggerSpi {
110
111 /**
112 * @var array $singletons
113 */
114 protected $singletons;
115
116 /**
117 * Configuration for creating new loggers.
118 * @var array $config
119 */
120 protected $config;
121
122
123 /**
124 * @param array $config Configuration data.
125 */
126 public function __construct( array $config ) {
127 $this->config = $config;
128 $this->reset();
129 }
130
131
132 /**
133 * Reset internal caches.
134 *
135 * This is public for use in unit tests. Under normal operation there should
136 * be no need to flush the caches.
137 */
138 public function reset() {
139 $this->singletons = array(
140 'loggers' => array(),
141 'handlers' => array(),
142 'formatters' => array(),
143 'processors' => array(),
144 );
145 }
146
147
148 /**
149 * Get a logger instance.
150 *
151 * Creates and caches a logger instance based on configuration found in the
152 * $wgMWLoggerMonologSpiConfig global. Subsequent request for the same channel
153 * name will return the cached instance.
154 *
155 * @param string $channel Logging channel
156 * @return \Psr\Log\LoggerInterface Logger instance
157 */
158 public function getLogger( $channel ) {
159 if ( !isset( $this->singletons['loggers'][$channel] ) ) {
160 // Fallback to using the '@default' configuration if an explict
161 // configuration for the requested channel isn't found.
162 $spec = isset( $this->config['loggers'][$channel] ) ?
163 $this->config['loggers'][$channel] :
164 $this->config['loggers']['@default'];
165
166 $monolog = $this->createLogger( $channel, $spec );
167 $this->singletons['loggers'][$channel] = $monolog;
168 }
169
170 return $this->singletons['loggers'][$channel];
171 }
172
173
174 /**
175 * Create a logger.
176 * @param string $channel Logger channel
177 * @param array $spec Configuration
178 * @return \Monolog\Logger
179 */
180 protected function createLogger( $channel, $spec ) {
181 $obj = new \Monolog\Logger( $channel );
182
183 if ( isset( $spec['processors'] ) ) {
184 foreach ( $spec['processors'] as $processor ) {
185 $obj->pushProcessor( $this->getProcessor( $processor ) );
186 }
187 }
188
189 if ( isset( $spec['handlers'] ) ) {
190 foreach ( $spec['handlers'] as $handler ) {
191 $obj->pushHandler( $this->getHandler( $handler ) );
192 }
193 }
194 return $obj;
195 }
196
197
198 /**
199 * Create or return cached processor.
200 * @param string $name Processor name
201 * @return callable
202 */
203 public function getProcessor( $name ) {
204 if ( !isset( $this->singletons['processors'][$name] ) ) {
205 $spec = $this->config['processors'][$name];
206 $processor = ObjectFactory::getObjectFromSpec( $spec );
207 $this->singletons['processors'][$name] = $processor;
208 }
209 return $this->singletons['processors'][$name];
210 }
211
212
213 /**
214 * Create or return cached handler.
215 * @param string $name Processor name
216 * @return \Monolog\Handler\HandlerInterface
217 */
218 public function getHandler( $name ) {
219 if ( !isset( $this->singletons['handlers'][$name] ) ) {
220 $spec = $this->config['handlers'][$name];
221 $handler = ObjectFactory::getObjectFromSpec( $spec );
222 if ( isset( $spec['formatter'] ) ) {
223 $handler->setFormatter(
224 $this->getFormatter( $spec['formatter'] )
225 );
226 }
227 $this->singletons['handlers'][$name] = $handler;
228 }
229 return $this->singletons['handlers'][$name];
230 }
231
232
233 /**
234 * Create or return cached formatter.
235 * @param string $name Formatter name
236 * @return \Monolog\Formatter\FormatterInterface
237 */
238 public function getFormatter( $name ) {
239 if ( !isset( $this->singletons['formatters'][$name] ) ) {
240 $spec = $this->config['formatters'][$name];
241 $formatter = ObjectFactory::getObjectFromSpec( $spec );
242 $this->singletons['formatters'][$name] = $formatter;
243 }
244 return $this->singletons['formatters'][$name];
245 }
246 }