comparison core/modules/dblog/src/Logger/DbLog.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 namespace Drupal\dblog\Logger;
4
5 use Drupal\Component\Utility\Unicode;
6 use Drupal\Core\Database\Connection;
7 use Drupal\Core\Database\Database;
8 use Drupal\Core\Database\DatabaseException;
9 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
10 use Drupal\Core\Logger\LogMessageParserInterface;
11 use Drupal\Core\Logger\RfcLoggerTrait;
12 use Psr\Log\LoggerInterface;
13
14 /**
15 * Logs events in the watchdog database table.
16 */
17 class DbLog implements LoggerInterface {
18 use RfcLoggerTrait;
19 use DependencySerializationTrait;
20
21 /**
22 * The dedicated database connection target to use for log entries.
23 */
24 const DEDICATED_DBLOG_CONNECTION_TARGET = 'dedicated_dblog';
25
26 /**
27 * The database connection object.
28 *
29 * @var \Drupal\Core\Database\Connection
30 */
31 protected $connection;
32
33 /**
34 * The message's placeholders parser.
35 *
36 * @var \Drupal\Core\Logger\LogMessageParserInterface
37 */
38 protected $parser;
39
40 /**
41 * Constructs a DbLog object.
42 *
43 * @param \Drupal\Core\Database\Connection $connection
44 * The database connection object.
45 * @param \Drupal\Core\Logger\LogMessageParserInterface $parser
46 * The parser to use when extracting message variables.
47 */
48 public function __construct(Connection $connection, LogMessageParserInterface $parser) {
49 $this->connection = $connection;
50 $this->parser = $parser;
51 }
52
53 /**
54 * {@inheritdoc}
55 */
56 public function log($level, $message, array $context = []) {
57 // Remove any backtraces since they may contain an unserializable variable.
58 unset($context['backtrace']);
59
60 // Convert PSR3-style messages to SafeMarkup::format() style, so they can be
61 // translated too in runtime.
62 $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context);
63
64 try {
65 $this->connection
66 ->insert('watchdog')
67 ->fields([
68 'uid' => $context['uid'],
69 'type' => Unicode::substr($context['channel'], 0, 64),
70 'message' => $message,
71 'variables' => serialize($message_placeholders),
72 'severity' => $level,
73 'link' => $context['link'],
74 'location' => $context['request_uri'],
75 'referer' => $context['referer'],
76 'hostname' => Unicode::substr($context['ip'], 0, 128),
77 'timestamp' => $context['timestamp'],
78 ])
79 ->execute();
80 }
81 catch (\Exception $e) {
82 // When running Drupal on MySQL or MariaDB you can run into several errors
83 // that corrupt the database connection. Some examples for these kind of
84 // errors on the database layer are "1100 - Table 'xyz' was not locked
85 // with LOCK TABLES" and "1153 - Got a packet bigger than
86 // 'max_allowed_packet' bytes". If such an error happens, the MySQL server
87 // invalidates the connection and answers all further requests in this
88 // connection with "2006 - MySQL server had gone away". In that case the
89 // insert statement above results in a database exception. To ensure that
90 // the causal error is written to the log we try once to open a dedicated
91 // connection and write again.
92 if (
93 // Only handle database related exceptions.
94 ($e instanceof DatabaseException || $e instanceof \PDOException) &&
95 // Avoid an endless loop of re-write attempts.
96 $this->connection->getTarget() != self::DEDICATED_DBLOG_CONNECTION_TARGET
97 ) {
98 // Open a dedicated connection for logging.
99 $key = $this->connection->getKey();
100 $info = Database::getConnectionInfo($key);
101 Database::addConnectionInfo($key, self::DEDICATED_DBLOG_CONNECTION_TARGET, $info['default']);
102 $this->connection = Database::getConnection(self::DEDICATED_DBLOG_CONNECTION_TARGET, $key);
103 // Now try once to log the error again.
104 $this->log($level, $message, $context);
105 }
106 else {
107 throw $e;
108 }
109 }
110 }
111
112 }