MediaWiki  master
Profiler.php
Go to the documentation of this file.
1 <?php
21 use Wikimedia\ScopedCallback;
22 
33 abstract class Profiler {
35  protected $profileID = false;
37  protected $params = [];
39  protected $context = null;
41  protected $trxProfiler;
43  private $allowOutput = false;
44 
46  private static $instance = null;
47 
51  public function __construct( array $params ) {
52  if ( isset( $params['profileID'] ) ) {
53  $this->profileID = $params['profileID'];
54  }
55  $this->params = $params;
56  $this->trxProfiler = new TransactionProfiler();
57  }
58 
63  final public static function instance() {
64  if ( self::$instance === null ) {
65  global $wgProfiler;
66 
67  $params = $wgProfiler + [
68  'class' => ProfilerStub::class,
69  'sampling' => 1,
70  'threshold' => 0.0,
71  'output' => [],
72  ];
73 
74  $inSample = mt_rand( 0, $params['sampling'] - 1 ) === 0;
75  // wfIsCLI() is not available yet
76  if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || !$inSample ) {
77  $params['class'] = ProfilerStub::class;
78  }
79 
80  if ( !is_array( $params['output'] ) ) {
81  $params['output'] = [ $params['output'] ];
82  }
83 
84  self::$instance = new $params['class']( $params );
85  }
86  return self::$instance;
87  }
88 
96  final public static function replaceStubInstance( Profiler $profiler ) {
97  if ( self::$instance && !( self::$instance instanceof ProfilerStub ) ) {
98  throw new MWException( 'Could not replace non-stub profiler instance.' );
99  } else {
100  self::$instance = $profiler;
101  }
102  }
103 
107  public function setProfileID( $id ) {
108  $this->profileID = $id;
109  }
110 
114  public function getProfileID() {
115  if ( $this->profileID === false ) {
116  return WikiMap::getCurrentWikiDbDomain()->getId();
117  } else {
118  return $this->profileID;
119  }
120  }
121 
128  public function setContext( $context ) {
129  $this->context = $context;
130  }
131 
138  public function getContext() {
139  if ( $this->context ) {
140  return $this->context;
141  } else {
142  wfDebug( __METHOD__ . " called and \$context is null. " .
143  "Return RequestContext::getMain(); for sanity" );
144  return RequestContext::getMain();
145  }
146  }
147 
148  public function profileIn( $functionname ) {
149  wfDeprecated( __METHOD__, '1.33' );
150  }
151 
152  public function profileOut( $functionname ) {
153  wfDeprecated( __METHOD__, '1.33' );
154  }
155 
164  abstract public function scopedProfileIn( $section );
165 
169  public function scopedProfileOut( SectionProfileCallback &$section = null ) {
170  $section = null;
171  }
172 
177  public function getTransactionProfiler() {
178  return $this->trxProfiler;
179  }
180 
184  abstract public function close();
185 
193  private function getOutputs() {
194  $outputs = [];
195  foreach ( $this->params['output'] as $outputType ) {
196  // The class may be specified as either the full class name (for
197  // example, 'ProfilerOutputStats') or (for backward compatibility)
198  // the trailing portion of the class name (for example, 'stats').
199  $outputClass = strpos( $outputType, 'ProfilerOutput' ) === false
200  ? 'ProfilerOutput' . ucfirst( $outputType )
201  : $outputType;
202  if ( !class_exists( $outputClass ) ) {
203  throw new MWException( "'$outputType' is an invalid output type" );
204  }
205  $outputInstance = new $outputClass( $this, $this->params );
206  if ( $outputInstance->canUse() ) {
207  $outputs[] = $outputInstance;
208  }
209  }
210  return $outputs;
211  }
212 
218  public function logData() {
219  $request = $this->getContext()->getRequest();
220 
221  $timeElapsed = $request->getElapsedTime();
222  $timeElapsedThreshold = $this->params['threshold'];
223  if ( $timeElapsed <= $timeElapsedThreshold ) {
224  return;
225  }
226 
227  $outputs = [];
228  foreach ( $this->getOutputs() as $output ) {
229  if ( !$output->logsToOutput() ) {
230  $outputs[] = $output;
231  }
232  }
233 
234  if ( $outputs ) {
235  $stats = $this->getFunctionStats();
236  foreach ( $outputs as $output ) {
237  $output->log( $stats );
238  }
239  }
240  }
241 
248  public function logDataPageOutputOnly() {
249  if ( !$this->allowOutput ) {
250  return;
251  }
252 
253  $outputs = [];
254  foreach ( $this->getOutputs() as $output ) {
255  if ( $output->logsToOutput() ) {
256  $outputs[] = $output;
257  }
258  }
259 
260  if ( $outputs ) {
261  $stats = $this->getFunctionStats();
262  foreach ( $outputs as $output ) {
263  $output->log( $stats );
264  }
265  }
266  }
267 
277  public function getContentType() {
278  if ( $this->allowOutput ) {
279  foreach ( headers_list() as $header ) {
280  if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
281  return $m[1];
282  }
283  }
284  }
285  return null;
286  }
287 
294  public function setTemplated( $t ) {
295  wfDeprecated( __METHOD__, '1.34' );
296  $this->allowOutput = ( $t === true );
297  }
298 
305  public function getTemplated() {
306  wfDeprecated( __METHOD__, '1.34' );
307  return $this->getAllowOutput();
308  }
309 
315  public function setAllowOutput() {
316  $this->allowOutput = true;
317  }
318 
325  public function getAllowOutput() {
326  return $this->allowOutput;
327  }
328 
355  abstract public function getFunctionStats();
356 
362  abstract public function getOutput();
363 }
Profiler\getTemplated
getTemplated()
Was this call as templated or not.
Definition: Profiler.php:305
Profiler\getTransactionProfiler
getTransactionProfiler()
Definition: Profiler.php:177
WikiMap\getCurrentWikiDbDomain
static getCurrentWikiDbDomain()
Definition: WikiMap.php:293
Profiler\setTemplated
setTemplated( $t)
Mark this call as templated or not.
Definition: Profiler.php:294
Profiler\replaceStubInstance
static replaceStubInstance(Profiler $profiler)
Replace the current profiler with $profiler if no non-stub profiler is set.
Definition: Profiler.php:96
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:63
true
return true
Definition: router.php:90
Profiler\getOutput
getOutput()
Returns a profiling output to be stored in debug file.
Profiler\getContentType
getContentType()
Get the Content-Type for deciding how to format appended profile output.
Definition: Profiler.php:277
Profiler\$instance
static Profiler $instance
Definition: Profiler.php:46
ProfilerStub
Stub profiler that does nothing.
Definition: ProfilerStub.php:26
Profiler\$profileID
string bool $profileID
Profiler ID for bucketing data.
Definition: Profiler.php:35
Profiler\$context
IContextSource $context
Current request context.
Definition: Profiler.php:39
Profiler\scopedProfileIn
scopedProfileIn( $section)
Mark the start of a custom profiling frame (e.g.
Profiler\getOutputs
getOutputs()
Get all usable outputs.
Definition: Profiler.php:193
Profiler\$trxProfiler
TransactionProfiler $trxProfiler
Definition: Profiler.php:41
SectionProfileCallback
Subclass ScopedCallback to avoid call_user_func_array(), which is slow.
Definition: SectionProfileCallback.php:28
Profiler\profileOut
profileOut( $functionname)
Definition: Profiler.php:152
Profiler\$allowOutput
bool $allowOutput
Definition: Profiler.php:43
MWException
MediaWiki exception.
Definition: MWException.php:26
$wgProfiler
$wgProfiler
Profiler configuration.
Definition: DefaultSettings.php:6829
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1029
Profiler\profileIn
profileIn( $functionname)
Definition: Profiler.php:148
Profiler\close
close()
Close opened profiling sections.
Profiler\setAllowOutput
setAllowOutput()
Enable appending profiles to standard output.
Definition: Profiler.php:315
Profiler
Profiler base class that defines the interface and some shared functionality.
Definition: Profiler.php:33
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:912
Profiler\__construct
__construct(array $params)
Definition: Profiler.php:51
Profiler\setContext
setContext( $context)
Sets the context for this Profiler.
Definition: Profiler.php:128
$header
$header
Definition: updateCredits.php:41
Profiler\logData
logData()
Log the data to the backing store for all ProfilerOutput instances that have one.
Definition: Profiler.php:218
Profiler\setProfileID
setProfileID( $id)
Definition: Profiler.php:107
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
Profiler\getContext
getContext()
Gets the context for this Profiler.
Definition: Profiler.php:138
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
Profiler\getFunctionStats
getFunctionStats()
Get the aggregated inclusive profiling data for each method.
Profiler\logDataPageOutputOnly
logDataPageOutputOnly()
Log the data to the script/request output for all ProfilerOutput instances that do so.
Definition: Profiler.php:248
Profiler\getAllowOutput
getAllowOutput()
Whether appending profiles is allowed.
Definition: Profiler.php:325
Profiler\$params
array $params
All of the params passed from $wgProfiler.
Definition: Profiler.php:37
$t
$t
Definition: testCompression.php:74
Wikimedia\Rdbms\TransactionProfiler
Detect high-contention DB queries via profiling calls.
Definition: TransactionProfiler.php:38
Profiler\getProfileID
getProfileID()
Definition: Profiler.php:114
Profiler\scopedProfileOut
scopedProfileOut(SectionProfileCallback &$section=null)
Definition: Profiler.php:169