Passed
Push — master ( 35aa34...c9fcf5 )
by Roeland
49:09 queued 29:27
created
lib/private/Log.php 1 patch
Indentation   +321 added lines, -321 removed lines patch added patch discarded remove patch
@@ -56,325 +56,325 @@
 block discarded – undo
56 56
  */
57 57
 class Log implements ILogger, IDataLogger {
58 58
 
59
-	/** @var IWriter */
60
-	private $logger;
61
-
62
-	/** @var SystemConfig */
63
-	private $config;
64
-
65
-	/** @var boolean|null cache the result of the log condition check for the request */
66
-	private $logConditionSatisfied = null;
67
-
68
-	/** @var Normalizer */
69
-	private $normalizer;
70
-
71
-	/** @var IRegistry */
72
-	private $crashReporters;
73
-
74
-	/**
75
-	 * @param IWriter $logger The logger that should be used
76
-	 * @param SystemConfig $config the system config object
77
-	 * @param Normalizer|null $normalizer
78
-	 * @param IRegistry|null $registry
79
-	 */
80
-	public function __construct(IWriter $logger, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
81
-		// FIXME: Add this for backwards compatibility, should be fixed at some point probably
82
-		if ($config === null) {
83
-			$config = \OC::$server->getSystemConfig();
84
-		}
85
-
86
-		$this->config = $config;
87
-		$this->logger = $logger;
88
-		if ($normalizer === null) {
89
-			$this->normalizer = new Normalizer();
90
-		} else {
91
-			$this->normalizer = $normalizer;
92
-		}
93
-		$this->crashReporters = $registry;
94
-	}
95
-
96
-	/**
97
-	 * System is unusable.
98
-	 *
99
-	 * @param string $message
100
-	 * @param array $context
101
-	 * @return void
102
-	 */
103
-	public function emergency(string $message, array $context = []) {
104
-		$this->log(ILogger::FATAL, $message, $context);
105
-	}
106
-
107
-	/**
108
-	 * Action must be taken immediately.
109
-	 *
110
-	 * Example: Entire website down, database unavailable, etc. This should
111
-	 * trigger the SMS alerts and wake you up.
112
-	 *
113
-	 * @param string $message
114
-	 * @param array $context
115
-	 * @return void
116
-	 */
117
-	public function alert(string $message, array $context = []) {
118
-		$this->log(ILogger::ERROR, $message, $context);
119
-	}
120
-
121
-	/**
122
-	 * Critical conditions.
123
-	 *
124
-	 * Example: Application component unavailable, unexpected exception.
125
-	 *
126
-	 * @param string $message
127
-	 * @param array $context
128
-	 * @return void
129
-	 */
130
-	public function critical(string $message, array $context = []) {
131
-		$this->log(ILogger::ERROR, $message, $context);
132
-	}
133
-
134
-	/**
135
-	 * Runtime errors that do not require immediate action but should typically
136
-	 * be logged and monitored.
137
-	 *
138
-	 * @param string $message
139
-	 * @param array $context
140
-	 * @return void
141
-	 */
142
-	public function error(string $message, array $context = []) {
143
-		$this->log(ILogger::ERROR, $message, $context);
144
-	}
145
-
146
-	/**
147
-	 * Exceptional occurrences that are not errors.
148
-	 *
149
-	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
150
-	 * that are not necessarily wrong.
151
-	 *
152
-	 * @param string $message
153
-	 * @param array $context
154
-	 * @return void
155
-	 */
156
-	public function warning(string $message, array $context = []) {
157
-		$this->log(ILogger::WARN, $message, $context);
158
-	}
159
-
160
-	/**
161
-	 * Normal but significant events.
162
-	 *
163
-	 * @param string $message
164
-	 * @param array $context
165
-	 * @return void
166
-	 */
167
-	public function notice(string $message, array $context = []) {
168
-		$this->log(ILogger::INFO, $message, $context);
169
-	}
170
-
171
-	/**
172
-	 * Interesting events.
173
-	 *
174
-	 * Example: User logs in, SQL logs.
175
-	 *
176
-	 * @param string $message
177
-	 * @param array $context
178
-	 * @return void
179
-	 */
180
-	public function info(string $message, array $context = []) {
181
-		$this->log(ILogger::INFO, $message, $context);
182
-	}
183
-
184
-	/**
185
-	 * Detailed debug information.
186
-	 *
187
-	 * @param string $message
188
-	 * @param array $context
189
-	 * @return void
190
-	 */
191
-	public function debug(string $message, array $context = []) {
192
-		$this->log(ILogger::DEBUG, $message, $context);
193
-	}
194
-
195
-
196
-	/**
197
-	 * Logs with an arbitrary level.
198
-	 *
199
-	 * @param int $level
200
-	 * @param string $message
201
-	 * @param array $context
202
-	 * @return void
203
-	 */
204
-	public function log(int $level, string $message, array $context = []) {
205
-		$minLevel = $this->getLogLevel($context);
206
-
207
-		array_walk($context, [$this->normalizer, 'format']);
208
-
209
-		$app = $context['app'] ?? 'no app in context';
210
-
211
-		// interpolate $message as defined in PSR-3
212
-		$replace = [];
213
-		foreach ($context as $key => $val) {
214
-			$replace['{' . $key . '}'] = $val;
215
-		}
216
-		$message = strtr($message, $replace);
217
-
218
-		try {
219
-			if ($level >= $minLevel) {
220
-				$this->writeLog($app, $message, $level);
221
-
222
-				if ($this->crashReporters !== null) {
223
-					$messageContext = array_merge(
224
-						$context,
225
-						[
226
-							'level' => $level
227
-						]
228
-					);
229
-					$this->crashReporters->delegateMessage($message, $messageContext);
230
-				}
231
-			} else {
232
-				if ($this->crashReporters !== null) {
233
-					$this->crashReporters->delegateBreadcrumb($message, 'log', $context);
234
-				}
235
-			}
236
-		} catch (\Throwable $e) {
237
-			// make sure we dont hard crash if logging fails
238
-		}
239
-	}
240
-
241
-	private function getLogLevel($context) {
242
-		$logCondition = $this->config->getValue('log.condition', []);
243
-
244
-		/**
245
-		 * check for a special log condition - this enables an increased log on
246
-		 * a per request/user base
247
-		 */
248
-		if ($this->logConditionSatisfied === null) {
249
-			// default to false to just process this once per request
250
-			$this->logConditionSatisfied = false;
251
-			if (!empty($logCondition)) {
252
-
253
-				// check for secret token in the request
254
-				if (isset($logCondition['shared_secret'])) {
255
-					$request = \OC::$server->getRequest();
256
-
257
-					if ($request->getMethod() === 'PUT' &&
258
-						strpos($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false &&
259
-						strpos($request->getHeader('Content-Type'), 'application/json') === false) {
260
-						$logSecretRequest = '';
261
-					} else {
262
-						$logSecretRequest = $request->getParam('log_secret', '');
263
-					}
264
-
265
-					// if token is found in the request change set the log condition to satisfied
266
-					if ($request && hash_equals($logCondition['shared_secret'], $logSecretRequest)) {
267
-						$this->logConditionSatisfied = true;
268
-					}
269
-				}
270
-
271
-				// check for user
272
-				if (isset($logCondition['users'])) {
273
-					$user = \OC::$server->getUserSession()->getUser();
274
-
275
-					// if the user matches set the log condition to satisfied
276
-					if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
277
-						$this->logConditionSatisfied = true;
278
-					}
279
-				}
280
-			}
281
-		}
282
-
283
-		// if log condition is satisfied change the required log level to DEBUG
284
-		if ($this->logConditionSatisfied) {
285
-			return ILogger::DEBUG;
286
-		}
287
-
288
-		if (isset($context['app'])) {
289
-			$app = $context['app'];
290
-
291
-			/**
292
-			 * check log condition based on the context of each log message
293
-			 * once this is met -> change the required log level to debug
294
-			 */
295
-			if (!empty($logCondition)
296
-				&& isset($logCondition['apps'])
297
-				&& in_array($app, $logCondition['apps'], true)) {
298
-				return ILogger::DEBUG;
299
-			}
300
-		}
301
-
302
-		return min($this->config->getValue('loglevel', ILogger::WARN), ILogger::FATAL);
303
-	}
304
-
305
-	/**
306
-	 * Logs an exception very detailed
307
-	 *
308
-	 * @param \Exception|\Throwable $exception
309
-	 * @param array $context
310
-	 * @return void
311
-	 * @since 8.2.0
312
-	 */
313
-	public function logException(\Throwable $exception, array $context = []) {
314
-		$app = $context['app'] ?? 'no app in context';
315
-		$level = $context['level'] ?? ILogger::ERROR;
316
-
317
-		$serializer = new ExceptionSerializer($this->config);
318
-		$data = $serializer->serializeException($exception);
319
-		$data['CustomMessage'] = $context['message'] ?? '--';
320
-
321
-		$minLevel = $this->getLogLevel($context);
322
-
323
-		array_walk($context, [$this->normalizer, 'format']);
324
-
325
-		try {
326
-			if ($level >= $minLevel) {
327
-				if (!$this->logger instanceof IFileBased) {
328
-					$data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES);
329
-				}
330
-				$this->writeLog($app, $data, $level);
331
-			}
332
-
333
-			$context['level'] = $level;
334
-			if (!is_null($this->crashReporters)) {
335
-				$this->crashReporters->delegateReport($exception, $context);
336
-			}
337
-		} catch (\Throwable $e) {
338
-			// make sure we dont hard crash if logging fails
339
-		}
340
-	}
341
-
342
-	public function logData(string $message, array $data, array $context = []): void {
343
-		$app = $context['app'] ?? 'no app in context';
344
-		$level = $context['level'] ?? ILogger::ERROR;
345
-
346
-		$minLevel = $this->getLogLevel($context);
347
-
348
-		array_walk($context, [$this->normalizer, 'format']);
349
-
350
-		try {
351
-			if ($level >= $minLevel) {
352
-				$data['message'] = $message;
353
-				if (!$this->logger instanceof IFileBased) {
354
-					$data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES);
355
-				}
356
-				$this->writeLog($app, $data, $level);
357
-			}
358
-
359
-			$context['level'] = $level;
360
-		} catch (\Throwable $e) {
361
-			// make sure we dont hard crash if logging fails
362
-		}
363
-	}
364
-
365
-	/**
366
-	 * @param string $app
367
-	 * @param string|array $entry
368
-	 * @param int $level
369
-	 */
370
-	protected function writeLog(string $app, $entry, int $level) {
371
-		$this->logger->write($app, $entry, $level);
372
-	}
373
-
374
-	public function getLogPath():string {
375
-		if ($this->logger instanceof IFileBased) {
376
-			return $this->logger->getLogFilePath();
377
-		}
378
-		throw new \RuntimeException('Log implementation has no path');
379
-	}
59
+    /** @var IWriter */
60
+    private $logger;
61
+
62
+    /** @var SystemConfig */
63
+    private $config;
64
+
65
+    /** @var boolean|null cache the result of the log condition check for the request */
66
+    private $logConditionSatisfied = null;
67
+
68
+    /** @var Normalizer */
69
+    private $normalizer;
70
+
71
+    /** @var IRegistry */
72
+    private $crashReporters;
73
+
74
+    /**
75
+     * @param IWriter $logger The logger that should be used
76
+     * @param SystemConfig $config the system config object
77
+     * @param Normalizer|null $normalizer
78
+     * @param IRegistry|null $registry
79
+     */
80
+    public function __construct(IWriter $logger, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
81
+        // FIXME: Add this for backwards compatibility, should be fixed at some point probably
82
+        if ($config === null) {
83
+            $config = \OC::$server->getSystemConfig();
84
+        }
85
+
86
+        $this->config = $config;
87
+        $this->logger = $logger;
88
+        if ($normalizer === null) {
89
+            $this->normalizer = new Normalizer();
90
+        } else {
91
+            $this->normalizer = $normalizer;
92
+        }
93
+        $this->crashReporters = $registry;
94
+    }
95
+
96
+    /**
97
+     * System is unusable.
98
+     *
99
+     * @param string $message
100
+     * @param array $context
101
+     * @return void
102
+     */
103
+    public function emergency(string $message, array $context = []) {
104
+        $this->log(ILogger::FATAL, $message, $context);
105
+    }
106
+
107
+    /**
108
+     * Action must be taken immediately.
109
+     *
110
+     * Example: Entire website down, database unavailable, etc. This should
111
+     * trigger the SMS alerts and wake you up.
112
+     *
113
+     * @param string $message
114
+     * @param array $context
115
+     * @return void
116
+     */
117
+    public function alert(string $message, array $context = []) {
118
+        $this->log(ILogger::ERROR, $message, $context);
119
+    }
120
+
121
+    /**
122
+     * Critical conditions.
123
+     *
124
+     * Example: Application component unavailable, unexpected exception.
125
+     *
126
+     * @param string $message
127
+     * @param array $context
128
+     * @return void
129
+     */
130
+    public function critical(string $message, array $context = []) {
131
+        $this->log(ILogger::ERROR, $message, $context);
132
+    }
133
+
134
+    /**
135
+     * Runtime errors that do not require immediate action but should typically
136
+     * be logged and monitored.
137
+     *
138
+     * @param string $message
139
+     * @param array $context
140
+     * @return void
141
+     */
142
+    public function error(string $message, array $context = []) {
143
+        $this->log(ILogger::ERROR, $message, $context);
144
+    }
145
+
146
+    /**
147
+     * Exceptional occurrences that are not errors.
148
+     *
149
+     * Example: Use of deprecated APIs, poor use of an API, undesirable things
150
+     * that are not necessarily wrong.
151
+     *
152
+     * @param string $message
153
+     * @param array $context
154
+     * @return void
155
+     */
156
+    public function warning(string $message, array $context = []) {
157
+        $this->log(ILogger::WARN, $message, $context);
158
+    }
159
+
160
+    /**
161
+     * Normal but significant events.
162
+     *
163
+     * @param string $message
164
+     * @param array $context
165
+     * @return void
166
+     */
167
+    public function notice(string $message, array $context = []) {
168
+        $this->log(ILogger::INFO, $message, $context);
169
+    }
170
+
171
+    /**
172
+     * Interesting events.
173
+     *
174
+     * Example: User logs in, SQL logs.
175
+     *
176
+     * @param string $message
177
+     * @param array $context
178
+     * @return void
179
+     */
180
+    public function info(string $message, array $context = []) {
181
+        $this->log(ILogger::INFO, $message, $context);
182
+    }
183
+
184
+    /**
185
+     * Detailed debug information.
186
+     *
187
+     * @param string $message
188
+     * @param array $context
189
+     * @return void
190
+     */
191
+    public function debug(string $message, array $context = []) {
192
+        $this->log(ILogger::DEBUG, $message, $context);
193
+    }
194
+
195
+
196
+    /**
197
+     * Logs with an arbitrary level.
198
+     *
199
+     * @param int $level
200
+     * @param string $message
201
+     * @param array $context
202
+     * @return void
203
+     */
204
+    public function log(int $level, string $message, array $context = []) {
205
+        $minLevel = $this->getLogLevel($context);
206
+
207
+        array_walk($context, [$this->normalizer, 'format']);
208
+
209
+        $app = $context['app'] ?? 'no app in context';
210
+
211
+        // interpolate $message as defined in PSR-3
212
+        $replace = [];
213
+        foreach ($context as $key => $val) {
214
+            $replace['{' . $key . '}'] = $val;
215
+        }
216
+        $message = strtr($message, $replace);
217
+
218
+        try {
219
+            if ($level >= $minLevel) {
220
+                $this->writeLog($app, $message, $level);
221
+
222
+                if ($this->crashReporters !== null) {
223
+                    $messageContext = array_merge(
224
+                        $context,
225
+                        [
226
+                            'level' => $level
227
+                        ]
228
+                    );
229
+                    $this->crashReporters->delegateMessage($message, $messageContext);
230
+                }
231
+            } else {
232
+                if ($this->crashReporters !== null) {
233
+                    $this->crashReporters->delegateBreadcrumb($message, 'log', $context);
234
+                }
235
+            }
236
+        } catch (\Throwable $e) {
237
+            // make sure we dont hard crash if logging fails
238
+        }
239
+    }
240
+
241
+    private function getLogLevel($context) {
242
+        $logCondition = $this->config->getValue('log.condition', []);
243
+
244
+        /**
245
+         * check for a special log condition - this enables an increased log on
246
+         * a per request/user base
247
+         */
248
+        if ($this->logConditionSatisfied === null) {
249
+            // default to false to just process this once per request
250
+            $this->logConditionSatisfied = false;
251
+            if (!empty($logCondition)) {
252
+
253
+                // check for secret token in the request
254
+                if (isset($logCondition['shared_secret'])) {
255
+                    $request = \OC::$server->getRequest();
256
+
257
+                    if ($request->getMethod() === 'PUT' &&
258
+                        strpos($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false &&
259
+                        strpos($request->getHeader('Content-Type'), 'application/json') === false) {
260
+                        $logSecretRequest = '';
261
+                    } else {
262
+                        $logSecretRequest = $request->getParam('log_secret', '');
263
+                    }
264
+
265
+                    // if token is found in the request change set the log condition to satisfied
266
+                    if ($request && hash_equals($logCondition['shared_secret'], $logSecretRequest)) {
267
+                        $this->logConditionSatisfied = true;
268
+                    }
269
+                }
270
+
271
+                // check for user
272
+                if (isset($logCondition['users'])) {
273
+                    $user = \OC::$server->getUserSession()->getUser();
274
+
275
+                    // if the user matches set the log condition to satisfied
276
+                    if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
277
+                        $this->logConditionSatisfied = true;
278
+                    }
279
+                }
280
+            }
281
+        }
282
+
283
+        // if log condition is satisfied change the required log level to DEBUG
284
+        if ($this->logConditionSatisfied) {
285
+            return ILogger::DEBUG;
286
+        }
287
+
288
+        if (isset($context['app'])) {
289
+            $app = $context['app'];
290
+
291
+            /**
292
+             * check log condition based on the context of each log message
293
+             * once this is met -> change the required log level to debug
294
+             */
295
+            if (!empty($logCondition)
296
+                && isset($logCondition['apps'])
297
+                && in_array($app, $logCondition['apps'], true)) {
298
+                return ILogger::DEBUG;
299
+            }
300
+        }
301
+
302
+        return min($this->config->getValue('loglevel', ILogger::WARN), ILogger::FATAL);
303
+    }
304
+
305
+    /**
306
+     * Logs an exception very detailed
307
+     *
308
+     * @param \Exception|\Throwable $exception
309
+     * @param array $context
310
+     * @return void
311
+     * @since 8.2.0
312
+     */
313
+    public function logException(\Throwable $exception, array $context = []) {
314
+        $app = $context['app'] ?? 'no app in context';
315
+        $level = $context['level'] ?? ILogger::ERROR;
316
+
317
+        $serializer = new ExceptionSerializer($this->config);
318
+        $data = $serializer->serializeException($exception);
319
+        $data['CustomMessage'] = $context['message'] ?? '--';
320
+
321
+        $minLevel = $this->getLogLevel($context);
322
+
323
+        array_walk($context, [$this->normalizer, 'format']);
324
+
325
+        try {
326
+            if ($level >= $minLevel) {
327
+                if (!$this->logger instanceof IFileBased) {
328
+                    $data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES);
329
+                }
330
+                $this->writeLog($app, $data, $level);
331
+            }
332
+
333
+            $context['level'] = $level;
334
+            if (!is_null($this->crashReporters)) {
335
+                $this->crashReporters->delegateReport($exception, $context);
336
+            }
337
+        } catch (\Throwable $e) {
338
+            // make sure we dont hard crash if logging fails
339
+        }
340
+    }
341
+
342
+    public function logData(string $message, array $data, array $context = []): void {
343
+        $app = $context['app'] ?? 'no app in context';
344
+        $level = $context['level'] ?? ILogger::ERROR;
345
+
346
+        $minLevel = $this->getLogLevel($context);
347
+
348
+        array_walk($context, [$this->normalizer, 'format']);
349
+
350
+        try {
351
+            if ($level >= $minLevel) {
352
+                $data['message'] = $message;
353
+                if (!$this->logger instanceof IFileBased) {
354
+                    $data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES);
355
+                }
356
+                $this->writeLog($app, $data, $level);
357
+            }
358
+
359
+            $context['level'] = $level;
360
+        } catch (\Throwable $e) {
361
+            // make sure we dont hard crash if logging fails
362
+        }
363
+    }
364
+
365
+    /**
366
+     * @param string $app
367
+     * @param string|array $entry
368
+     * @param int $level
369
+     */
370
+    protected function writeLog(string $app, $entry, int $level) {
371
+        $this->logger->write($app, $entry, $level);
372
+    }
373
+
374
+    public function getLogPath():string {
375
+        if ($this->logger instanceof IFileBased) {
376
+            return $this->logger->getLogFilePath();
377
+        }
378
+        throw new \RuntimeException('Log implementation has no path');
379
+    }
380 380
 }
Please login to merge, or discard this patch.