com.lokorin.lokorin.lib
[ class tree: com.lokorin.lokorin.lib ] [ index: com.lokorin.lokorin.lib ] [ all elements ]

Source for file lib_performance.php

Documentation is available at lib_performance.php

  1. <?php
  2. /*
  3. * Lokorin.com
  4. * Copyright 2004-2006
  5. * Licensed under the GNU LGPL. See COPYING for full terms.
  6. */
  7. /**
  8. * Describes a library that handles everything that has to do with the
  9. * performance monitoring of the site.
  10. * @author Andreas Launila
  11. * @version $Revision: 1.3 $
  12. * @package com.lokorin.lokorin.lib
  13. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  14. */
  15.  
  16. /**#@+
  17. * Performance type specific identifiers. The constants decide what performance
  18. * time that should be looked at.
  19. * @access public
  20. * @var integer
  21. */
  22. define("PERFORMANCE_DB", 1);
  23. define("PERFORMANCE_PAGE", 2);
  24. define("PERFORMANCE_PAGE_WITHOUT_DB", 3);
  25. define("PERFORMANCE_PER_QUERY", 4);
  26. define("PERFORMANCE_QUERIES", 5);
  27. define("PERFORMANCE_SIZE", 6);
  28. define("PERFORMANCE_HITS", 7);
  29. /**#@-*/ * Gets a top list of the performance of the specified type.
  30. * @param integer $selectType A performance constant describing the type of
  31. * performance that should be looked at.
  32. * @param boolean $average Whether or not the average performance should be
  33. * used. If true then the average performance is looked at, otherwise the
  34. * peak performance is looked at.
  35. * @param boolean $descending Whether or not the slowest performance should be
  36. * considered greatest. If true then the slowest performance will be shown
  37. * first in the list, otherwise the fastest performance will be shown
  38. * first.
  39. * @param integer $count The maximum number of entries that should be displayed
  40. * in the top lost. E.g. 10 means that a maximum number of 10 entries will
  41. * be shown. Fewer entries will be shown if there are not at least 10
  42. * entries to show.
  43. * @param integer $minLoggedData The minimum amount of times that data about
  44. * the returned urls have to have been requested to be included in the
  45. * result.
  46. * @return array An array with the requested uri as key and the corresponding
  47. * measured value in microseconds as array value. The array is sorted
  48. * descendingly is $slowest equals true, otherwise it's sorted
  49. * ascendingly.
  50. * @throws IllegalArgumentException If the provided select type constant is
  51. * not valid.
  52. * @access public
  53. */
  54. function getTopList($selectType, $average = true, $descending = true,
  55. $count = 10, $minLoggedData = 30) {
  56. global $db;
  57. if($descending) {
  58. $order = "DESC";
  59. } else {
  60. $order = "ASC";
  61. }
  62. $result = $db->query("SELECT `requested_uri` AS uri, round(".
  63. getSelectField($selectType, $average, $descending).") AS value ".
  64. "FROM ".TABLE_PERFORMANCE." ".
  65. "WHERE ".
  66. "(SELECT COUNT(*) FROM ".TABLE_PERFORMANCE." ".
  67. "WHERE `requested_uri`=uri) >= ".$db->escape($minLoggedData)." ".
  68. "GROUP BY `requested_uri` ".
  69. "ORDER BY value ".$order." LIMIT ".$count);
  70. $topList = array();
  71. while(list($uri, $time) = mysql_fetch_row($result)) {
  72. $topList[$uri] = $time;
  73. }
  74. return $topList;
  75. }
  76.  
  77. /**
  78. * Gets the select parameter that should be used when selecting the specified
  79. * select type from the performance database.
  80. * @param integer $selectType A performance constant describing the type of
  81. * performance that should be looked at.
  82. * @param boolean $average Whether or not the average performance should be
  83. * used. If true then the average performance is looked at, otherwise the
  84. * peak performance is looked at.
  85. * @param boolean $descending Whether or not the slowest performance should be
  86. * considered greatest. If true then the slowest performance will be shown
  87. * first in the list, otherwise the fastest performance will be shown
  88. * first.
  89. * @return string A string that can be entered after SELECT in a query.
  90. * @throws IllegalArgumentException If the provided select type constant is
  91. * not valid.
  92. * @access private
  93. */
  94. function getSelectField($selectType, $average, $descending) {
  95. if($average) {
  96. $function = "round(avg(%s))";
  97. } else if($descending) {
  98. $function = "max(%s)";
  99. } else {
  100. $function = "min(%s)";
  101. }
  102. return getFieldExpression($selectType, $function);
  103. }
  104.  
  105. /**
  106. * Gets the expression of the field that is connected to the specified select
  107. * type constant. The function can also wrap the expression in an optional
  108. * printf pattern if possible.
  109. * @param integer $select Type A performance constant describing the type of
  110. * performance that should be looked at.
  111. * @param string $function The printf pattern that the expression should be
  112. * wrapped in, if allowed by the expression. The first instance of %s will
  113. * be replaced by the field expression if possible, otherwise the
  114. * expression will be returned without being sent through the pattern.
  115. * @return string A field expression that counts as a valid SQL field.
  116. * @throws IllegalArgumentException If the provided select type constant is
  117. * not valid.
  118. * @access private
  119. */
  120. function getFieldExpression($selectType, $function = "%s") {
  121. switch($selectType) {
  122. case PERFORMANCE_DB: return sprintf($function, "`db_microseconds`");
  123. case PERFORMANCE_PAGE: return sprintf($function, "`elapsed_microseconds`");
  124. case PERFORMANCE_PAGE_WITHOUT_DB: return sprintf($function, "`elapsed_microseconds`-`db_microseconds`");
  125. case PERFORMANCE_PER_QUERY: return sprintf($function, "`db_microseconds`/`db_queries`");
  126. case PERFORMANCE_QUERIES: return sprintf($function, "`db_queries`");
  127. case PERFORMANCE_SIZE: return sprintf($function, "`page_size`");
  128. case PERFORMANCE_HITS: return "COUNT(*)";
  129. default:
  130. throw new IllegalArgumentException("Select type (".$selectType.
  131. ") not recognised.");
  132. }
  133. }
  134.  
  135. /**
  136. * formats a unix timestamp into a date representation.
  137. * @param integer $time The unix timestamp that should be formatted.
  138. * @return string The date that corresponds to the given timestamp.
  139. * @access public
  140. */
  141. function formatTimestampToDate($time) {
  142. return date('d M y', $time);
  143. }
  144.  
  145. /**
  146. * Formats microseconds by rewriting them as seconds.
  147. * @param integer $microseconds The value in microseconds that should be
  148. * formatted.
  149. * @return string The formatted value in seconds.
  150. * @access public
  151. */
  152. function formatMicroseconds($microseconds) {
  153. return round($microseconds/pow(10, 6), 1);
  154. }
  155.  
  156. /**
  157. * Describes a collection of all performance data related to a specified URI.
  158. * @author Andreas Launila
  159. * @package com.lokorin.lokorin.lib
  160. */
  161. class PerformanceData {
  162. /**
  163. * The URI which the data is linked to.
  164. * @var string
  165. */
  166. private $uri;
  167. /**
  168. * Contains the basic statistical data, data which summarises the
  169. * performance. The key is the title of the data, the value is an array
  170. * where the key is the value's name (e.g. "min") and the value is the
  171. * corresponding value (e.g. "5 queries").
  172. * @var array
  173. */
  174. private $basicData;
  175. /**
  176. * An array containing all performance types. Type constant as array key,
  177. * the value is another array in which the first value is the corresponding
  178. * title and the second value is the unit.
  179. */
  180. private $types;
  181. /**
  182. * Constructor for PerformanceData.
  183. * @param string $uri The URI which the performance data should represent.
  184. * @throws IllegalArgumentException If no data was found for the specified
  185. * URI.
  186. */
  187. public function __construct($uri) {
  188. $this->uri = $uri;
  189. $this->basicData = array();
  190. $this->types = array(
  191. PERFORMANCE_PAGE => array("Page (with DB)", "ms"),
  192. PERFORMANCE_PAGE_WITHOUT_DB => array("Page (without DB)", "ms"),
  193. PERFORMANCE_DB => array("Database (total)", "ms"),
  194. PERFORMANCE_PER_QUERY => array("Database (per query)", "ms"),
  195. PERFORMANCE_QUERIES => array("Performed queries", "queries"),
  196. PERFORMANCE_SIZE => array("Page size", "bytes")
  197. );
  198. //Build up the fields that should be selected.
  199. $selectFields = "";
  200. foreach($this->types as $type => $titles) {
  201. if($selectFields != "") {
  202. $selectFields .= ", ";
  203. }
  204. $selectFields .= $this->getAllSelectFields($type);
  205. }
  206. //Query the database.
  207. global $db;
  208. $row = mysql_fetch_row($db->query("SELECT COUNT(*), ".$selectFields." ".
  209. "FROM ".TABLE_PERFORMANCE." ".
  210. "WHERE `requested_uri`=".$db->escape($this->uri)));
  211. //Record the result.
  212. $this->basicData["Hits"] = array("Total" => $row[0]);
  213. if($row[0] == 0) {
  214. //No data has been recorded.
  215. throw new IllegalArgumentException("No data was found for the URI (".
  216. $this->uri.")");
  217. }
  218. unset($row[0]);
  219. $i = 1;
  220. foreach($this->types as $type => $titles) {
  221. $pattern = "%s ".$titles[1];
  222. $this->basicData[$titles[0]] = array(
  223. "Minimum" => sprintf($pattern, $row[$i + 0]),
  224. "Average" => sprintf($pattern, $row[$i + 1]),
  225. "Maximum" => sprintf($pattern, $row[$i + 2])
  226. );
  227. $i += 3;
  228. }
  229. }
  230. /**
  231. * Gets the select fields for the min, average and max values (in that
  232. * order) for the specified select type.
  233. * @param integer $selectType A performance constant describing the type of
  234. * performance that should be looked at.
  235. * @return string A string that can be entered after SELECT in a query.
  236. */
  237. private function getAllSelectFields($selectType) {
  238. return getSelectField($selectType, false, false).", ".
  239. getSelectField($selectType, true, true).", ".
  240. getSelectField($selectType, false, true);
  241. }
  242. /**
  243. * Gets the most basic statistical data, data which summarises the
  244. * performance.
  245. * @return array The key is the title of the data, the value is an array
  246. * where the key is the value's name (e.g. "min") and the value is the
  247. * corresponding value (e.g. "5 queries").
  248. */
  249. public function getBasicData() {
  250. return $this->basicData;
  251. }
  252. /**
  253. * Gets the URI that the performance data is linked to.
  254. * @return string A uniform resource identifier.
  255. */
  256. public function getUri() {
  257. return $this->uri;
  258. }
  259. /**
  260. * Gets a graph that displays all the recorded statistics as a function of
  261. * time. E.g. all sizes known for the page are displayed as a function of
  262. * time. All functions are displayed in the same graph.
  263. * @return resource An image resource.
  264. */
  265. public function getGraph() {
  266. global $db;
  267. doInclude("lib_graphs");
  268. $graph = new Graph();
  269. //Define the palette.
  270. $graph->addColor("lgreen", 238, 0, 204);
  271. $graph->addColor("orange", 204, 102, 0);
  272. $graph->addColor("dgreen", 48, 116, 84);
  273. //The types that should be displayed with colors as values.
  274. $typeColors = array(
  275. PERFORMANCE_PAGE => "lgreen",
  276. PERFORMANCE_PAGE_WITHOUT_DB => "orange",
  277. PERFORMANCE_DB => "dgreen"
  278. );
  279. //Add all the functions.
  280. $maxValue = 0;
  281. foreach($this->types as $type => $titles) {
  282. if(!in_array($type, array_keys($typeColors))) {
  283. continue;
  284. }
  285. $function = $this->getFunction($type);
  286. if(max($function) > $maxValue) {
  287. $maxValue = max($function);
  288. }
  289. $graph->addFunction($titles[0], $function, $typeColors[$type]);
  290. }
  291. $paramMarkers = array();
  292. $functionMarkers = array();
  293. //Construct the parameter markers.
  294. $idFields = array("requested_uri" => $this->uri);
  295. $first = $db->querySelectFirst(TABLE_PERFORMANCE, "started",
  296. $db->buildSqlSelector($idFields)."ORDER BY started DESC LIMIT 1");
  297. $firstYear = date('Y', $first);
  298. $lastYear = date('Y', time());
  299. for($year = $firstYear; $year <= $lastYear; $year++) {
  300. for($month = 1; $month <= 12; $month += 2) {
  301. $paramMarkers[] = mktime(0, 0, 0, $month, 1, $year);
  302. }
  303. }
  304. //Construct the value markers.
  305. for($i = 0; $i<$maxValue; $i += 100000) {
  306. $functionMarkers[] = $i;
  307. }
  308. return $graph->getGraph("white", "black", $paramMarkers,
  309. $functionMarkers, "formatTimestampToDate", "formatMicroseconds");
  310. }
  311. /**
  312. * Gets the function for a specific select type.
  313. * @param integer $selectType The type of performance data that the
  314. * function should represent.
  315. * @return array An array of measurments. The key is the timestamp when the
  316. * value was measured, the value is the measured value.
  317. */
  318. private function getFunction($selectType) {
  319. global $db;
  320. $result = $db->query("SELECT DISTINCT round(`started`/(3600*24)) AS time, ".
  321. "round(avg(".getFieldExpression($selectType).")) AS value ".
  322. "FROM ".TABLE_PERFORMANCE." ".
  323. "WHERE requested_uri=".$db->escape($this->uri)." ".
  324. "GROUP BY time ".
  325. "ORDER BY time ASC");
  326. $values = array();
  327. while(list($time, $value) = mysql_fetch_row($result)) {
  328. $values[$time] = $value;
  329. }
  330. return $values;
  331. }
  332. }
  333.  
  334. ?>

Documentation generated on Sun, 16 Apr 2006 21:03:46 +0200 by phpDocumentor 1.3.0RC4