Simpletest Coverage - includes/database/log.inc

1 <?php
2 // $Id: log.inc,v 1.6 2008/12/20 18:24:33 dries Exp $
3
4 /**
5 * @file
6 * Logging classes for the database layer.
7 */
8
9 /**
10 * Database query logger.
11 *
12 * We log queries in a separate object rather than in the connection object
13 * because we want to be able to see all queries sent to a given database, not
14 * database target. If we logged the queries in each connection object we
15 * would not be able to track what queries went to which target.
16 *
17 * Every connection has one and only one logging object on it for all targets
18 * and logging keys.
19 */
20 class DatabaseLog {
21
22 /**
23 * Cache of logged queries. This will only be used if the query logger is enabled.
24 *
25 * The structure for the logging array is as follows:
26 *
27 * array(
28 * $logging_key = array(
29 * array(query => '', args => array(), caller => '', target => '', time => 0),
30 * array(query => '', args => array(), caller => '', target => '', time => 0),
31 * ),
32 * );
33 *
34 * @var array
35 */
36 protected $queryLog = array();
37
38 /**
39 * The connection key for which this object is logging.
40 *
41 * @var string
42 */
43 protected $connectionKey = 'default';
44
45 /**
46 * Constructor.
47 *
48 * @param $key
49 * The database connection key for which to enable logging.
50 */
51 public function __construct($key = 'default') {
52 $this->connectionKey = $key;
53 }
54
55 /**
56 * Begin logging queries to the specified connection and logging key.
57 *
58 * If the specified logging key is already running this method does nothing.
59 *
60 * @param $logging_key
61 * The identification key for this log request. By specifying different
62 * logging keys we are able to start and stop multiple logging runs
63 * simultaneously without them colliding.
64 */
65 public function start($logging_key) {
66 if (empty($this->queryLog[$logging_key])) {
67 $this->clear($logging_key);
68 }
69 }
70
71 /**
72 * Retrieve the query log for the specified logging key so far.
73 *
74 * @param $logging_key
75 * The logging key to fetch.
76 * @return
77 * An indexed array of all query records for this logging key.
78 */
79 public function get($logging_key) {
80 return $this->queryLog[$logging_key];
81 }
82
83 /**
84 * Empty the query log for the specified logging key.
85 *
86 * This method does not stop logging, it simply clears the log. To stop
87 * logging, use the end() method.
88 *
89 * @param $logging_key
90 * The logging key to empty.
91 */
92 public function clear($logging_key) {
93 $this->queryLog[$logging_key] = array();
94 }
95
96 /**
97 * Stop logging for the specified logging key.
98 *
99 * @param $logging_key
100 * The logging key to stop.
101 */
102 public function end($logging_key) {
103 unset($this->queryLog[$logging_key]);
104 }
105
106 /**
107 * Log a query to all active logging keys.
108 *
109 * @param $statement
110 * The prepared statement object to log.
111 * @param $args
112 * The arguments passed to the statement object.
113 * @param $time
114 * The time in milliseconds the query took to execute.
115 */
116 public function log(DatabaseStatementInterface $statement, $args, $time) {
117 foreach (array_keys($this->queryLog) as $key) {
118 $this->queryLog[$key][] = array(
119 'query' => $statement->getQueryString(),
120 'args' => $args,
121 'target' => $statement->dbh->getTarget(),
122 'caller' => $this->findCaller(),
123 'time' => $time,
124 );
125 }
126 }
127
128 /**
129 * Determine the routine that called this query.
130 *
131 * We define "the routine that called this query" as the first entry in
132 * the call stack that is not inside includes/database. That makes the
133 * climbing logic very simple, and handles the variable stack depth caused
134 * by the query builders.
135 *
136 * @link http://www.php.net/debug_backtrace
137 * @return
138 * This method returns a stack trace entry similar to that generated by
139 * debug_backtrace(). However, it flattens the trace entry and the trace
140 * entry before it so that we get the function and args of the function that
141 * called into the database system, not the function and args of the
142 * database call itself.
143 */
144 public function findCaller() {
145 $stack = debug_backtrace();
146 $stack_count = count($stack);
147 for ($i = 0; $i < $stack_count; ++$i) {
148 if (strpos($stack[$i]['file'], 'includes' . DIRECTORY_SEPARATOR . 'database') === FALSE) {
149 return array(
150 'file' => $stack[$i]['file'],
151 'line' => $stack[$i]['line'],
152 'function' => $stack[$i + 1]['function'],
153 'args' => $stack[$i + 1]['args'],
154 );
155 return $stack[$i];
156 }
157 }
158 }
159 }
160

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.