Implement extension registration from an extension.json file
[mediawiki.git] / includes / profiler / Profiler.php
blob667a9e22062d982441dca23105742a0c7486b7b6
1 <?php
2 /**
3 * Base class for profiling.
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.
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.
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
20 * @file
21 * @ingroup Profiler
22 * @defgroup Profiler Profiler
25 /**
26 * Profiler base class that defines the interface and some trivial
27 * functionality
29 * @ingroup Profiler
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();
39 /** @var TransactionProfiler */
40 protected $trxProfiler;
42 /**
43 * @var array Mapping of output type to class name
45 private static $outputTypes = array(
46 'db' => 'ProfilerOutputDb',
47 'text' => 'ProfilerOutputText',
48 'udp' => 'ProfilerOutputUdp',
51 // @codingStandardsIgnoreStart PSR2.Classes.PropertyDeclaration.Underscore
52 /** @var Profiler Do not call this outside Profiler and ProfileSection */
53 public static $__instance = null;
54 // @codingStandardsIgnoreEnd
56 /**
57 * @param array $params
59 public function __construct( array $params ) {
60 if ( isset( $params['profileID'] ) ) {
61 $this->profileID = $params['profileID'];
63 $this->params = $params;
64 $this->trxProfiler = new TransactionProfiler();
67 /**
68 * Singleton
69 * @return Profiler
71 final public static function instance() {
72 if ( self::$__instance === null ) {
73 global $wgProfiler;
74 if ( is_array( $wgProfiler ) ) {
75 $class = isset( $wgProfiler['class'] ) ? $wgProfiler['class'] : 'ProfilerStub';
76 $factor = isset( $wgProfiler['sampling'] ) ? $wgProfiler['sampling'] : 1;
77 if ( PHP_SAPI === 'cli' || mt_rand( 0, $factor - 1 ) != 0 ) {
78 $class = 'ProfilerStub';
80 self::$__instance = new $class( $wgProfiler );
81 } else {
82 self::$__instance = new ProfilerStub( array() );
85 return self::$__instance;
88 /**
89 * Replace the current profiler with $profiler if no non-stub profiler is set
91 * @param Profiler $profiler
92 * @throws MWException
93 * @since 1.25
95 final public static function replaceStubInstance( Profiler $profiler ) {
96 if ( self::$__instance && !( self::$__instance instanceof ProfilerStub ) ) {
97 throw new MWException( 'Could not replace non-stub profiler instance.' );
98 } else {
99 self::$__instance = $profiler;
104 * @param string $id
106 public function setProfileID( $id ) {
107 $this->profileID = $id;
111 * @return string
113 public function getProfileID() {
114 if ( $this->profileID === false ) {
115 return wfWikiID();
116 } else {
117 return $this->profileID;
122 * Called by wfProfieIn()
124 * @param string $functionname
126 abstract public function profileIn( $functionname );
129 * Called by wfProfieOut()
131 * @param string $functionname
133 abstract public function profileOut( $functionname );
136 * Mark the start of a custom profiling frame (e.g. DB queries).
137 * The frame ends when the result of this method falls out of scope.
139 * @param string $section
140 * @return ScopedCallback|null
141 * @since 1.25
143 abstract public function scopedProfileIn( $section );
146 * @param ScopedCallback $section
148 public function scopedProfileOut( ScopedCallback &$section ) {
149 $section = null;
153 * @return TransactionProfiler
154 * @since 1.25
156 public function getTransactionProfiler() {
157 return $this->trxProfiler;
161 * Close opened profiling sections
163 abstract public function close();
166 * Log the data to some store or even the page output
168 * @throws MWException
169 * @since 1.25
171 public function logData() {
172 $output = isset( $this->params['output'] ) ? $this->params['output'] : null;
174 if ( !$output || $this instanceof ProfilerStub ) {
175 // return early when no output classes defined or we're a stub
176 return;
179 if ( !is_array( $output ) ) {
180 $output = array( $output );
183 foreach ( $output as $outType ) {
184 if ( !isset( self::$outputTypes[$outType] ) ) {
185 throw new MWException( "'$outType' is an invalid output type" );
187 $class = self::$outputTypes[$outType];
189 /** @var ProfilerOutput $profileOut */
190 $profileOut = new $class( $this, $this->params );
191 if ( $profileOut->canUse() ) {
192 $profileOut->log( $this->getFunctionStats() );
198 * Get the content type sent out to the client.
199 * Used for profilers that output instead of store data.
200 * @return string
201 * @since 1.25
203 public function getContentType() {
204 foreach ( headers_list() as $header ) {
205 if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
206 return $m[1];
209 return null;
213 * Mark this call as templated or not
215 * @param bool $t
217 public function setTemplated( $t ) {
218 $this->templated = $t;
222 * Was this call as templated or not
224 * @return bool
226 public function getTemplated() {
227 return $this->templated;
231 * Get the aggregated inclusive profiling data for each method
233 * The percent time for each time is based on the current "total" time
234 * used is based on all methods so far. This method can therefore be
235 * called several times in between several profiling calls without the
236 * delays in usage of the profiler skewing the results. A "-total" entry
237 * is always included in the results.
239 * When a call chain involves a method invoked within itself, any
240 * entries for the cyclic invocation should be be demarked with "@".
241 * This makes filtering them out easier and follows the xhprof style.
243 * @return array List of method entries arrays, each having:
244 * - name : method name
245 * - calls : the number of invoking calls
246 * - real : real time ellapsed (ms)
247 * - %real : percent real time
248 * - cpu : CPU time ellapsed (ms)
249 * - %cpu : percent CPU time
250 * - memory : memory used (bytes)
251 * - %memory : percent memory used
252 * - min_real : min real time in a call (ms)
253 * - max_real : max real time in a call (ms)
254 * @since 1.25
256 abstract public function getFunctionStats();
259 * Returns a profiling output to be stored in debug file
261 * @return string
263 abstract public function getOutput();