PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/system/libraries/Zend/Db/Profiler.php

https://bitbucket.org/micromax/vox-fw
PHP | 471 lines | 179 code | 58 blank | 234 comment | 27 complexity | 51fb71c62538963b6a7ad176672e2c81 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Db
  17. * @subpackage Profiler
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Profiler.php 23775 2011-03-01 17:25:24Z ralph $
  21. */
  22. /**
  23. * @category Zend
  24. * @package Zend_Db
  25. * @subpackage Profiler
  26. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  27. * @license http://framework.zend.com/license/new-bsd New BSD License
  28. */
  29. class Zend_Db_Profiler
  30. {
  31. /**
  32. * A connection operation or selecting a database.
  33. */
  34. const CONNECT = 1;
  35. /**
  36. * Any general database query that does not fit into the other constants.
  37. */
  38. const QUERY = 2;
  39. /**
  40. * Adding new data to the database, such as SQL's INSERT.
  41. */
  42. const INSERT = 4;
  43. /**
  44. * Updating existing information in the database, such as SQL's UPDATE.
  45. *
  46. */
  47. const UPDATE = 8;
  48. /**
  49. * An operation related to deleting data in the database,
  50. * such as SQL's DELETE.
  51. */
  52. const DELETE = 16;
  53. /**
  54. * Retrieving information from the database, such as SQL's SELECT.
  55. */
  56. const SELECT = 32;
  57. /**
  58. * Transactional operation, such as start transaction, commit, or rollback.
  59. */
  60. const TRANSACTION = 64;
  61. /**
  62. * Inform that a query is stored (in case of filtering)
  63. */
  64. const STORED = 'stored';
  65. /**
  66. * Inform that a query is ignored (in case of filtering)
  67. */
  68. const IGNORED = 'ignored';
  69. /**
  70. * Array of Zend_Db_Profiler_Query objects.
  71. *
  72. * @var array
  73. */
  74. protected $_queryProfiles = array();
  75. /**
  76. * Stores enabled state of the profiler. If set to False, calls to
  77. * queryStart() will simply be ignored.
  78. *
  79. * @var boolean
  80. */
  81. protected $_enabled = false;
  82. /**
  83. * Stores the number of seconds to filter. NULL if filtering by time is
  84. * disabled. If an integer is stored here, profiles whose elapsed time
  85. * is less than this value in seconds will be unset from
  86. * the self::$_queryProfiles array.
  87. *
  88. * @var integer
  89. */
  90. protected $_filterElapsedSecs = null;
  91. /**
  92. * Logical OR of any of the filter constants. NULL if filtering by query
  93. * type is disable. If an integer is stored here, it is the logical OR of
  94. * any of the query type constants. When the query ends, if it is not
  95. * one of the types specified, it will be unset from the
  96. * self::$_queryProfiles array.
  97. *
  98. * @var integer
  99. */
  100. protected $_filterTypes = null;
  101. /**
  102. * Class constructor. The profiler is disabled by default unless it is
  103. * specifically enabled by passing in $enabled here or calling setEnabled().
  104. *
  105. * @param boolean $enabled
  106. * @return void
  107. */
  108. public function __construct($enabled = false)
  109. {
  110. $this->setEnabled($enabled);
  111. }
  112. /**
  113. * Enable or disable the profiler. If $enable is false, the profiler
  114. * is disabled and will not log any queries sent to it.
  115. *
  116. * @param boolean $enable
  117. * @return Zend_Db_Profiler Provides a fluent interface
  118. */
  119. public function setEnabled($enable)
  120. {
  121. $this->_enabled = (boolean) $enable;
  122. return $this;
  123. }
  124. /**
  125. * Get the current state of enable. If True is returned,
  126. * the profiler is enabled.
  127. *
  128. * @return boolean
  129. */
  130. public function getEnabled()
  131. {
  132. return $this->_enabled;
  133. }
  134. /**
  135. * Sets a minimum number of seconds for saving query profiles. If this
  136. * is set, only those queries whose elapsed time is equal or greater than
  137. * $minimumSeconds will be saved. To save all queries regardless of
  138. * elapsed time, set $minimumSeconds to null.
  139. *
  140. * @param integer $minimumSeconds OPTIONAL
  141. * @return Zend_Db_Profiler Provides a fluent interface
  142. */
  143. public function setFilterElapsedSecs($minimumSeconds = null)
  144. {
  145. if (null === $minimumSeconds) {
  146. $this->_filterElapsedSecs = null;
  147. } else {
  148. $this->_filterElapsedSecs = (integer) $minimumSeconds;
  149. }
  150. return $this;
  151. }
  152. /**
  153. * Returns the minimum number of seconds for saving query profiles, or null if
  154. * query profiles are saved regardless of elapsed time.
  155. *
  156. * @return integer|null
  157. */
  158. public function getFilterElapsedSecs()
  159. {
  160. return $this->_filterElapsedSecs;
  161. }
  162. /**
  163. * Sets the types of query profiles to save. Set $queryType to one of
  164. * the Zend_Db_Profiler::* constants to only save profiles for that type of
  165. * query. To save more than one type, logical OR them together. To
  166. * save all queries regardless of type, set $queryType to null.
  167. *
  168. * @param integer $queryTypes OPTIONAL
  169. * @return Zend_Db_Profiler Provides a fluent interface
  170. */
  171. public function setFilterQueryType($queryTypes = null)
  172. {
  173. $this->_filterTypes = $queryTypes;
  174. return $this;
  175. }
  176. /**
  177. * Returns the types of query profiles saved, or null if queries are saved regardless
  178. * of their types.
  179. *
  180. * @return integer|null
  181. * @see Zend_Db_Profiler::setFilterQueryType()
  182. */
  183. public function getFilterQueryType()
  184. {
  185. return $this->_filterTypes;
  186. }
  187. /**
  188. * Clears the history of any past query profiles. This is relentless
  189. * and will even clear queries that were started and may not have
  190. * been marked as ended.
  191. *
  192. * @return Zend_Db_Profiler Provides a fluent interface
  193. */
  194. public function clear()
  195. {
  196. $this->_queryProfiles = array();
  197. return $this;
  198. }
  199. /**
  200. * @param integer $queryId
  201. * @return integer or null
  202. */
  203. public function queryClone(Zend_Db_Profiler_Query $query)
  204. {
  205. $this->_queryProfiles[] = clone $query;
  206. end($this->_queryProfiles);
  207. return key($this->_queryProfiles);
  208. }
  209. /**
  210. * Starts a query. Creates a new query profile object (Zend_Db_Profiler_Query)
  211. * and returns the "query profiler handle". Run the query, then call
  212. * queryEnd() and pass it this handle to make the query as ended and
  213. * record the time. If the profiler is not enabled, this takes no
  214. * action and immediately returns null.
  215. *
  216. * @param string $queryText SQL statement
  217. * @param integer $queryType OPTIONAL Type of query, one of the Zend_Db_Profiler::* constants
  218. * @return integer|null
  219. */
  220. public function queryStart($queryText, $queryType = null)
  221. {
  222. if (!$this->_enabled) {
  223. return null;
  224. }
  225. // make sure we have a query type
  226. if (null === $queryType) {
  227. switch (strtolower(substr(ltrim($queryText), 0, 6))) {
  228. case 'insert':
  229. $queryType = self::INSERT;
  230. break;
  231. case 'update':
  232. $queryType = self::UPDATE;
  233. break;
  234. case 'delete':
  235. $queryType = self::DELETE;
  236. break;
  237. case 'select':
  238. $queryType = self::SELECT;
  239. break;
  240. default:
  241. $queryType = self::QUERY;
  242. break;
  243. }
  244. }
  245. /**
  246. * @see Zend_Db_Profiler_Query
  247. */
  248. require_once 'Zend/Db/Profiler/Query.php';
  249. $this->_queryProfiles[] = new Zend_Db_Profiler_Query($queryText, $queryType);
  250. end($this->_queryProfiles);
  251. return key($this->_queryProfiles);
  252. }
  253. /**
  254. * Ends a query. Pass it the handle that was returned by queryStart().
  255. * This will mark the query as ended and save the time.
  256. *
  257. * @param integer $queryId
  258. * @throws Zend_Db_Profiler_Exception
  259. * @return void
  260. */
  261. public function queryEnd($queryId)
  262. {
  263. // Don't do anything if the Zend_Db_Profiler is not enabled.
  264. if (!$this->_enabled) {
  265. return self::IGNORED;
  266. }
  267. // Check for a valid query handle.
  268. if (!isset($this->_queryProfiles[$queryId])) {
  269. /**
  270. * @see Zend_Db_Profiler_Exception
  271. */
  272. require_once 'Zend/Db/Profiler/Exception.php';
  273. throw new Zend_Db_Profiler_Exception("Profiler has no query with handle '$queryId'.");
  274. }
  275. $qp = $this->_queryProfiles[$queryId];
  276. // Ensure that the query profile has not already ended
  277. if ($qp->hasEnded()) {
  278. /**
  279. * @see Zend_Db_Profiler_Exception
  280. */
  281. require_once 'Zend/Db/Profiler/Exception.php';
  282. throw new Zend_Db_Profiler_Exception("Query with profiler handle '$queryId' has already ended.");
  283. }
  284. // End the query profile so that the elapsed time can be calculated.
  285. $qp->end();
  286. /**
  287. * If filtering by elapsed time is enabled, only keep the profile if
  288. * it ran for the minimum time.
  289. */
  290. if (null !== $this->_filterElapsedSecs && $qp->getElapsedSecs() < $this->_filterElapsedSecs) {
  291. unset($this->_queryProfiles[$queryId]);
  292. return self::IGNORED;
  293. }
  294. /**
  295. * If filtering by query type is enabled, only keep the query if
  296. * it was one of the allowed types.
  297. */
  298. if (null !== $this->_filterTypes && !($qp->getQueryType() & $this->_filterTypes)) {
  299. unset($this->_queryProfiles[$queryId]);
  300. return self::IGNORED;
  301. }
  302. return self::STORED;
  303. }
  304. /**
  305. * Get a profile for a query. Pass it the same handle that was returned
  306. * by queryStart() and it will return a Zend_Db_Profiler_Query object.
  307. *
  308. * @param integer $queryId
  309. * @throws Zend_Db_Profiler_Exception
  310. * @return Zend_Db_Profiler_Query
  311. */
  312. public function getQueryProfile($queryId)
  313. {
  314. if (!array_key_exists($queryId, $this->_queryProfiles)) {
  315. /**
  316. * @see Zend_Db_Profiler_Exception
  317. */
  318. require_once 'Zend/Db/Profiler/Exception.php';
  319. throw new Zend_Db_Profiler_Exception("Query handle '$queryId' not found in profiler log.");
  320. }
  321. return $this->_queryProfiles[$queryId];
  322. }
  323. /**
  324. * Get an array of query profiles (Zend_Db_Profiler_Query objects). If $queryType
  325. * is set to one of the Zend_Db_Profiler::* constants then only queries of that
  326. * type will be returned. Normally, queries that have not yet ended will
  327. * not be returned unless $showUnfinished is set to True. If no
  328. * queries were found, False is returned. The returned array is indexed by the query
  329. * profile handles.
  330. *
  331. * @param integer $queryType
  332. * @param boolean $showUnfinished
  333. * @return array|false
  334. */
  335. public function getQueryProfiles($queryType = null, $showUnfinished = false)
  336. {
  337. $queryProfiles = array();
  338. foreach ($this->_queryProfiles as $key => $qp) {
  339. if ($queryType === null) {
  340. $condition = true;
  341. } else {
  342. $condition = ($qp->getQueryType() & $queryType);
  343. }
  344. if (($qp->hasEnded() || $showUnfinished) && $condition) {
  345. $queryProfiles[$key] = $qp;
  346. }
  347. }
  348. if (empty($queryProfiles)) {
  349. $queryProfiles = false;
  350. }
  351. return $queryProfiles;
  352. }
  353. /**
  354. * Get the total elapsed time (in seconds) of all of the profiled queries.
  355. * Only queries that have ended will be counted. If $queryType is set to
  356. * one or more of the Zend_Db_Profiler::* constants, the elapsed time will be calculated
  357. * only for queries of the given type(s).
  358. *
  359. * @param integer $queryType OPTIONAL
  360. * @return float
  361. */
  362. public function getTotalElapsedSecs($queryType = null)
  363. {
  364. $elapsedSecs = 0;
  365. foreach ($this->_queryProfiles as $key => $qp) {
  366. if (null === $queryType) {
  367. $condition = true;
  368. } else {
  369. $condition = ($qp->getQueryType() & $queryType);
  370. }
  371. if (($qp->hasEnded()) && $condition) {
  372. $elapsedSecs += $qp->getElapsedSecs();
  373. }
  374. }
  375. return $elapsedSecs;
  376. }
  377. /**
  378. * Get the total number of queries that have been profiled. Only queries that have ended will
  379. * be counted. If $queryType is set to one of the Zend_Db_Profiler::* constants, only queries of
  380. * that type will be counted.
  381. *
  382. * @param integer $queryType OPTIONAL
  383. * @return integer
  384. */
  385. public function getTotalNumQueries($queryType = null)
  386. {
  387. if (null === $queryType) {
  388. return count($this->_queryProfiles);
  389. }
  390. $numQueries = 0;
  391. foreach ($this->_queryProfiles as $qp) {
  392. if ($qp->hasEnded() && ($qp->getQueryType() & $queryType)) {
  393. $numQueries++;
  394. }
  395. }
  396. return $numQueries;
  397. }
  398. /**
  399. * Get the Zend_Db_Profiler_Query object for the last query that was run, regardless if it has
  400. * ended or not. If the query has not ended, its end time will be null. If no queries have
  401. * been profiled, false is returned.
  402. *
  403. * @return Zend_Db_Profiler_Query|false
  404. */
  405. public function getLastQueryProfile()
  406. {
  407. if (empty($this->_queryProfiles)) {
  408. return false;
  409. }
  410. end($this->_queryProfiles);
  411. return current($this->_queryProfiles);
  412. }
  413. }