summaryrefslogtreecommitdiff
path: root/includes/database
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2008-10-11 21:53:36 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2008-10-11 21:53:36 +0000
commit5dff3b8e153f246a49907478092e2a5cf5a02241 (patch)
treef36c348d2f8de7338c9365bd60c9e0cc6a447593 /includes/database
parentecf7ad41d0c3b8d4ea12e3883d3b5c9060eb2963 (diff)
downloadbrdo-5dff3b8e153f246a49907478092e2a5cf5a02241.tar.gz
brdo-5dff3b8e153f246a49907478092e2a5cf5a02241.tar.bz2
#242873 follow-up by pwolanin: Move new check_plain() check constants to bootstrap.inc so they're there in early bootstrap.
Diffstat (limited to 'includes/database')
-rw-r--r--includes/database/log.inc159
1 files changed, 159 insertions, 0 deletions
diff --git a/includes/database/log.inc b/includes/database/log.inc
new file mode 100644
index 000000000..da3f2bb88
--- /dev/null
+++ b/includes/database/log.inc
@@ -0,0 +1,159 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Logging classes for the database layer.
+ */
+
+/**
+ * Database query logger.
+ *
+ * We log queries in a separate object rather than in the connection object
+ * because we want to be able to see all queries sent to a given database, not
+ * database target. If we logged the queries in each connection object we
+ * would not be able to track what queries went to which target.
+ *
+ * Every connection has one and only one logging object on it for all targets
+ * and logging keys.
+ */
+class DatabaseLog {
+
+ /**
+ * Cache of logged queries. This will only be used if the query logger is enabled.
+ *
+ * The structure for the logging array is as follows:
+ *
+ * array(
+ * $logging_key = array(
+ * array(query => '', args => array(), caller => '', target => '', time => 0),
+ * array(query => '', args => array(), caller => '', target => '', time => 0),
+ * ),
+ * );
+ *
+ * @var array
+ */
+ protected $queryLog = array();
+
+ /**
+ * The connection key for which this object is logging.
+ *
+ * @var string
+ */
+ protected $connectionKey = 'default';
+
+ /**
+ * Constructor.
+ *
+ * @param $key
+ * The database connection key for which to enable logging.
+ */
+ public function __construct($key = 'default') {
+ $this->connectionKey = $key;
+ }
+
+ /**
+ * Begin logging queries to the specified connection and logging key.
+ *
+ * If the specified logging key is already running this method does nothing.
+ *
+ * @param $logging_key
+ * The identification key for this log request. By specifying different
+ * logging keys we are able to start and stop multiple logging runs
+ * simultaneously without them colliding.
+ */
+ public function start($logging_key) {
+ if (empty($this->queryLog[$logging_key])) {
+ $this->clear($logging_key);
+ }
+ }
+
+ /**
+ * Retrieve the query log for the specified logging key so far.
+ *
+ * @param $logging_key
+ * The logging key to fetch.
+ * @return
+ * An indexed array of all query records for this logging key.
+ */
+ public function get($logging_key) {
+ return $this->queryLog[$logging_key];
+ }
+
+ /**
+ * Empty the query log for the specified logging key.
+ *
+ * This method does not stop logging, it simply clears the log. To stop
+ * logging, use the end() method.
+ *
+ * @param $logging_key
+ * The logging key to empty.
+ */
+ public function clear($logging_key) {
+ $this->queryLog[$logging_key] = array();
+ }
+
+ /**
+ * Stop logging for the specified logging key.
+ *
+ * @param $logging_key
+ * The logging key to stop.
+ */
+ public function end($logging_key) {
+ unset($this->queryLog[$logging_key]);
+ }
+
+ /**
+ * Log a query to all active logging keys.
+ *
+ * @param $statement
+ * The prepared statement object to log.
+ * @param $args
+ * The arguments passed to the statement object.
+ * @param $time
+ * The time in milliseconds the query took to execute.
+ */
+ public function log(DatabaseStatement $statement, $args, $time) {
+ foreach (array_keys($this->queryLog) as $key) {
+ $this->queryLog[$key][] = array(
+ 'query' => $statement->queryString,
+ 'args' => $args,
+ 'target' => $statement->dbh->getTarget(),
+ 'caller' => $this->findCaller(),
+ 'time' => $time,
+ );
+ }
+ }
+
+ /**
+ * Determine the routine that called this query.
+ *
+ * We define "the routine that called this query" as the first entry in
+ * the call stack that is not inside includes/database. That makes the
+ * climbing logic very simple, and handles the variable stack depth caused
+ * by the query builders.
+ *
+ * @link http://www.php.net/debug_backtrace
+ * @return
+ * This method returns a stack trace entry similar to that generated by
+ * debug_backtrace(). However, it flattens the trace entry and the trace
+ * entry before it so that we get the function and args of the function that
+ * called into the database system, not the function and args of the
+ * database call itself.
+ */
+ public function findCaller() {
+ $stack = debug_backtrace();
+ $stack_count = count($stack);
+ for ($i = 0; $i < $stack_count; ++$i) {
+ if (strpos($stack[$i]['file'], 'includes/database') === FALSE) {
+ return array(
+ 'file' => $stack[$i]['file'],
+ 'line' => $stack[$i]['line'],
+ 'function' => $stack[$i + 1]['function'],
+ 'args' => $stack[$i + 1]['args'],
+ );
+ return $stack[$i];
+ }
+ }
+ }
+}