MediaWiki  master
Profiler.php
Go to the documentation of this file.
1 <?php
22 use Psr\Log\LoggerInterface;
24 use Wikimedia\ScopedCallback;
25 
36 abstract class Profiler {
38  protected $profileID = false;
40  protected $params = [];
42  protected $context = null;
44  protected $trxProfiler;
46  protected $logger;
48  private $allowOutput = false;
49 
51  private static $instance = null;
52 
56  public function __construct( array $params ) {
57  if ( isset( $params['profileID'] ) ) {
58  $this->profileID = $params['profileID'];
59  }
60  $this->params = $params;
61  $this->trxProfiler = new TransactionProfiler();
62  $this->logger = LoggerFactory::getInstance( 'profiler' );
63  }
64 
69  final public static function instance() {
70  if ( self::$instance === null ) {
71  global $wgProfiler;
72 
73  $params = $wgProfiler + [
74  'class' => ProfilerStub::class,
75  'sampling' => 1,
76  'threshold' => 0.0,
77  'output' => [],
78  ];
79 
80  $inSample = mt_rand( 0, $params['sampling'] - 1 ) === 0;
81  // wfIsCLI() is not available yet
82  if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || !$inSample ) {
83  $params['class'] = ProfilerStub::class;
84  }
85 
86  if ( !is_array( $params['output'] ) ) {
87  $params['output'] = [ $params['output'] ];
88  }
89 
90  self::$instance = new $params['class']( $params );
91  }
92  return self::$instance;
93  }
94 
102  final public static function replaceStubInstance( Profiler $profiler ) {
103  if ( self::$instance && !( self::$instance instanceof ProfilerStub ) ) {
104  throw new MWException( 'Could not replace non-stub profiler instance.' );
105  } else {
106  self::$instance = $profiler;
107  }
108  }
109 
113  public function setProfileID( $id ) {
114  $this->profileID = $id;
115  }
116 
120  public function getProfileID() {
121  if ( $this->profileID === false ) {
122  return WikiMap::getCurrentWikiDbDomain()->getId();
123  } else {
124  return $this->profileID;
125  }
126  }
127 
134  public function setContext( $context ) {
135  $this->context = $context;
136  }
137 
144  public function getContext() {
145  if ( $this->context ) {
146  return $this->context;
147  } else {
148  $this->logger->warning( __METHOD__ . " called before setContext, " .
149  "fallback to RequestContext::getMain()." );
150  return RequestContext::getMain();
151  }
152  }
153 
154  public function profileIn( $functionname ) {
155  wfDeprecated( __METHOD__, '1.33' );
156  }
157 
158  public function profileOut( $functionname ) {
159  wfDeprecated( __METHOD__, '1.33' );
160  }
161 
170  abstract public function scopedProfileIn( $section );
171 
175  public function scopedProfileOut( SectionProfileCallback &$section = null ) {
176  $section = null;
177  }
178 
183  public function getTransactionProfiler() {
184  return $this->trxProfiler;
185  }
186 
190  abstract public function close();
191 
199  private function getOutputs() {
200  $outputs = [];
201  foreach ( $this->params['output'] as $outputType ) {
202  // The class may be specified as either the full class name (for
203  // example, 'ProfilerOutputStats') or (for backward compatibility)
204  // the trailing portion of the class name (for example, 'stats').
205  $outputClass = strpos( $outputType, 'ProfilerOutput' ) === false
206  ? 'ProfilerOutput' . ucfirst( $outputType )
207  : $outputType;
208  if ( !class_exists( $outputClass ) ) {
209  throw new MWException( "'$outputType' is an invalid output type" );
210  }
211  $outputInstance = new $outputClass( $this, $this->params );
212  if ( $outputInstance->canUse() ) {
213  $outputs[] = $outputInstance;
214  }
215  }
216  return $outputs;
217  }
218 
224  public function logData() {
225  $request = $this->getContext()->getRequest();
226 
227  $timeElapsed = $request->getElapsedTime();
228  $timeElapsedThreshold = $this->params['threshold'];
229  if ( $timeElapsed <= $timeElapsedThreshold ) {
230  return;
231  }
232 
233  $outputs = [];
234  foreach ( $this->getOutputs() as $output ) {
235  if ( !$output->logsToOutput() ) {
236  $outputs[] = $output;
237  }
238  }
239 
240  if ( $outputs ) {
241  $stats = $this->getFunctionStats();
242  foreach ( $outputs as $output ) {
243  $output->log( $stats );
244  }
245  }
246  }
247 
254  public function logDataPageOutputOnly() {
255  if ( !$this->allowOutput ) {
256  return;
257  }
258 
259  $outputs = [];
260  foreach ( $this->getOutputs() as $output ) {
261  if ( $output->logsToOutput() ) {
262  $outputs[] = $output;
263  }
264  }
265 
266  if ( $outputs ) {
267  $stats = $this->getFunctionStats();
268  foreach ( $outputs as $output ) {
269  $output->log( $stats );
270  }
271  }
272  }
273 
283  public function getContentType() {
284  if ( $this->allowOutput ) {
285  foreach ( headers_list() as $header ) {
286  if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
287  return $m[1];
288  }
289  }
290  }
291  return null;
292  }
293 
300  public function setTemplated( $t ) {
301  wfDeprecated( __METHOD__, '1.34' );
302  $this->allowOutput = ( $t === true );
303  }
304 
311  public function getTemplated() {
312  wfDeprecated( __METHOD__, '1.34' );
313  return $this->getAllowOutput();
314  }
315 
321  public function setAllowOutput() {
322  $this->allowOutput = true;
323  }
324 
331  public function getAllowOutput() {
332  return $this->allowOutput;
333  }
334 
361  abstract public function getFunctionStats();
362 
368  abstract public function getOutput();
369 }
Profiler\getTemplated
getTemplated()
Was this call as templated or not.
Definition: Profiler.php:311
Profiler\getTransactionProfiler
getTransactionProfiler()
Definition: Profiler.php:183
WikiMap\getCurrentWikiDbDomain
static getCurrentWikiDbDomain()
Definition: WikiMap.php:293
Profiler\setTemplated
setTemplated( $t)
Mark this call as templated or not.
Definition: Profiler.php:300
Profiler\replaceStubInstance
static replaceStubInstance(Profiler $profiler)
Replace the current profiler with $profiler if no non-stub profiler is set.
Definition: Profiler.php:102
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:69
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:283
Profiler\$instance
static Profiler $instance
Definition: Profiler.php:51
ProfilerStub
Stub profiler that does nothing.
Definition: ProfilerStub.php:26
Profiler\$profileID
string bool $profileID
Profiler ID for bucketing data.
Definition: Profiler.php:38
Profiler\$context
IContextSource $context
Current request context.
Definition: Profiler.php:42
Profiler\scopedProfileIn
scopedProfileIn( $section)
Mark the start of a custom profiling frame (e.g.
Profiler\getOutputs
getOutputs()
Get all usable outputs.
Definition: Profiler.php:199
Profiler\$trxProfiler
TransactionProfiler $trxProfiler
Definition: Profiler.php:44
SectionProfileCallback
Subclass ScopedCallback to avoid call_user_func_array(), which is slow.
Definition: SectionProfileCallback.php:28
Profiler\profileOut
profileOut( $functionname)
Definition: Profiler.php:158
Profiler\$logger
LoggerInterface $logger
Definition: Profiler.php:46
Profiler\$allowOutput
bool $allowOutput
Definition: Profiler.php:48
MWException
MediaWiki exception.
Definition: MWException.php:29
$wgProfiler
$wgProfiler
Profiler configuration.
Definition: DefaultSettings.php:6842
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1027
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
Profiler\profileIn
profileIn( $functionname)
Definition: Profiler.php:154
Profiler\close
close()
Close opened profiling sections.
Profiler\setAllowOutput
setAllowOutput()
Enable appending profiles to standard output.
Definition: Profiler.php:321
Profiler
Profiler base class that defines the interface and some shared functionality.
Definition: Profiler.php:36
Profiler\__construct
__construct(array $params)
Definition: Profiler.php:56
Profiler\setContext
setContext( $context)
Sets the context for this Profiler.
Definition: Profiler.php:134
$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:224
Profiler\setProfileID
setProfileID( $id)
Definition: Profiler.php:113
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:454
Profiler\getContext
getContext()
Gets the context for this Profiler.
Definition: Profiler.php:144
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
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:254
Profiler\getAllowOutput
getAllowOutput()
Whether appending profiles is allowed.
Definition: Profiler.php:331
Profiler\$params
array $params
All of the params passed from $wgProfiler.
Definition: Profiler.php:40
$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:120
Profiler\scopedProfileOut
scopedProfileOut(SectionProfileCallback &$section=null)
Definition: Profiler.php:175