Code coverage for /20081101/includes/database/log.inc

Line #Times calledCode
1
<?php
2
// $Id: log.inc,v 1.4 2008/10/24 18:36:01 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
 */
201
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') {
521
    $this->connectionKey = $key;
531
  }
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) {
661
    if (empty($this->queryLog[$logging_key])) {
671
      $this->clear($logging_key);
681
    }
691
  }
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) {
801
    return $this->queryLog[$logging_key];
810
  }
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) {
931
    $this->queryLog[$logging_key] = array();
941
  }
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) {
1031
    unset($this->queryLog[$logging_key]);
1041
  }
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(DatabaseStatement $statement, $args, $time) {
1171
    foreach (array_keys($this->queryLog) as $key) {
1181
      $this->queryLog[$key][] = array(
1191
        'query' => $statement->queryString,
1201
        'args' => $args,
1211
        'target' => $statement->dbh->getTarget(),
1221
        'caller' => $this->findCaller(),
1231
        'time' => $time,
124
      );
1251
    }
1261
  }
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() {
1451
    $stack = debug_backtrace();
1461
    $stack_count = count($stack);
1471
    for ($i = 0; $i < $stack_count; ++$i) {
1481
      if (strpos($stack[$i]['file'], 'includes' . DIRECTORY_SEPARATOR .
'database') === FALSE) {
149
        return array(
1501
          'file' => $stack[$i]['file'],
1511
          'line' => $stack[$i]['line'],
1521
          'function' => $stack[$i + 1]['function'],
1531
          'args' => $stack[$i + 1]['args'],
1541
        );
1550
        return $stack[$i];
1560
      }
1571
    }
1580
  }
159
}
1601