Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 34
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 / 34
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 / 13
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     * @static
50     *
51     * @param string $message The string to log
52     * @param int $priority The syslog priority to log this message at
53     * @param string|null $label When pushing/popping a label would be too much work
54     */
55    public static function log( $message, $priority = LOG_INFO, $label = null ) {
56        if ( static::$inst == null ) {
57            static::$inst = new Logger();
58        }
59
60        static::$inst->logString( $message, $priority, $label );
61    }
62
63    /**
64     * Log an exception to Syslog. The stack trace will be included as a JSON string.
65     * @static
66     *
67     * @param Exception $ex The exception
68     * @param string $additionalText Any string to also log as context, default is empty
69     * @param int $priority The syslog priority to log this message at, default ERR
70     * @param string|null $label When pushing/popping a label would be too much work
71     */
72    public static function logEx( Exception $ex, $additionalText = '', $priority = LOG_ERR, $label = null ) {
73        if ( static::$inst == null ) {
74            static::$inst = new Logger();
75        }
76
77        $msg = [];
78        $msg[] = get_class( $ex );
79
80        if ( $additionalText != '' ) {
81            $msg[] = $additionalText;
82        }
83
84        $msg[] = '@';
85        $msg[] = $ex->getFile() . ':' . $ex->getLine();
86        $msg[] = '->';
87        $msg[] = $ex->getMessage();
88        $msg[] = '; Trace ->';
89        $msg[] = json_encode( $ex->getTrace() );
90
91        static::$inst->logString( implode( ' ', $msg ), $priority, $label );
92    }
93
94    /**
95     * Set the process Syslog thinks this is. This is just a string that gets prepended to the log
96     * message by the Syslog utility. Can be used for very cheap bucketing of logs.
97     * @static
98     *
99     * @param string $bucket
100     */
101    public static function setBucket( $bucket ) {
102        static::$bucket = $bucket;
103    }
104
105    /**
106     * A string that will be added to the front of every log message regardless of the current
107     * label. Use it for things like request IDs.
108     * @static
109     *
110     * @param string $context
111     */
112    public static function setContext( $context ) {
113        static::$context = $context;
114    }
115
116    /**
117     * By pushing a label, you change the sub identifier string for each message logged after the
118     * string was pushed.
119     * @static
120     *
121     * @param string $label
122     */
123    public static function pushLabel( $label ) {
124        static::$label[] = $label;
125    }
126
127    /**
128     * Go back to the last label.
129     * @static
130     */
131    public static function popLabel() {
132        array_pop( static::$label );
133    }
134
135    /**
136     * Perform the actual log operation.
137     * @param string $msgText
138     * @param int $pri
139     * @param string|null $label
140     */
141    private function logString( $msgText, $pri, $label = null ) {
142        global $wgFundraisingEmailUnsubscribeLogFacility;
143
144        if ( static::$context != '' ) {
145            $msg[] = '(' . static::$context . ')';
146        }
147        $msg[] = ':';
148        if ( $label != null ) {
149            $msg[] = $label;
150            $msg[] = ':';
151        } elseif ( end( static::$label ) != '' ) {
152            $msg[] = end( static::$label );
153            $msg[] = ':';
154        }
155        $msg[] = $msgText;
156
157        openlog( static::$bucket, LOG_ODELAY, $wgFundraisingEmailUnsubscribeLogFacility );
158        syslog( $pri, implode( ' ', $msg ) );
159        closelog();
160    }
161}