3 namespace MediaWiki\Logger\Monolog
;
6 * LogstashFormatter squashes the base message array and the context and extras subarrays into one.
7 * This can result in unfortunately named context fields overwriting other data (T145133).
8 * This class modifies the standard LogstashFormatter to rename such fields and flag the message.
9 * Also changes exception JSON-ification which is done poorly by the standard class.
11 * Compatible with Monolog 1.x only.
15 class LogstashFormatter
extends \Monolog\Formatter\LogstashFormatter
{
16 /** @var array Keys which should not be used in log context */
17 protected $reservedKeys = [
18 // from LogstashFormatter
19 'message', 'channel', 'level', 'type',
21 'url', 'ip', 'http_method', 'server', 'referrer',
23 'host', 'wiki', 'reqId', 'mwversion',
29 * Prevent key conflicts
30 * @param array $record
33 protected function formatV0( array $record ) {
34 if ( $this->contextPrefix
) {
35 return parent
::formatV0( $record );
38 $context = !empty( $record['context'] ) ?
$record['context'] : [];
39 $record['context'] = [];
40 $formatted = parent
::formatV0( $record );
42 $formatted['@fields'] = $this->fixKeyConflicts( $formatted['@fields'], $context );
47 * Prevent key conflicts
48 * @param array $record
51 protected function formatV1( array $record ) {
52 if ( $this->contextPrefix
) {
53 return parent
::formatV1( $record );
56 $context = !empty( $record['context'] ) ?
$record['context'] : [];
57 $record['context'] = [];
58 $formatted = parent
::formatV1( $record );
60 $formatted = $this->fixKeyConflicts( $formatted, $context );
65 * Check whether some context field would overwrite another message key. If so, rename
67 * @param array $fields Fields to be sent to logstash
68 * @param array $context Copy of the original $record['context']
69 * @return array Updated version of $fields
71 protected function fixKeyConflicts( array $fields, array $context ) {
72 foreach ( $context as $key => $val ) {
74 in_array( $key, $this->reservedKeys
, true ) &&
75 isset( $fields[$key] ) && $fields[$key] !== $val
77 $fields['logstash_formatter_key_conflict'][] = $key;
86 * Use a more user-friendly trace format than NormalizerFormatter
87 * @param \Exception|\Throwable $e
90 protected function normalizeException( $e ) {
91 if ( !$e instanceof \Exception
&& !$e instanceof \Throwable
) {
92 throw new \
InvalidArgumentException( 'Exception/Throwable expected, got '
93 . gettype( $e ) . ' / ' . get_class( $e ) );
97 'class' => get_class( $e ),
98 'message' => $e->getMessage(),
99 'code' => $e->getCode(),
100 'file' => $e->getFile() . ':' . $e->getLine(),
101 'trace' => \MWExceptionHandler
::getRedactedTraceAsString( $e ),
104 $previous = $e->getPrevious();
106 $data['previous'] = $this->normalizeException( $previous );