PluginProbe
DecaLog / 4.4.0
DecaLog v4.4.0
3.0.2 3.1.0 3.10.0 3.2.0 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0 3.7.1 3.8.0 3.9.0 3.9.1 4.0.0 4.1.0 4.2.0 4.3.0 4.3.1 4.4.0 4.5.0 All 75 releases
decalog / includes / storage / class-dbstorage.php

class-dbstorage.php in DecaLog 4.4.0, at includes/storage/class-dbstorage.php

244 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * DB events storage engine for DecaLog.
4 *
5 * Handles all DB events storage features.
6 *
7 * @package Storage
8 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
9 * @since 3.0.0
10 */
11
12 namespace Decalog\Storage;
13
14 use Decalog\Plugin\Feature\ClassTypes;
15 use Decalog\Plugin\Feature\EventTypes;
16 use Decalog\System\Database;
17 use Decalog\System\Http;
18 use Decalog\Plugin\Feature\Log;
19
20 /**
21 * Define the DecaLog DB events storage mechanisms.
22 *
23 * Handles all features of DB events storage engine for DecaLog.
24 *
25 * @package Storage
26 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
27 * @since 3.0.0
28 */
29 class DBStorage extends AbstractDBStorage {
30
31 /**
32 * Initialize the logger.
33 *
34 * @since 3.0.0
35 */
36 public function initialize() {
37 global $wpdb;
38 $cl = [];
39 foreach ( ClassTypes::$classes as $c ) {
40 $cl[] = "'" . $c . "'";
41 }
42 $classes = implode( ',', $cl );
43 $cl = [];
44 foreach ( Http::$verbs as $c ) {
45 $cl[] = "'" . $c . "'";
46 }
47 $verbs = implode( ',', $cl );
48 if ( '' !== $this->bucket_name ) {
49 $charset_collate = 'DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci';
50 $sql = 'CREATE TABLE IF NOT EXISTS ' . $wpdb->base_prefix . $this->bucket_name;
51 $sql .= ' (`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,';
52 $sql .= " `timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',";
53 $sql .= " `level` enum('emergency','alert','critical','error','warning','notice','info','debug','unknown') NOT NULL DEFAULT 'unknown',";
54 $sql .= " `channel` enum('cli','cron','ajax','xmlrpc','api','feed','wback','wfront','unknown') NOT NULL DEFAULT 'unknown',";
55 $sql .= ' `class` enum(' . $classes . ") NOT NULL DEFAULT 'unknown',";
56 $sql .= " `instance` varchar(66) NOT NULL DEFAULT 'undefined',";
57 $sql .= " `component` varchar(26) NOT NULL DEFAULT 'Unknown',";
58 $sql .= " `version` varchar(13) NOT NULL DEFAULT 'N/A',";
59 $sql .= " `code` int(11) UNSIGNED NOT NULL DEFAULT '0',";
60 $sql .= " `message` text,";
61 $sql .= " `site_id` int(11) UNSIGNED NOT NULL DEFAULT '0',";
62 $sql .= " `site_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
63 $sql .= " `user_id` varchar(66) NOT NULL DEFAULT '0',"; // Needed by SHA-256 pseudonymization.
64 $sql .= " `user_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
65 $sql .= " `user_session` varchar(64),";
66 $sql .= " `remote_ip` varchar(66) NOT NULL DEFAULT '127.0.0.1',"; // Needed by SHA-256 obfuscation.
67 $sql .= " `url` varchar(2083) NOT NULL DEFAULT '-',";
68 $sql .= ' `verb` enum(' . $verbs . ") NOT NULL DEFAULT 'unknown',";
69 $sql .= " `server` varchar(250) NOT NULL DEFAULT 'unknown',";
70 $sql .= " `referrer` varchar(250) NOT NULL DEFAULT '-',";
71 $sql .= " `user_agent` varchar(1024) NOT NULL DEFAULT '-',";
72 $sql .= " `file` varchar(250) NOT NULL DEFAULT 'unknown',";
73 $sql .= " `line` int(11) UNSIGNED NOT NULL DEFAULT '0',";
74 $sql .= " `classname` varchar(100) NOT NULL DEFAULT 'unknown',";
75 $sql .= " `function` varchar(100) NOT NULL DEFAULT 'unknown',";
76 $sql .= ' `trace` text,';
77 $sql .= ' PRIMARY KEY (`id`)';
78 $sql .= ") $charset_collate;";
79 // phpcs:ignore
80 $wpdb->query( $sql );
81 $log = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
82 $log->debug( sprintf( 'Table "%s" updated or created.', $this->bucket_name ) );
83 }
84 }
85
86 /**
87 * Update the logger.
88 *
89 * @param string $from The version from which the plugin is updated.
90 * @since 3.0.0
91 */
92 public function update( $from ) {
93 global $wpdb;
94
95 // Starting from 2.4.0, WordpressHandler allows 'library' as class and session token storing..
96 // We have to make a copy of the table, delete the old one, then rename the newly created table to avoid
97 // potential "#1118 - Row size too large" error that may appear if we just make a "ALTER TABLE ... MODIFY COLUMN ...".
98 if ( version_compare( '2.4.0', $from, '>' ) ) {
99 try {
100 $cl = [];
101 foreach ( ClassTypes::$classes as $c ) {
102 $cl[] = "'" . $c . "'";
103 }
104 $classes = implode( ',', $cl );
105 $cl = [];
106 foreach ( Http::$verbs as $c ) {
107 $cl[] = "'" . $c . "'";
108 }
109 $verbs = implode( ',', $cl );
110 if ( '' !== $this->bucket_name ) {
111 $charset_collate = 'DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci';
112 $sql = 'CREATE TABLE IF NOT EXISTS ' . $wpdb->base_prefix . $this->bucket_name . '_mig';
113 $sql .= ' (`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,';
114 $sql .= " `timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',";
115 $sql .= " `level` enum('emergency','alert','critical','error','warning','notice','info','debug','unknown') NOT NULL DEFAULT 'unknown',";
116 $sql .= " `channel` enum('cli','cron','ajax','xmlrpc','api','feed','wback','wfront','unknown') NOT NULL DEFAULT 'unknown',";
117 $sql .= ' `class` enum(' . $classes . ") NOT NULL DEFAULT 'unknown',";
118 $sql .= " `component` varchar(26) NOT NULL DEFAULT 'Unknown',";
119 $sql .= " `version` varchar(13) NOT NULL DEFAULT 'N/A',";
120 $sql .= " `code` int(11) UNSIGNED NOT NULL DEFAULT '0',";
121 $sql .= " `message` text,";
122 $sql .= " `site_id` int(11) UNSIGNED NOT NULL DEFAULT '0',";
123 $sql .= " `site_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
124 $sql .= " `user_id` varchar(66) NOT NULL DEFAULT '0',"; // Needed by SHA-256 pseudonymization.
125 $sql .= " `user_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
126 $sql .= " `user_session` varchar(64),";
127 $sql .= " `remote_ip` varchar(66) NOT NULL DEFAULT '127.0.0.1',"; // Needed by SHA-256 obfuscation.
128 $sql .= " `url` varchar(2083) NOT NULL DEFAULT '-',";
129 $sql .= ' `verb` enum(' . $verbs . ") NOT NULL DEFAULT 'unknown',";
130 $sql .= " `server` varchar(250) NOT NULL DEFAULT 'unknown',";
131 $sql .= " `referrer` varchar(250) NOT NULL DEFAULT '-',";
132 $sql .= " `user_agent` varchar(1024) NOT NULL DEFAULT '-',";
133 $sql .= " `file` varchar(250) NOT NULL DEFAULT 'unknown',";
134 $sql .= " `line` int(11) UNSIGNED NOT NULL DEFAULT '0',";
135 $sql .= " `classname` varchar(100) NOT NULL DEFAULT 'unknown',";
136 $sql .= " `function` varchar(100) NOT NULL DEFAULT 'unknown',";
137 $sql .= ' `trace` text,';
138 $sql .= ' PRIMARY KEY (`id`)';
139 $sql .= ") $charset_collate;";
140 // phpcs:ignore
141 $wpdb->query( $sql );
142 $sql = 'INSERT INTO ' . $wpdb->base_prefix . $this->bucket_name . '_mig (`timestamp`, `level`, `channel`, `class`, `component`, `version`, `code`, `message`, `site_id`, `site_name`, `user_id`, `user_name`, `user_session`, `remote_ip`, `url`, `verb`, `server`, `referrer`, `user_agent`, `file`, `line`, `classname`, `function`, `trace`) SELECT `timestamp`, `level`, `channel`, `class`, `component`, `version`, `code`, `message`, `site_id`, `site_name`, `user_id`, `user_name`, null AS user_session, `remote_ip`, `url`, `verb`, `server`, `referrer`, `user_agent`, `file`, `line`, `classname`, `function`, `trace` FROM ' . $wpdb->base_prefix . $this->bucket_name . ';';
143 // phpcs:ignore
144 if ( false === $wpdb->query( $sql ) ) {
145 throw new \Exception();
146 }
147 $sql = 'DROP TABLE IF EXISTS ' . $wpdb->base_prefix . $this->bucket_name;
148 // phpcs:ignore
149 if ( false === $wpdb->query( $sql ) ) {
150 throw new \Exception();
151 }
152 $sql = 'RENAME TABLE ' . $wpdb->base_prefix . $this->bucket_name . '_mig TO ' . $wpdb->base_prefix . $this->bucket_name . ';';
153 // phpcs:ignore
154 if ( false === $wpdb->query( $sql ) ) {
155 throw new \Exception();
156 }
157 $log = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
158 $log->info( 'WordPress events log successfully migrated.' );
159 } else {
160 throw new \Exception();
161 }
162 } catch ( \Throwable $e ) {
163 $log = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
164 $log->alert( 'Unable to migrate a WordPress events log. To continue you have to remove all loggers having "WordPress events log" type, then recreate them.' );
165 }
166 }
167
168 // Starting from 3.3.0, WordpressHandler allows to store instance name.
169 // We have to make a copy of the table, delete the old one, then rename the newly created table to avoid
170 // potential "#1118 - Row size too large" error that may appear if we just make a "ALTER TABLE ... MODIFY COLUMN ...".
171 if ( version_compare( '3.3.0', $from, '>' ) ) {
172 try {
173 $cl = [];
174 foreach ( ClassTypes::$classes as $c ) {
175 $cl[] = "'" . $c . "'";
176 }
177 $classes = implode( ',', $cl );
178 $cl = [];
179 foreach ( Http::$verbs as $c ) {
180 $cl[] = "'" . $c . "'";
181 }
182 $verbs = implode( ',', $cl );
183 if ( '' !== $this->bucket_name ) {
184 $charset_collate = 'DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci';
185 $sql = 'CREATE TABLE IF NOT EXISTS ' . $wpdb->base_prefix . $this->bucket_name . '_mig';
186 $sql .= ' (`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,';
187 $sql .= " `timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',";
188 $sql .= " `level` enum('emergency','alert','critical','error','warning','notice','info','debug','unknown') NOT NULL DEFAULT 'unknown',";
189 $sql .= " `channel` enum('cli','cron','ajax','xmlrpc','api','feed','wback','wfront','unknown') NOT NULL DEFAULT 'unknown',";
190 $sql .= ' `class` enum(' . $classes . ") NOT NULL DEFAULT 'unknown',";
191 $sql .= " `instance` varchar(66) NOT NULL DEFAULT 'undefined',";
192 $sql .= " `component` varchar(26) NOT NULL DEFAULT 'Unknown',";
193 $sql .= " `version` varchar(13) NOT NULL DEFAULT 'N/A',";
194 $sql .= " `code` int(11) UNSIGNED NOT NULL DEFAULT '0',";
195 $sql .= " `message` text,";
196 $sql .= " `site_id` int(11) UNSIGNED NOT NULL DEFAULT '0',";
197 $sql .= " `site_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
198 $sql .= " `user_id` varchar(66) NOT NULL DEFAULT '0',"; // Needed by SHA-256 pseudonymization.
199 $sql .= " `user_name` varchar(250) NOT NULL DEFAULT 'Unknown',";
200 $sql .= " `user_session` varchar(64),";
201 $sql .= " `remote_ip` varchar(66) NOT NULL DEFAULT '127.0.0.1',"; // Needed by SHA-256 obfuscation.
202 $sql .= " `url` varchar(2083) NOT NULL DEFAULT '-',";
203 $sql .= ' `verb` enum(' . $verbs . ") NOT NULL DEFAULT 'unknown',";
204 $sql .= " `server` varchar(250) NOT NULL DEFAULT 'unknown',";
205 $sql .= " `referrer` varchar(250) NOT NULL DEFAULT '-',";
206 $sql .= " `user_agent` varchar(1024) NOT NULL DEFAULT '-',";
207 $sql .= " `file` varchar(250) NOT NULL DEFAULT 'unknown',";
208 $sql .= " `line` int(11) UNSIGNED NOT NULL DEFAULT '0',";
209 $sql .= " `classname` varchar(100) NOT NULL DEFAULT 'unknown',";
210 $sql .= " `function` varchar(100) NOT NULL DEFAULT 'unknown',";
211 $sql .= ' `trace` text,';
212 $sql .= ' PRIMARY KEY (`id`)';
213 $sql .= ") $charset_collate;";
214 // phpcs:ignore
215 $wpdb->query( $sql );
216 $sql = 'INSERT INTO ' . $wpdb->base_prefix . $this->bucket_name . '_mig (`timestamp`, `level`, `channel`, `class`, `component`, `version`, `code`, `message`, `site_id`, `site_name`, `user_id`, `user_name`, `user_session`, `remote_ip`, `url`, `verb`, `server`, `referrer`, `user_agent`, `file`, `line`, `classname`, `function`, `trace`) SELECT `timestamp`, `level`, `channel`, `class`, `component`, `version`, `code`, `message`, `site_id`, `site_name`, `user_id`, `user_name`, null AS user_session, `remote_ip`, `url`, `verb`, `server`, `referrer`, `user_agent`, `file`, `line`, `classname`, `function`, `trace` FROM ' . $wpdb->base_prefix . $this->bucket_name . ';';
217 // phpcs:ignore
218 if ( false === $wpdb->query( $sql ) ) {
219 throw new \Exception();
220 }
221 $sql = 'DROP TABLE IF EXISTS ' . $wpdb->base_prefix . $this->bucket_name;
222 // phpcs:ignore
223 if ( false === $wpdb->query( $sql ) ) {
224 throw new \Exception();
225 }
226 $sql = 'RENAME TABLE ' . $wpdb->base_prefix . $this->bucket_name . '_mig TO ' . $wpdb->base_prefix . $this->bucket_name . ';';
227 // phpcs:ignore
228 if ( false === $wpdb->query( $sql ) ) {
229 throw new \Exception();
230 }
231 $log = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
232 $log->info( 'WordPress events log successfully migrated.' );
233 } else {
234 throw new \Exception();
235 }
236 } catch ( \Throwable $e ) {
237 $log = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
238 $log->alert( 'Unable to migrate a WordPress events log. To continue you have to remove all loggers having "WordPress events log" type, then recreate them.' );
239 }
240 }
241 }
242
243 }
244