Refactor profiling output from profiling
[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 // @codingStandardsIgnoreStart PSR2.Classes.PropertyDeclaration.Underscore
43 /** @var Profiler Do not call this outside Profiler and ProfileSection */
44 public static $__instance = null;
45 // @codingStandardsIgnoreEnd
46
47 /**
48 * @param array $params
49 */
50 public function __construct( array $params ) {
51 if ( isset( $params['profileID'] ) ) {
52 $this->profileID = $params['profileID'];
53 }
54 $this->params = $params;
55 $this->trxProfiler = new TransactionProfiler();
56 }
57
58 /**
59 * Singleton
60 * @return Profiler
61 */
62 final public static function instance() {
63 if ( self::$__instance === null ) {
64 global $wgProfiler;
65 if ( is_array( $wgProfiler ) ) {
66 if ( !isset( $wgProfiler['class'] ) ) {
67 $class = 'ProfilerStub';
68 } else {
69 $class = $wgProfiler['class'];
70 }
71 self::$__instance = new $class( $wgProfiler );
72 } else {
73 self::$__instance = new ProfilerStub( array() );
74 }
75 }
76 return self::$__instance;
77 }
78
79 /**
80 * Return whether this a stub profiler
81 *
82 * @return bool
83 */
84 abstract public function isStub();
85
86 /**
87 * @param string $id
88 */
89 public function setProfileID( $id ) {
90 $this->profileID = $id;
91 }
92
93 /**
94 * @return string
95 */
96 public function getProfileID() {
97 if ( $this->profileID === false ) {
98 return wfWikiID();
99 } else {
100 return $this->profileID;
101 }
102 }
103
104 /**
105 * Called by wfProfieIn()
106 *
107 * @param string $functionname
108 */
109 abstract public function profileIn( $functionname );
110
111 /**
112 * Called by wfProfieOut()
113 *
114 * @param string $functionname
115 */
116 abstract public function profileOut( $functionname );
117
118 /**
119 * @return TransactionProfiler
120 * @since 1.25
121 */
122 public function getTransactionProfiler() {
123 return $this->trxProfiler;
124 }
125
126 /**
127 * Close opened profiling sections
128 */
129 abstract public function close();
130
131 /**
132 * Log the data to some store or even the page output
133 *
134 * @since 1.25
135 */
136 public function logData() {
137 $output = isset( $this->params['output'] ) ?
138 $this->params['output'] : null;
139
140 if ( !$output || $this->isStub() ) {
141 // return early when no output classes defined or we're a stub
142 return;
143 }
144
145 if ( !is_array( $output ) ) {
146 $output = array( $output );
147 }
148
149 foreach ( $output as $outType ) {
150 $class = 'ProfilerOutput' . ucfirst( strtolower( $outType ) );
151 $profileOut = new $class( $this, $this->params );
152 if ( $profileOut->canUse() ) {
153 $profileOut->log();
154 }
155 }
156 }
157
158 /**
159 * Get the content type sent out to the client.
160 * Used for profilers that output instead of store data.
161 * @return string
162 * @since 1.25
163 */
164 public function getContentType() {
165 foreach ( headers_list() as $header ) {
166 if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) {
167 return $m[1];
168 }
169 }
170 return null;
171 }
172
173 /**
174 * Mark this call as templated or not
175 *
176 * @param bool $t
177 */
178 public function setTemplated( $t ) {
179 $this->templated = $t;
180 }
181
182 /**
183 * Was this call as templated or not
184 *
185 * @return bool
186 */
187 public function getTemplated() {
188 return $this->templated;
189 }
190
191 /**
192 * Get the aggregated inclusive profiling data for each method
193 *
194 * The percent time for each time is based on the current "total" time
195 * used is based on all methods so far. This method can therefore be
196 * called several times in between several profiling calls without the
197 * delays in usage of the profiler skewing the results. A "-total" entry
198 * is always included in the results.
199 *
200 * When a call chain involves a method invoked within itself, any
201 * entries for the cyclic invocation should be be demarked with "@".
202 * This makes filtering them out easier and follows the xhprof style.
203 *
204 * @return array List of method entries arrays, each having:
205 * - name : method name
206 * - calls : the number of invoking calls
207 * - real : real time ellapsed (ms)
208 * - %real : percent real time
209 * - cpu : CPU time ellapsed (ms)
210 * - %cpu : percent CPU time
211 * - memory : memory used (bytes)
212 * - %memory : percent memory used
213 * @since 1.25
214 */
215 abstract public function getFunctionStats();
216
217 /**
218 * Returns a profiling output to be stored in debug file
219 *
220 * @return string
221 */
222 abstract public function getOutput();
223 }