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.
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.
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
21 namespace MediaWiki\Logger\Monolog
;
24 use Monolog\Formatter\LineFormatter
as MonologLineFormatter
;
25 use MWExceptionHandler
;
28 * Formats incoming records into a one-line string.
30 * An 'exeception' in the log record's context will be treated specially.
31 * It will be output for an '%exception%' placeholder in the format and
32 * excluded from '%context%' output if the '%exception%' placeholder is
35 * Exceptions that are logged with this formatter will optional have their
36 * stack traces appended. If that is done, MWExceptionHandler::redactedTrace()
37 * will be used to redact the trace information.
40 * @author Bryan Davis <bd808@wikimedia.org>
41 * @copyright © 2015 Bryan Davis and Wikimedia Foundation.
43 class LineFormatter
extends MonologLineFormatter
{
46 * @param string $format The format of the message
47 * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
48 * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
49 * @param bool $ignoreEmptyContextAndExtra
50 * @param bool $includeStacktraces
52 public function __construct(
53 $format = null, $dateFormat = null, $allowInlineLineBreaks = false,
54 $ignoreEmptyContextAndExtra = false, $includeStacktraces = false
57 $format, $dateFormat, $allowInlineLineBreaks,
58 $ignoreEmptyContextAndExtra
60 $this->includeStacktraces( $includeStacktraces );
66 public function format( array $record ) {
67 // Drop the 'private' flag from the context
68 unset( $record['context']['private'] );
70 // Handle exceptions specially: pretty format and remove from context
71 // Will be output for a '%exception%' placeholder in format
72 $prettyException = '';
73 if ( isset( $record['context']['exception'] ) &&
74 strpos( $this->format
, '%exception%' ) !== false
76 $e = $record['context']['exception'];
77 unset( $record['context']['exception'] );
79 if ( $e instanceof Exception
) {
80 $prettyException = $this->normalizeException( $e );
81 } elseif ( is_array( $e ) ) {
82 $prettyException = $this->normalizeExceptionArray( $e );
84 $prettyException = $this->stringify( $e );
88 $output = parent
::format( $record );
90 if ( strpos( $output, '%exception%' ) !== false ) {
91 $output = str_replace( '%exception%', $prettyException, $output );
97 * Convert an Exception to a string.
102 protected function normalizeException( $e ) {
103 return $this->normalizeExceptionArray( $this->exceptionAsArray( $e ) );
107 * Convert an exception to an array of structured data.
109 * @param Exception $e
112 protected function exceptionAsArray( Exception
$e ) {
114 'class' => get_class( $e ),
115 'message' => $e->getMessage(),
116 'code' => $e->getCode(),
117 'file' => $e->getFile(),
118 'line' => $e->getLine(),
119 'trace' => MWExceptionHandler
::redactTrace( $e->getTrace() ),
122 $prev = $e->getPrevious();
124 $out['previous'] = $this->exceptionAsArray( $prev );
131 * Convert an array of Exception data to a string.
136 protected function normalizeExceptionArray( array $e ) {
138 'class' => 'Unknown',
141 'message' => 'unknown',
144 $e = array_merge( $defaults, $e );
146 $str = "\n[Exception {$e['class']}] (" .
147 "{$e['file']}:{$e['line']}) {$e['message']}";
149 if ( $this->includeStacktraces
&& $e['trace'] ) {
151 MWExceptionHandler
::prettyPrintTrace( $e['trace'], ' ' );
154 if ( isset( $e['previous'] ) ) {
155 $prev = $e['previous'];
157 $prev = array_merge( $defaults, $prev );
158 $str .= "\nCaused by: [Exception {$prev['class']}] (" .
159 "{$prev['file']}:{$prev['line']}) {$prev['message']}";
161 if ( $this->includeStacktraces
&& $prev['trace'] ) {
163 MWExceptionHandler
::prettyPrintTrace(
168 $prev = isset( $prev['previous'] ) ?
$prev['previous'] : null;