Merge "ProfilerOutput: Remove logStandardData() and make log() abstract"
[lhc/web/wiklou.git] / includes / profiler / Profiler.php
1 <?php
2 /**
3 * Base class for profiling.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Profiler
22 * @defgroup Profiler Profiler
23 */
24
25 /**
26 * Profiler base class that defines the interface and some trivial
27 * functionality
28 *
29 * @ingroup Profiler
30 */
31 abstract class Profiler {
32 /** @var string|bool Profiler ID for bucketing data */
33 protected $profileID = false;
34 /** @var bool Whether MediaWiki is in a SkinTemplate output context */
35 protected $templated = false;
36 /** @var array All of the params passed from $wgProfiler */
37 protected $params = array();
38
39 /** @var TransactionProfiler */
40 protected $trxProfiler;
41
42 /**
43 * @var array Mapping of output type to class name
44 */
45 private static $outputTypes = array(
46 'db' => 'ProfilerOutputDb',
47 'text' => 'ProfilerOutputText',
48 'udp' => 'ProfilerOutputUdp',
49 );
50
51 // @codingStandardsIgnoreStart PSR2.Classes.PropertyDeclaration.Underscore
52 /** @var Profiler Do not call this outside Profiler and ProfileSection */
53 public static $__instance = null;
54 // @codingStandardsIgnoreEnd
55
56 /**
57 * @param array $params
58 */
59 public function __construct( array $params ) {
60 if ( isset( $params['profileID'] ) ) {
61 $this->profileID = $params['profileID'];
62 }
63 $this->params = $params;
64 $this->trxProfiler = new TransactionProfiler();
65 }
66
67 /**
68 * Singleton
69 * @return Profiler
70 */
71 final public static function instance() {
72 if ( self::$__instance === null ) {
73 global $wgProfiler;
74 if ( is_array( $wgProfiler ) ) {
75 if ( !isset( $wgProfiler['class'] ) ) {
76 $class = 'ProfilerStub';
77 } else {
78 $class = $wgProfiler['class'];
79 }
80 self::$__instance = new $class( $wgProfiler );
81 } else {
82 self::$__instance = new ProfilerStub( array() );
83 }
84 }
85 return self::$__instance;
86 }
87
88 /**
89 * Return whether this a stub profiler
90 *
91 * @return bool
92 */
93 abstract public function isStub();
94
95 /**
96 * @param string $id
97 */
98 public function setProfileID( $id ) {
99 $this->profileID = $id;
100 }
101
102 /**
103 * @return string
104 */
105 public function getProfileID() {
106 if ( $this->profileID === false ) {
107 return wfWikiID();
108 } else {
109 return $this->profileID;
110 }
111 }
112
113 /**
114 * Called by wfProfieIn()
115 *
116 * @param string $functionname
117 */
118 abstract public function profileIn( $functionname );
119
120 /**
121 * Called by wfProfieOut()
122 *
123 * @param string $functionname
124 */
125 abstract public function profileOut( $functionname );
126
127 /**
128 * @return TransactionProfiler
129 * @since 1.25
130 */
131 public function getTransactionProfiler() {
132 return $this->trxProfiler;
133 }
134
135 /**
136 * Close opened profiling sections
137 */
138 abstract public function close();
139
140 /**
141 * Log the data to some store or even the page output
142 *
143 * @throws MWException
144 * @since 1.25
145 */
146 public function logData() {
147 $output = isset( $this->params['output'] ) ?
148 $this->params['output'] : null;
149
150 if ( !$output || $this->isStub() ) {
151 // return early when no output classes defined or we're a stub
152 return;
153 }
154
155 if ( !is_array( $output ) ) {
156 $output = array( $output );
157 }
158
159 foreach ( $output as $outType ) {
160 if ( isset( self::$outputTypes[$outType] ) ) {
161 $class = self::$outputTypes[$outType];
162 } else {
163 throw new MWException( "'$outType' is an invalid output type" );
164 }
165 /** @var ProfilerOutput $profileOut */
166 $profileOut = new $class( $this, $this->params );
167 if ( $profileOut->canUse() ) {
168 $profileOut->log( $this->getFunctionStats() );
169 }
170 }
171 }
172
173 /**
174 * Get the content type sent out to the client.
175 * Used for profilers that output instead of store data.
176 * @return string
177 * @since 1.25
178 */
179 public function getContentType() {
180 foreach ( headers_list() as $header ) {
181 if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
182 return $m[1];
183 }
184 }
185 return null;
186 }
187
188 /**
189 * Mark this call as templated or not
190 *
191 * @param bool $t
192 */
193 public function setTemplated( $t ) {
194 $this->templated = $t;
195 }
196
197 /**
198 * Was this call as templated or not
199 *
200 * @return bool
201 */
202 public function getTemplated() {
203 return $this->templated;
204 }
205
206 /**
207 * Get the aggregated inclusive profiling data for each method
208 *
209 * The percent time for each time is based on the current "total" time
210 * used is based on all methods so far. This method can therefore be
211 * called several times in between several profiling calls without the
212 * delays in usage of the profiler skewing the results. A "-total" entry
213 * is always included in the results.
214 *
215 * When a call chain involves a method invoked within itself, any
216 * entries for the cyclic invocation should be be demarked with "@".
217 * This makes filtering them out easier and follows the xhprof style.
218 *
219 * @return array List of method entries arrays, each having:
220 * - name : method name
221 * - calls : the number of invoking calls
222 * - real : real time ellapsed (ms)
223 * - %real : percent real time
224 * - cpu : CPU time ellapsed (ms)
225 * - %cpu : percent CPU time
226 * - memory : memory used (bytes)
227 * - %memory : percent memory used
228 * @since 1.25
229 */
230 abstract public function getFunctionStats();
231
232 /**
233 * Returns a profiling output to be stored in debug file
234 *
235 * @return string
236 */
237 abstract public function getOutput();
238 }