"Fossies" - the Fresh Open Source Software Archive

Member "drupal-8.9.10/core/lib/Drupal/Core/Database/Log.php" (26 Nov 2020, 5222 Bytes) of package /linux/www/drupal-8.9.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Log.php" see the Fossies "Dox" file reference documentation.

    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    *
   73    * @return
   74    *   An indexed array of all query records for this logging key.
   75    */
   76   public function get($logging_key) {
   77     return $this->queryLog[$logging_key];
   78   }
   79 
   80   /**
   81    * Empty the query log for the specified logging key.
   82    *
   83    * This method does not stop logging, it simply clears the log. To stop
   84    * logging, use the end() method.
   85    *
   86    * @param $logging_key
   87    *   The logging key to empty.
   88    */
   89   public function clear($logging_key) {
   90     $this->queryLog[$logging_key] = [];
   91   }
   92 
   93   /**
   94    * Stop logging for the specified logging key.
   95    *
   96    * @param $logging_key
   97    *   The logging key to stop.
   98    */
   99   public function end($logging_key) {
  100     unset($this->queryLog[$logging_key]);
  101   }
  102 
  103   /**
  104    * Log a query to all active logging keys.
  105    *
  106    * @param $statement
  107    *   The prepared statement object to log.
  108    * @param $args
  109    *   The arguments passed to the statement object.
  110    * @param $time
  111    *   The time in milliseconds the query took to execute.
  112    */
  113   public function log(StatementInterface $statement, $args, $time) {
  114     foreach (array_keys($this->queryLog) as $key) {
  115       $this->queryLog[$key][] = [
  116         'query' => $statement->getQueryString(),
  117         'args' => $args,
  118         'target' => $statement->dbh->getTarget(),
  119         'caller' => $this->findCaller(),
  120         'time' => $time,
  121       ];
  122     }
  123   }
  124 
  125   /**
  126    * Determine the routine that called this query.
  127    *
  128    * We define "the routine that called this query" as the first entry in
  129    * the call stack that is not inside the includes/Drupal/Database directory,
  130    * does not begin with db_ and does have a file (which excludes
  131    * call_user_func_array(), anonymous functions and similar). That makes the
  132    * climbing logic very simple, and handles the variable stack depth caused by
  133    * the query builders.
  134    *
  135    * See the @link http://php.net/debug_backtrace debug_backtrace() @endlink
  136    * function.
  137    *
  138    * @return
  139    *   This method returns a stack trace entry similar to that generated by
  140    *   debug_backtrace(). However, it flattens the trace entry and the trace
  141    *   entry before it so that we get the function and args of the function that
  142    *   called into the database system, not the function and args of the
  143    *   database call itself.
  144    */
  145   public function findCaller() {
  146     $stack = debug_backtrace();
  147     for ($i = 0, $stack_count = count($stack); $i < $stack_count; ++$i) {
  148       // If the call was made from a function, 'class' will be empty. It's
  149       // just easier to give it a default value than to try and integrate
  150       // that into the if statement below.
  151       if (empty($stack[$i + 1]['class'])) {
  152         $stack[$i + 1]['class'] = '';
  153       }
  154       if (strpos($stack[$i + 1]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE && !empty($stack[$i]['file'])) {
  155         $stack[$i] += ['file' => '?', 'line' => '?', 'args' => []];
  156         return [
  157           'file' => $stack[$i]['file'],
  158           'line' => $stack[$i]['line'],
  159           'function' => $stack[$i + 1]['function'],
  160           'class' => $stack[$i + 1]['class'],
  161           'type' => isset($stack[$i + 1]['type']) ? $stack[$i + 1]['type'] : NULL,
  162           'args' => $stack[$i + 1]['args'],
  163         ];
  164       }
  165     }
  166   }
  167 
  168 }