MediaWiki  master
Profiler.php
Go to the documentation of this file.
1 <?php
26 
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 ) {
66 
67  $params = [
68  'class' => ProfilerStub::class,
69  'sampling' => 1,
70  'threshold' => $wgProfileLimit,
71  'output' => [],
72  ];
73  if ( is_array( $wgProfiler ) ) {
74  $params = array_merge( $params, $wgProfiler );
75  }
76 
77  $inSample = mt_rand( 0, $params['sampling'] - 1 ) === 0;
78  // wfIsCLI() is not available yet
79  if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || !$inSample ) {
80  $params['class'] = ProfilerStub::class;
81  }
82 
83  if ( !is_array( $params['output'] ) ) {
84  $params['output'] = [ $params['output'] ];
85  }
86 
87  self::$instance = new $params['class']( $params );
88  }
89  return self::$instance;
90  }
91 
99  final public static function replaceStubInstance( Profiler $profiler ) {
100  if ( self::$instance && !( self::$instance instanceof ProfilerStub ) ) {
101  throw new MWException( 'Could not replace non-stub profiler instance.' );
102  } else {
103  self::$instance = $profiler;
104  }
105  }
106 
110  public function setProfileID( $id ) {
111  $this->profileID = $id;
112  }
113 
117  public function getProfileID() {
118  if ( $this->profileID === false ) {
119  return WikiMap::getCurrentWikiDbDomain()->getId();
120  } else {
121  return $this->profileID;
122  }
123  }
124 
131  public function setContext( $context ) {
132  $this->context = $context;
133  }
134 
141  public function getContext() {
142  if ( $this->context ) {
143  return $this->context;
144  } else {
145  wfDebug( __METHOD__ . " called and \$context is null. " .
146  "Return RequestContext::getMain(); for sanity\n" );
147  return RequestContext::getMain();
148  }
149  }
150 
151  public function profileIn( $functionname ) {
152  wfDeprecated( __METHOD__, '1.33' );
153  }
154 
155  public function profileOut( $functionname ) {
156  wfDeprecated( __METHOD__, '1.33' );
157  }
158 
167  abstract public function scopedProfileIn( $section );
168 
172  public function scopedProfileOut( SectionProfileCallback &$section = null ) {
173  $section = null;
174  }
175 
180  public function getTransactionProfiler() {
181  return $this->trxProfiler;
182  }
183 
187  abstract public function close();
188 
196  private function getOutputs() {
197  $outputs = [];
198  foreach ( $this->params['output'] as $outputType ) {
199  // The class may be specified as either the full class name (for
200  // example, 'ProfilerOutputStats') or (for backward compatibility)
201  // the trailing portion of the class name (for example, 'stats').
202  $outputClass = strpos( $outputType, 'ProfilerOutput' ) === false
203  ? 'ProfilerOutput' . ucfirst( $outputType )
204  : $outputType;
205  if ( !class_exists( $outputClass ) ) {
206  throw new MWException( "'$outputType' is an invalid output type" );
207  }
208  $outputInstance = new $outputClass( $this, $this->params );
209  if ( $outputInstance->canUse() ) {
210  $outputs[] = $outputInstance;
211  }
212  }
213  return $outputs;
214  }
215 
221  public function logData() {
222  $request = $this->getContext()->getRequest();
223 
224  $timeElapsed = $request->getElapsedTime();
225  $timeElapsedThreshold = $this->params['threshold'];
226  if ( $timeElapsed <= $timeElapsedThreshold ) {
227  return;
228  }
229 
230  $outputs = [];
231  foreach ( $this->getOutputs() as $output ) {
232  if ( !$output->logsToOutput() ) {
233  $outputs[] = $output;
234  }
235  }
236 
237  if ( $outputs ) {
238  $stats = $this->getFunctionStats();
239  foreach ( $outputs as $output ) {
240  $output->log( $stats );
241  }
242  }
243  }
244 
251  public function logDataPageOutputOnly() {
252  if ( !$this->allowOutput ) {
253  return;
254  }
255 
256  $outputs = [];
257  foreach ( $this->getOutputs() as $output ) {
258  if ( $output->logsToOutput() ) {
259  $outputs[] = $output;
260  }
261  }
262 
263  if ( $outputs ) {
264  $stats = $this->getFunctionStats();
265  foreach ( $outputs as $output ) {
266  $output->log( $stats );
267  }
268  }
269  }
270 
280  public function getContentType() {
281  if ( $this->allowOutput ) {
282  foreach ( headers_list() as $header ) {
283  if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
284  return $m[1];
285  }
286  }
287  }
288  return null;
289  }
290 
297  public function setTemplated( $t ) {
298  wfDeprecated( __METHOD__, '1.34' );
299  $this->allowOutput = ( $t === true );
300  }
301 
308  public function getTemplated() {
309  wfDeprecated( __METHOD__, '1.34' );
310  return $this->getAllowOutput();
311  }
312 
318  public function setAllowOutput() {
319  $this->allowOutput = true;
320  }
321 
328  public function getAllowOutput() {
329  return $this->allowOutput;
330  }
331 
358  abstract public function getFunctionStats();
359 
365  abstract public function getOutput();
366 }
Helper class that detects high-contention DB queries via profiling calls.
getContext()
Gets the context for this Profiler.
Definition: Profiler.php:141
string bool $profileID
Profiler ID for bucketing data.
Definition: Profiler.php:35
static Profiler $instance
Definition: Profiler.php:46
__construct(array $params)
Definition: Profiler.php:51
scopedProfileIn( $section)
Mark the start of a custom profiling frame (e.g.
getOutput()
Returns a profiling output to be stored in debug file.
scopedProfileOut(SectionProfileCallback &$section=null)
Definition: Profiler.php:172
IContextSource $context
Current request context.
Definition: Profiler.php:39
static instance()
Singleton.
Definition: Profiler.php:63
getProfileID()
Definition: Profiler.php:117
array $params
All of the params passed from $wgProfiler.
Definition: Profiler.php:37
Stub profiler that does nothing.
profileOut( $functionname)
Definition: Profiler.php:155
static replaceStubInstance(Profiler $profiler)
Replace the current profiler with $profiler if no non-stub profiler is set.
Definition: Profiler.php:99
static getMain()
Get the RequestContext object associated with the main request.
getOutputs()
Get all usable outputs.
Definition: Profiler.php:196
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
setContext( $context)
Sets the context for this Profiler.
Definition: Profiler.php:131
close()
Close opened profiling sections.
setAllowOutput()
Enable appending profiles to standard output.
Definition: Profiler.php:318
$header
setProfileID( $id)
Definition: Profiler.php:110
profileIn( $functionname)
Definition: Profiler.php:151
static getCurrentWikiDbDomain()
Definition: WikiMap.php:293
getTemplated()
Was this call as templated or not.
Definition: Profiler.php:308
logData()
Log the data to the backing store for all ProfilerOutput instances that have one. ...
Definition: Profiler.php:221
Subclass ScopedCallback to avoid call_user_func_array(), which is slow.
$wgProfileLimit
Only record profiling info for pages that took longer than this.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
bool $allowOutput
Definition: Profiler.php:43
logDataPageOutputOnly()
Log the data to the script/request output for all ProfilerOutput instances that do so...
Definition: Profiler.php:251
getTransactionProfiler()
Definition: Profiler.php:180
$wgProfiler
Profiler configuration.
TransactionProfiler $trxProfiler
Definition: Profiler.php:41
getAllowOutput()
Whether appending profiles is allowed.
Definition: Profiler.php:328
return true
Definition: router.php:92
setTemplated( $t)
Mark this call as templated or not.
Definition: Profiler.php:297
getFunctionStats()
Get the aggregated inclusive profiling data for each method.
getContentType()
Get the Content-Type for deciding how to format appended profile output.
Definition: Profiler.php:280