Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Logger
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 8
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 log
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 logEx
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 setBucket
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setContext
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 pushLabel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 popLabel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 logString
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Syslog utilities :) Really it doesn't have to be syslog specific but it's what fundraising
4 * at MW has always used. This just serves as a convienent wrapper class for managing things I find
5 * useful in logs.
6 *
7 * As to why am I reinventing the wheel for the nth time; well... MW's own logging mechanism sucks
8 * and does not do what FR needs it to do; and PHPs debug_log() would also require a wrapper.
9 *
10 * -- License --
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 * http://www.gnu.org/copyleft/gpl.html
25 *
26 * @file
27 */
28
29/**
30 * Methods for logging stuff to Syslog
31 */
32class Logger {
33
34    /** @var self The global instance of the Syslog class */
35    private static $inst = null;
36
37    /** @var string What process to tell syslog the message came from */
38    private static $bucket = '';
39    /** @var string A persistent string prepended to all messages */
40    private static $context = '';
41    /** @var string[] A stack of strings, whatever is on the top of the stack will get prepended to the message */
42    private static $label = [ '' ];
43
44    private function __construct() {
45    }
46
47    /**
48     * Log a message string to Syslog
49     *
50     * @param string $message The string to log
51     * @param int $priority The syslog priority to log this message at
52     * @param string|null $label When pushing/popping a label would be too much work
53     */
54    public static function log( $message, $priority = LOG_INFO, $label = null ) {
55        if ( static::$inst == null ) {
56            static::$inst = new Logger();
57        }
58
59        static::$inst->logString( $message, $priority, $label );
60    }
61
62    /**
63     * Log an exception to Syslog. The stack trace will be included as a JSON string.
64     *
65     * @param Exception $ex The exception
66     * @param string $additionalText Any string to also log as context, default is empty
67     * @param int $priority The syslog priority to log this message at, default ERR
68     * @param string|null $label When pushing/popping a label would be too much work
69     */
70    public static function logEx( Exception $ex, $additionalText = '', $priority = LOG_ERR, $label = null ) {
71        if ( static::$inst == null ) {
72            static::$inst = new Logger();
73        }
74
75        $msg = [];
76        $msg[] = get_class( $ex );
77
78        if ( $additionalText != '' ) {
79            $msg[] = $additionalText;
80        }
81
82        $msg[] = '@';
83        $msg[] = $ex->getFile() . ':' . $ex->getLine();
84        $msg[] = '->';
85        $msg[] = $ex->getMessage();
86        $msg[] = '; Trace ->';
87        $msg[] = json_encode( $ex->getTrace() );
88
89        static::$inst->logString( implode( ' ', $msg ), $priority, $label );
90    }
91
92    /**
93     * Set the process Syslog thinks this is. This is just a string that gets prepended to the log
94     * message by the Syslog utility. Can be used for very cheap bucketing of logs.
95     *
96     * @param string $bucket
97     */
98    public static function setBucket( $bucket ) {
99        static::$bucket = $bucket;
100    }
101
102    /**
103     * A string that will be added to the front of every log message regardless of the current
104     * label. Use it for things like request IDs.
105     *
106     * @param string $context
107     */
108    public static function setContext( $context ) {
109        static::$context = $context;
110    }
111
112    /**
113     * By pushing a label, you change the sub identifier string for each message logged after the
114     * string was pushed.
115     *
116     * @param string $label
117     */
118    public static function pushLabel( $label ) {
119        static::$label[] = $label;
120    }
121
122    /**
123     * Go back to the last label.
124     */
125    public static function popLabel() {
126        array_pop( static::$label );
127    }
128
129    /**
130     * Perform the actual log operation.
131     * @param string $msgText
132     * @param int $pri
133     * @param string|null $label
134     */
135    private function logString( $msgText, $pri, $label = null ) {
136        global $wgFundraisingEmailUnsubscribeLogFacility;
137
138        $msg = [];
139        if ( static::$context != '' ) {
140            $msg[] = '(' . static::$context . ')';
141        }
142        $msg[] = ':';
143        if ( $label != null ) {
144            $msg[] = $label;
145            $msg[] = ':';
146        } elseif ( end( static::$label ) != '' ) {
147            $msg[] = end( static::$label );
148            $msg[] = ':';
149        }
150        $msg[] = $msgText;
151
152        openlog( static::$bucket, LOG_ODELAY, $wgFundraisingEmailUnsubscribeLogFacility );
153        syslog( $pri, implode( ' ', $msg ) );
154        closelog();
155    }
156}