Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Database/Log.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Database; | |
4 | |
5 /** | |
6 * Database query logger. | |
7 * | |
8 * We log queries in a separate object rather than in the connection object | |
9 * because we want to be able to see all queries sent to a given database, not | |
10 * database target. If we logged the queries in each connection object we | |
11 * would not be able to track what queries went to which target. | |
12 * | |
13 * Every connection has one and only one logging object on it for all targets | |
14 * and logging keys. | |
15 */ | |
16 class Log { | |
17 | |
18 /** | |
19 * Cache of logged queries. This will only be used if the query logger is enabled. | |
20 * | |
21 * The structure for the logging array is as follows: | |
22 * | |
23 * array( | |
24 * $logging_key = array( | |
25 * array('query' => '', 'args' => array(), 'caller' => '', 'target' => '', 'time' => 0), | |
26 * array('query' => '', 'args' => array(), 'caller' => '', 'target' => '', 'time' => 0), | |
27 * ), | |
28 * ); | |
29 * | |
30 * @var array | |
31 */ | |
32 protected $queryLog = []; | |
33 | |
34 /** | |
35 * The connection key for which this object is logging. | |
36 * | |
37 * @var string | |
38 */ | |
39 protected $connectionKey = 'default'; | |
40 | |
41 /** | |
42 * Constructor. | |
43 * | |
44 * @param $key | |
45 * The database connection key for which to enable logging. | |
46 */ | |
47 public function __construct($key = 'default') { | |
48 $this->connectionKey = $key; | |
49 } | |
50 | |
51 /** | |
52 * Begin logging queries to the specified connection and logging key. | |
53 * | |
54 * If the specified logging key is already running this method does nothing. | |
55 * | |
56 * @param $logging_key | |
57 * The identification key for this log request. By specifying different | |
58 * logging keys we are able to start and stop multiple logging runs | |
59 * simultaneously without them colliding. | |
60 */ | |
61 public function start($logging_key) { | |
62 if (empty($this->queryLog[$logging_key])) { | |
63 $this->clear($logging_key); | |
64 } | |
65 } | |
66 | |
67 /** | |
68 * Retrieve the query log for the specified logging key so far. | |
69 * | |
70 * @param $logging_key | |
71 * The logging key to fetch. | |
72 * @return | |
73 * An indexed array of all query records for this logging key. | |
74 */ | |
75 public function get($logging_key) { | |
76 return $this->queryLog[$logging_key]; | |
77 } | |
78 | |
79 /** | |
80 * Empty the query log for the specified logging key. | |
81 * | |
82 * This method does not stop logging, it simply clears the log. To stop | |
83 * logging, use the end() method. | |
84 * | |
85 * @param $logging_key | |
86 * The logging key to empty. | |
87 */ | |
88 public function clear($logging_key) { | |
89 $this->queryLog[$logging_key] = []; | |
90 } | |
91 | |
92 /** | |
93 * Stop logging for the specified logging key. | |
94 * | |
95 * @param $logging_key | |
96 * The logging key to stop. | |
97 */ | |
98 public function end($logging_key) { | |
99 unset($this->queryLog[$logging_key]); | |
100 } | |
101 | |
102 /** | |
103 * Log a query to all active logging keys. | |
104 * | |
105 * @param $statement | |
106 * The prepared statement object to log. | |
107 * @param $args | |
108 * The arguments passed to the statement object. | |
109 * @param $time | |
110 * The time in milliseconds the query took to execute. | |
111 */ | |
112 public function log(StatementInterface $statement, $args, $time) { | |
113 foreach (array_keys($this->queryLog) as $key) { | |
114 $this->queryLog[$key][] = [ | |
115 'query' => $statement->getQueryString(), | |
116 'args' => $args, | |
117 'target' => $statement->dbh->getTarget(), | |
118 'caller' => $this->findCaller(), | |
119 'time' => $time, | |
120 ]; | |
121 } | |
122 } | |
123 | |
124 /** | |
125 * Determine the routine that called this query. | |
126 * | |
127 * We define "the routine that called this query" as the first entry in | |
128 * the call stack that is not inside the includes/Drupal/Database directory, | |
129 * does not begin with db_ and does have a file (which excludes | |
130 * call_user_func_array(), anonymous functions and similar). That makes the | |
131 * climbing logic very simple, and handles the variable stack depth caused by | |
132 * the query builders. | |
133 * | |
134 * See the @link http://php.net/debug_backtrace debug_backtrace() @endlink | |
135 * function. | |
136 * | |
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 for ($i = 0, $stack_count = count($stack); $i < $stack_count; ++$i) { | |
147 // If the call was made from a function, 'class' will be empty. It's | |
148 // just easier to give it a default value than to try and integrate | |
149 // that into the if statement below. | |
150 if (empty($stack[$i]['class'])) { | |
151 $stack[$i]['class'] = ''; | |
152 } | |
153 if (strpos($stack[$i]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE && !empty($stack[$i]['file'])) { | |
154 $stack[$i] += ['file' => '?', 'line' => '?', 'args' => []]; | |
155 return [ | |
156 'file' => $stack[$i]['file'], | |
157 'line' => $stack[$i]['line'], | |
158 'function' => $stack[$i + 1]['function'], | |
159 'class' => isset($stack[$i + 1]['class']) ? $stack[$i + 1]['class'] : NULL, | |
160 'type' => isset($stack[$i + 1]['type']) ? $stack[$i + 1]['type'] : NULL, | |
161 'args' => $stack[$i + 1]['args'], | |
162 ]; | |
163 } | |
164 } | |
165 } | |
166 | |
167 } |