Completed
Pull Request — master (#8946)
by Robin
113:16 queued 94:25
created
lib/private/Log.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -36,7 +36,6 @@
 block discarded – undo
36 36
 namespace OC;
37 37
 
38 38
 use InterfaSys\LogNormalizer\Normalizer;
39
-
40 39
 use OC\Log\File;
41 40
 use OCP\ILogger;
42 41
 use OCP\Support\CrashReport\IRegistry;
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-declare(strict_types=1);
2
+declare(strict_types = 1);
3 3
 /**
4 4
  * @copyright Copyright (c) 2016, ownCloud, Inc.
5 5
  *
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
 		// interpolate $message as defined in PSR-3
261 261
 		$replace = [];
262 262
 		foreach ($context as $key => $val) {
263
-			$replace['{' . $key . '}'] = $val;
263
+			$replace['{'.$key.'}'] = $val;
264 264
 		}
265 265
 		$message = strtr($message, $replace);
266 266
 
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
 
327 327
 	private function filterTrace(array $trace) {
328 328
 		$sensitiveValues = [];
329
-		$trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
329
+		$trace = array_map(function(array $traceLine) use (&$sensitiveValues) {
330 330
 			foreach ($this->methodsWithSensitiveParameters as $sensitiveMethod) {
331 331
 				if (strpos($traceLine['function'], $sensitiveMethod) !== false) {
332 332
 					$sensitiveValues = array_merge($sensitiveValues, $traceLine['args']);
@@ -336,14 +336,14 @@  discard block
 block discarded – undo
336 336
 			}
337 337
 			return $traceLine;
338 338
 		}, $trace);
339
-		return array_map(function (array $traceLine) use ($sensitiveValues) {
339
+		return array_map(function(array $traceLine) use ($sensitiveValues) {
340 340
 			$traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues);
341 341
 			return $traceLine;
342 342
 		}, $trace);
343 343
 	}
344 344
 
345 345
 	private function removeValuesFromArgs($args, $values) {
346
-		foreach($args as &$arg) {
346
+		foreach ($args as &$arg) {
347 347
 			if (in_array($arg, $values, true)) {
348 348
 				$arg = '*** sensitive parameter replaced ***';
349 349
 			} else if (is_array($arg)) {
Please login to merge, or discard this patch.
Indentation   +372 added lines, -372 removed lines patch added patch discarded remove patch
@@ -53,376 +53,376 @@
 block discarded – undo
53 53
  */
54 54
 class Log implements ILogger {
55 55
 
56
-	/** @var string */
57
-	private $logger;
58
-
59
-	/** @var SystemConfig */
60
-	private $config;
61
-
62
-	/** @var boolean|null cache the result of the log condition check for the request */
63
-	private $logConditionSatisfied = null;
64
-
65
-	/** @var Normalizer */
66
-	private $normalizer;
67
-
68
-	/** @var IRegistry */
69
-	private $crashReporters;
70
-
71
-	protected $methodsWithSensitiveParameters = [
72
-		// Session/User
73
-		'completeLogin',
74
-		'login',
75
-		'checkPassword',
76
-		'checkPasswordNoLogging',
77
-		'loginWithPassword',
78
-		'updatePrivateKeyPassword',
79
-		'validateUserPass',
80
-		'loginWithToken',
81
-		'{closure}',
82
-
83
-		// TokenProvider
84
-		'getToken',
85
-		'isTokenPassword',
86
-		'getPassword',
87
-		'decryptPassword',
88
-		'logClientIn',
89
-		'generateToken',
90
-		'validateToken',
91
-
92
-		// TwoFactorAuth
93
-		'solveChallenge',
94
-		'verifyChallenge',
95
-
96
-		// ICrypto
97
-		'calculateHMAC',
98
-		'encrypt',
99
-		'decrypt',
100
-
101
-		// LoginController
102
-		'tryLogin',
103
-		'confirmPassword',
104
-
105
-		// LDAP
106
-		'bind',
107
-		'areCredentialsValid',
108
-		'invokeLDAPMethod',
109
-
110
-		// Encryption
111
-		'storeKeyPair',
112
-		'setupUser',
113
-	];
114
-
115
-	/**
116
-	 * @param string $logger The logger that should be used
117
-	 * @param SystemConfig $config the system config object
118
-	 * @param Normalizer|null $normalizer
119
-	 * @param IRegistry|null $registry
120
-	 */
121
-	public function __construct($logger = null, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
122
-		// FIXME: Add this for backwards compatibility, should be fixed at some point probably
123
-		if ($config === null) {
124
-			$config = \OC::$server->getSystemConfig();
125
-		}
126
-
127
-		$this->config = $config;
128
-
129
-		// FIXME: Add this for backwards compatibility, should be fixed at some point probably
130
-		if ($logger === null) {
131
-			$logType = $this->config->getValue('log_type', 'file');
132
-			$this->logger = static::getLogClass($logType);
133
-			call_user_func([$this->logger, 'init']);
134
-		} else {
135
-			$this->logger = $logger;
136
-		}
137
-		if ($normalizer === null) {
138
-			$this->normalizer = new Normalizer();
139
-		} else {
140
-			$this->normalizer = $normalizer;
141
-		}
142
-		$this->crashReporters = $registry;
143
-	}
144
-
145
-	/**
146
-	 * System is unusable.
147
-	 *
148
-	 * @param string $message
149
-	 * @param array $context
150
-	 * @return void
151
-	 */
152
-	public function emergency(string $message, array $context = []) {
153
-		$this->log(Util::FATAL, $message, $context);
154
-	}
155
-
156
-	/**
157
-	 * Action must be taken immediately.
158
-	 *
159
-	 * Example: Entire website down, database unavailable, etc. This should
160
-	 * trigger the SMS alerts and wake you up.
161
-	 *
162
-	 * @param string $message
163
-	 * @param array $context
164
-	 * @return void
165
-	 */
166
-	public function alert(string $message, array $context = []) {
167
-		$this->log(Util::ERROR, $message, $context);
168
-	}
169
-
170
-	/**
171
-	 * Critical conditions.
172
-	 *
173
-	 * Example: Application component unavailable, unexpected exception.
174
-	 *
175
-	 * @param string $message
176
-	 * @param array $context
177
-	 * @return void
178
-	 */
179
-	public function critical(string $message, array $context = []) {
180
-		$this->log(Util::ERROR, $message, $context);
181
-	}
182
-
183
-	/**
184
-	 * Runtime errors that do not require immediate action but should typically
185
-	 * be logged and monitored.
186
-	 *
187
-	 * @param string $message
188
-	 * @param array $context
189
-	 * @return void
190
-	 */
191
-	public function error(string $message, array $context = []) {
192
-		$this->log(Util::ERROR, $message, $context);
193
-	}
194
-
195
-	/**
196
-	 * Exceptional occurrences that are not errors.
197
-	 *
198
-	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
199
-	 * that are not necessarily wrong.
200
-	 *
201
-	 * @param string $message
202
-	 * @param array $context
203
-	 * @return void
204
-	 */
205
-	public function warning(string $message, array $context = []) {
206
-		$this->log(Util::WARN, $message, $context);
207
-	}
208
-
209
-	/**
210
-	 * Normal but significant events.
211
-	 *
212
-	 * @param string $message
213
-	 * @param array $context
214
-	 * @return void
215
-	 */
216
-	public function notice(string $message, array $context = []) {
217
-		$this->log(Util::INFO, $message, $context);
218
-	}
219
-
220
-	/**
221
-	 * Interesting events.
222
-	 *
223
-	 * Example: User logs in, SQL logs.
224
-	 *
225
-	 * @param string $message
226
-	 * @param array $context
227
-	 * @return void
228
-	 */
229
-	public function info(string $message, array $context = []) {
230
-		$this->log(Util::INFO, $message, $context);
231
-	}
232
-
233
-	/**
234
-	 * Detailed debug information.
235
-	 *
236
-	 * @param string $message
237
-	 * @param array $context
238
-	 * @return void
239
-	 */
240
-	public function debug(string $message, array $context = []) {
241
-		$this->log(Util::DEBUG, $message, $context);
242
-	}
243
-
244
-
245
-	/**
246
-	 * Logs with an arbitrary level.
247
-	 *
248
-	 * @param int $level
249
-	 * @param string $message
250
-	 * @param array $context
251
-	 * @return void
252
-	 */
253
-	public function log(int $level, string $message, array $context = []) {
254
-		$minLevel = $this->getLogLevel($context);
255
-
256
-		array_walk($context, [$this->normalizer, 'format']);
257
-
258
-		$app = $context['app'] ?? 'no app in context';
259
-
260
-		// interpolate $message as defined in PSR-3
261
-		$replace = [];
262
-		foreach ($context as $key => $val) {
263
-			$replace['{' . $key . '}'] = $val;
264
-		}
265
-		$message = strtr($message, $replace);
266
-
267
-		if ($level >= $minLevel) {
268
-			$this->writeLog($app, $message, $level);
269
-		}
270
-	}
271
-
272
-	private function getLogLevel($context) {
273
-		/**
274
-		 * check for a special log condition - this enables an increased log on
275
-		 * a per request/user base
276
-		 */
277
-		if ($this->logConditionSatisfied === null) {
278
-			// default to false to just process this once per request
279
-			$this->logConditionSatisfied = false;
280
-			if (!empty($logCondition)) {
281
-
282
-				// check for secret token in the request
283
-				if (isset($logCondition['shared_secret'])) {
284
-					$request = \OC::$server->getRequest();
285
-
286
-					// if token is found in the request change set the log condition to satisfied
287
-					if ($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) {
288
-						$this->logConditionSatisfied = true;
289
-					}
290
-				}
291
-
292
-				// check for user
293
-				if (isset($logCondition['users'])) {
294
-					$user = \OC::$server->getUserSession()->getUser();
295
-
296
-					// if the user matches set the log condition to satisfied
297
-					if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
298
-						$this->logConditionSatisfied = true;
299
-					}
300
-				}
301
-			}
302
-		}
303
-
304
-		// if log condition is satisfied change the required log level to DEBUG
305
-		if ($this->logConditionSatisfied) {
306
-			return Util::DEBUG;
307
-		}
308
-
309
-		if (isset($context['app'])) {
310
-			$logCondition = $this->config->getValue('log.condition', []);
311
-			$app = $context['app'];
312
-
313
-			/**
314
-			 * check log condition based on the context of each log message
315
-			 * once this is met -> change the required log level to debug
316
-			 */
317
-			if (!empty($logCondition)
318
-				&& isset($logCondition['apps'])
319
-				&& in_array($app, $logCondition['apps'], true)) {
320
-				return Util::DEBUG;
321
-			}
322
-		}
323
-
324
-		return min($this->config->getValue('loglevel', Util::WARN), Util::FATAL);
325
-	}
326
-
327
-	private function filterTrace(array $trace) {
328
-		$sensitiveValues = [];
329
-		$trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
330
-			foreach ($this->methodsWithSensitiveParameters as $sensitiveMethod) {
331
-				if (strpos($traceLine['function'], $sensitiveMethod) !== false) {
332
-					$sensitiveValues = array_merge($sensitiveValues, $traceLine['args']);
333
-					$traceLine['args'] = ['*** sensitive parameters replaced ***'];
334
-					return $traceLine;
335
-				}
336
-			}
337
-			return $traceLine;
338
-		}, $trace);
339
-		return array_map(function (array $traceLine) use ($sensitiveValues) {
340
-			$traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues);
341
-			return $traceLine;
342
-		}, $trace);
343
-	}
344
-
345
-	private function removeValuesFromArgs($args, $values) {
346
-		foreach($args as &$arg) {
347
-			if (in_array($arg, $values, true)) {
348
-				$arg = '*** sensitive parameter replaced ***';
349
-			} else if (is_array($arg)) {
350
-				$arg = $this->removeValuesFromArgs($arg, $values);
351
-			}
352
-		}
353
-		return $args;
354
-	}
355
-
356
-	/**
357
-	 * Logs an exception very detailed
358
-	 *
359
-	 * @param \Exception|\Throwable $exception
360
-	 * @param array $context
361
-	 * @return void
362
-	 * @since 8.2.0
363
-	 */
364
-	public function logException(\Throwable $exception, array $context = []) {
365
-		$app = $context['app'] ?? 'no app in context';
366
-		$level = $context['level'] ?? Util::ERROR;
367
-
368
-		$data = [
369
-			'CustomMessage' => $context['message'] ?? '--',
370
-			'Exception' => get_class($exception),
371
-			'Message' => $exception->getMessage(),
372
-			'Code' => $exception->getCode(),
373
-			'Trace' => $this->filterTrace($exception->getTrace()),
374
-			'File' => $exception->getFile(),
375
-			'Line' => $exception->getLine(),
376
-		];
377
-		if ($exception instanceof HintException) {
378
-			$data['Hint'] = $exception->getHint();
379
-		}
380
-
381
-		$minLevel = $this->getLogLevel($context);
382
-
383
-		array_walk($context, [$this->normalizer, 'format']);
384
-
385
-		if ($level >= $minLevel) {
386
-			if ($this->logger !== File::class) {
387
-				$data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR);
388
-			}
389
-			$this->writeLog($app, $data, $level);
390
-		}
391
-
392
-		$context['level'] = $level;
393
-		if (!is_null($this->crashReporters)) {
394
-			$this->crashReporters->delegateReport($exception, $context);
395
-		}
396
-	}
397
-
398
-	/**
399
-	 * @param string $app
400
-	 * @param string|array $entry
401
-	 * @param int $level
402
-	 */
403
-	protected function writeLog(string $app, $entry, int $level) {
404
-		call_user_func([$this->logger, 'write'], $app, $entry, $level);
405
-	}
406
-
407
-	/**
408
-	 * @param string $logType
409
-	 * @return string
410
-	 * @internal
411
-	 */
412
-	public static function getLogClass(string $logType): string {
413
-		switch (strtolower($logType)) {
414
-			case 'errorlog':
415
-				return \OC\Log\Errorlog::class;
416
-			case 'syslog':
417
-				return \OC\Log\Syslog::class;
418
-			case 'file':
419
-				return \OC\Log\File::class;
420
-
421
-			// Backwards compatibility for old and fallback for unknown log types
422
-			case 'owncloud':
423
-			case 'nextcloud':
424
-			default:
425
-				return \OC\Log\File::class;
426
-		}
427
-	}
56
+    /** @var string */
57
+    private $logger;
58
+
59
+    /** @var SystemConfig */
60
+    private $config;
61
+
62
+    /** @var boolean|null cache the result of the log condition check for the request */
63
+    private $logConditionSatisfied = null;
64
+
65
+    /** @var Normalizer */
66
+    private $normalizer;
67
+
68
+    /** @var IRegistry */
69
+    private $crashReporters;
70
+
71
+    protected $methodsWithSensitiveParameters = [
72
+        // Session/User
73
+        'completeLogin',
74
+        'login',
75
+        'checkPassword',
76
+        'checkPasswordNoLogging',
77
+        'loginWithPassword',
78
+        'updatePrivateKeyPassword',
79
+        'validateUserPass',
80
+        'loginWithToken',
81
+        '{closure}',
82
+
83
+        // TokenProvider
84
+        'getToken',
85
+        'isTokenPassword',
86
+        'getPassword',
87
+        'decryptPassword',
88
+        'logClientIn',
89
+        'generateToken',
90
+        'validateToken',
91
+
92
+        // TwoFactorAuth
93
+        'solveChallenge',
94
+        'verifyChallenge',
95
+
96
+        // ICrypto
97
+        'calculateHMAC',
98
+        'encrypt',
99
+        'decrypt',
100
+
101
+        // LoginController
102
+        'tryLogin',
103
+        'confirmPassword',
104
+
105
+        // LDAP
106
+        'bind',
107
+        'areCredentialsValid',
108
+        'invokeLDAPMethod',
109
+
110
+        // Encryption
111
+        'storeKeyPair',
112
+        'setupUser',
113
+    ];
114
+
115
+    /**
116
+     * @param string $logger The logger that should be used
117
+     * @param SystemConfig $config the system config object
118
+     * @param Normalizer|null $normalizer
119
+     * @param IRegistry|null $registry
120
+     */
121
+    public function __construct($logger = null, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
122
+        // FIXME: Add this for backwards compatibility, should be fixed at some point probably
123
+        if ($config === null) {
124
+            $config = \OC::$server->getSystemConfig();
125
+        }
126
+
127
+        $this->config = $config;
128
+
129
+        // FIXME: Add this for backwards compatibility, should be fixed at some point probably
130
+        if ($logger === null) {
131
+            $logType = $this->config->getValue('log_type', 'file');
132
+            $this->logger = static::getLogClass($logType);
133
+            call_user_func([$this->logger, 'init']);
134
+        } else {
135
+            $this->logger = $logger;
136
+        }
137
+        if ($normalizer === null) {
138
+            $this->normalizer = new Normalizer();
139
+        } else {
140
+            $this->normalizer = $normalizer;
141
+        }
142
+        $this->crashReporters = $registry;
143
+    }
144
+
145
+    /**
146
+     * System is unusable.
147
+     *
148
+     * @param string $message
149
+     * @param array $context
150
+     * @return void
151
+     */
152
+    public function emergency(string $message, array $context = []) {
153
+        $this->log(Util::FATAL, $message, $context);
154
+    }
155
+
156
+    /**
157
+     * Action must be taken immediately.
158
+     *
159
+     * Example: Entire website down, database unavailable, etc. This should
160
+     * trigger the SMS alerts and wake you up.
161
+     *
162
+     * @param string $message
163
+     * @param array $context
164
+     * @return void
165
+     */
166
+    public function alert(string $message, array $context = []) {
167
+        $this->log(Util::ERROR, $message, $context);
168
+    }
169
+
170
+    /**
171
+     * Critical conditions.
172
+     *
173
+     * Example: Application component unavailable, unexpected exception.
174
+     *
175
+     * @param string $message
176
+     * @param array $context
177
+     * @return void
178
+     */
179
+    public function critical(string $message, array $context = []) {
180
+        $this->log(Util::ERROR, $message, $context);
181
+    }
182
+
183
+    /**
184
+     * Runtime errors that do not require immediate action but should typically
185
+     * be logged and monitored.
186
+     *
187
+     * @param string $message
188
+     * @param array $context
189
+     * @return void
190
+     */
191
+    public function error(string $message, array $context = []) {
192
+        $this->log(Util::ERROR, $message, $context);
193
+    }
194
+
195
+    /**
196
+     * Exceptional occurrences that are not errors.
197
+     *
198
+     * Example: Use of deprecated APIs, poor use of an API, undesirable things
199
+     * that are not necessarily wrong.
200
+     *
201
+     * @param string $message
202
+     * @param array $context
203
+     * @return void
204
+     */
205
+    public function warning(string $message, array $context = []) {
206
+        $this->log(Util::WARN, $message, $context);
207
+    }
208
+
209
+    /**
210
+     * Normal but significant events.
211
+     *
212
+     * @param string $message
213
+     * @param array $context
214
+     * @return void
215
+     */
216
+    public function notice(string $message, array $context = []) {
217
+        $this->log(Util::INFO, $message, $context);
218
+    }
219
+
220
+    /**
221
+     * Interesting events.
222
+     *
223
+     * Example: User logs in, SQL logs.
224
+     *
225
+     * @param string $message
226
+     * @param array $context
227
+     * @return void
228
+     */
229
+    public function info(string $message, array $context = []) {
230
+        $this->log(Util::INFO, $message, $context);
231
+    }
232
+
233
+    /**
234
+     * Detailed debug information.
235
+     *
236
+     * @param string $message
237
+     * @param array $context
238
+     * @return void
239
+     */
240
+    public function debug(string $message, array $context = []) {
241
+        $this->log(Util::DEBUG, $message, $context);
242
+    }
243
+
244
+
245
+    /**
246
+     * Logs with an arbitrary level.
247
+     *
248
+     * @param int $level
249
+     * @param string $message
250
+     * @param array $context
251
+     * @return void
252
+     */
253
+    public function log(int $level, string $message, array $context = []) {
254
+        $minLevel = $this->getLogLevel($context);
255
+
256
+        array_walk($context, [$this->normalizer, 'format']);
257
+
258
+        $app = $context['app'] ?? 'no app in context';
259
+
260
+        // interpolate $message as defined in PSR-3
261
+        $replace = [];
262
+        foreach ($context as $key => $val) {
263
+            $replace['{' . $key . '}'] = $val;
264
+        }
265
+        $message = strtr($message, $replace);
266
+
267
+        if ($level >= $minLevel) {
268
+            $this->writeLog($app, $message, $level);
269
+        }
270
+    }
271
+
272
+    private function getLogLevel($context) {
273
+        /**
274
+         * check for a special log condition - this enables an increased log on
275
+         * a per request/user base
276
+         */
277
+        if ($this->logConditionSatisfied === null) {
278
+            // default to false to just process this once per request
279
+            $this->logConditionSatisfied = false;
280
+            if (!empty($logCondition)) {
281
+
282
+                // check for secret token in the request
283
+                if (isset($logCondition['shared_secret'])) {
284
+                    $request = \OC::$server->getRequest();
285
+
286
+                    // if token is found in the request change set the log condition to satisfied
287
+                    if ($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) {
288
+                        $this->logConditionSatisfied = true;
289
+                    }
290
+                }
291
+
292
+                // check for user
293
+                if (isset($logCondition['users'])) {
294
+                    $user = \OC::$server->getUserSession()->getUser();
295
+
296
+                    // if the user matches set the log condition to satisfied
297
+                    if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
298
+                        $this->logConditionSatisfied = true;
299
+                    }
300
+                }
301
+            }
302
+        }
303
+
304
+        // if log condition is satisfied change the required log level to DEBUG
305
+        if ($this->logConditionSatisfied) {
306
+            return Util::DEBUG;
307
+        }
308
+
309
+        if (isset($context['app'])) {
310
+            $logCondition = $this->config->getValue('log.condition', []);
311
+            $app = $context['app'];
312
+
313
+            /**
314
+             * check log condition based on the context of each log message
315
+             * once this is met -> change the required log level to debug
316
+             */
317
+            if (!empty($logCondition)
318
+                && isset($logCondition['apps'])
319
+                && in_array($app, $logCondition['apps'], true)) {
320
+                return Util::DEBUG;
321
+            }
322
+        }
323
+
324
+        return min($this->config->getValue('loglevel', Util::WARN), Util::FATAL);
325
+    }
326
+
327
+    private function filterTrace(array $trace) {
328
+        $sensitiveValues = [];
329
+        $trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
330
+            foreach ($this->methodsWithSensitiveParameters as $sensitiveMethod) {
331
+                if (strpos($traceLine['function'], $sensitiveMethod) !== false) {
332
+                    $sensitiveValues = array_merge($sensitiveValues, $traceLine['args']);
333
+                    $traceLine['args'] = ['*** sensitive parameters replaced ***'];
334
+                    return $traceLine;
335
+                }
336
+            }
337
+            return $traceLine;
338
+        }, $trace);
339
+        return array_map(function (array $traceLine) use ($sensitiveValues) {
340
+            $traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues);
341
+            return $traceLine;
342
+        }, $trace);
343
+    }
344
+
345
+    private function removeValuesFromArgs($args, $values) {
346
+        foreach($args as &$arg) {
347
+            if (in_array($arg, $values, true)) {
348
+                $arg = '*** sensitive parameter replaced ***';
349
+            } else if (is_array($arg)) {
350
+                $arg = $this->removeValuesFromArgs($arg, $values);
351
+            }
352
+        }
353
+        return $args;
354
+    }
355
+
356
+    /**
357
+     * Logs an exception very detailed
358
+     *
359
+     * @param \Exception|\Throwable $exception
360
+     * @param array $context
361
+     * @return void
362
+     * @since 8.2.0
363
+     */
364
+    public function logException(\Throwable $exception, array $context = []) {
365
+        $app = $context['app'] ?? 'no app in context';
366
+        $level = $context['level'] ?? Util::ERROR;
367
+
368
+        $data = [
369
+            'CustomMessage' => $context['message'] ?? '--',
370
+            'Exception' => get_class($exception),
371
+            'Message' => $exception->getMessage(),
372
+            'Code' => $exception->getCode(),
373
+            'Trace' => $this->filterTrace($exception->getTrace()),
374
+            'File' => $exception->getFile(),
375
+            'Line' => $exception->getLine(),
376
+        ];
377
+        if ($exception instanceof HintException) {
378
+            $data['Hint'] = $exception->getHint();
379
+        }
380
+
381
+        $minLevel = $this->getLogLevel($context);
382
+
383
+        array_walk($context, [$this->normalizer, 'format']);
384
+
385
+        if ($level >= $minLevel) {
386
+            if ($this->logger !== File::class) {
387
+                $data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR);
388
+            }
389
+            $this->writeLog($app, $data, $level);
390
+        }
391
+
392
+        $context['level'] = $level;
393
+        if (!is_null($this->crashReporters)) {
394
+            $this->crashReporters->delegateReport($exception, $context);
395
+        }
396
+    }
397
+
398
+    /**
399
+     * @param string $app
400
+     * @param string|array $entry
401
+     * @param int $level
402
+     */
403
+    protected function writeLog(string $app, $entry, int $level) {
404
+        call_user_func([$this->logger, 'write'], $app, $entry, $level);
405
+    }
406
+
407
+    /**
408
+     * @param string $logType
409
+     * @return string
410
+     * @internal
411
+     */
412
+    public static function getLogClass(string $logType): string {
413
+        switch (strtolower($logType)) {
414
+            case 'errorlog':
415
+                return \OC\Log\Errorlog::class;
416
+            case 'syslog':
417
+                return \OC\Log\Syslog::class;
418
+            case 'file':
419
+                return \OC\Log\File::class;
420
+
421
+            // Backwards compatibility for old and fallback for unknown log types
422
+            case 'owncloud':
423
+            case 'nextcloud':
424
+            default:
425
+                return \OC\Log\File::class;
426
+        }
427
+    }
428 428
 }
Please login to merge, or discard this patch.
lib/private/Log/File.php 1 patch
Indentation   +156 added lines, -156 removed lines patch added patch discarded remove patch
@@ -44,166 +44,166 @@
 block discarded – undo
44 44
  */
45 45
 
46 46
 class File {
47
-	static protected $logFile;
47
+    static protected $logFile;
48 48
 
49
-	/**
50
-	 * Init class data
51
-	 */
52
-	public static function init() {
53
-		$systemConfig = \OC::$server->getSystemConfig();
54
-		$defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/nextcloud.log';
55
-		self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile);
49
+    /**
50
+     * Init class data
51
+     */
52
+    public static function init() {
53
+        $systemConfig = \OC::$server->getSystemConfig();
54
+        $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/nextcloud.log';
55
+        self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile);
56 56
 
57
-		/**
58
-		 * Fall back to default log file if specified logfile does not exist
59
-		 * and can not be created.
60
-		 */
61
-		if (!file_exists(self::$logFile)) {
62
-			if(!is_writable(dirname(self::$logFile))) {
63
-				self::$logFile = $defaultLogFile;
64
-			} else {
65
-				if(!touch(self::$logFile)) {
66
-					self::$logFile = $defaultLogFile;
67
-				}
68
-			}
69
-		}
70
-	}
57
+        /**
58
+         * Fall back to default log file if specified logfile does not exist
59
+         * and can not be created.
60
+         */
61
+        if (!file_exists(self::$logFile)) {
62
+            if(!is_writable(dirname(self::$logFile))) {
63
+                self::$logFile = $defaultLogFile;
64
+            } else {
65
+                if(!touch(self::$logFile)) {
66
+                    self::$logFile = $defaultLogFile;
67
+                }
68
+            }
69
+        }
70
+    }
71 71
 
72
-	/**
73
-	 * write a message in the log
74
-	 * @param string $app
75
-	 * @param string|array $message
76
-	 * @param int $level
77
-	 */
78
-	public static function write($app, $message, $level) {
79
-		$config = \OC::$server->getSystemConfig();
72
+    /**
73
+     * write a message in the log
74
+     * @param string $app
75
+     * @param string|array $message
76
+     * @param int $level
77
+     */
78
+    public static function write($app, $message, $level) {
79
+        $config = \OC::$server->getSystemConfig();
80 80
 
81
-		// default to ISO8601
82
-		$format = $config->getValue('logdateformat', \DateTime::ATOM);
83
-		$logTimeZone = $config->getValue('logtimezone', 'UTC');
84
-		try {
85
-			$timezone = new \DateTimeZone($logTimeZone);
86
-		} catch (\Exception $e) {
87
-			$timezone = new \DateTimeZone('UTC');
88
-		}
89
-		$time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", ""));
90
-		if ($time === false) {
91
-			$time = new \DateTime(null, $timezone);
92
-		} else {
93
-			// apply timezone if $time is created from UNIX timestamp
94
-			$time->setTimezone($timezone);
95
-		}
96
-		$request = \OC::$server->getRequest();
97
-		$reqId = $request->getId();
98
-		$remoteAddr = $request->getRemoteAddress();
99
-		// remove username/passwords from URLs before writing the to the log file
100
-		$time = $time->format($format);
101
-		$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
102
-		$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
103
-		if($config->getValue('installed', false)) {
104
-			$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
105
-		} else {
106
-			$user = '--';
107
-		}
108
-		$userAgent = $request->getHeader('User-Agent');
109
-		if ($userAgent === '') {
110
-			$userAgent = '--';
111
-		}
112
-		$version = $config->getValue('version', '');
113
-		$entry = compact(
114
-			'reqId',
115
-			'level',
116
-			'time',
117
-			'remoteAddr',
118
-			'user',
119
-			'app',
120
-			'method',
121
-			'url',
122
-			'message',
123
-			'userAgent',
124
-			'version'
125
-		);
126
-		// PHP's json_encode only accept proper UTF-8 strings, loop over all
127
-		// elements to ensure that they are properly UTF-8 compliant or convert
128
-		// them manually.
129
-		foreach($entry as $key => $value) {
130
-			if(is_string($value)) {
131
-				$testEncode = json_encode($value);
132
-				if($testEncode === false) {
133
-					$entry[$key] = utf8_encode($value);
134
-				}
135
-			}
136
-		}
137
-		$entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
138
-		$handle = @fopen(self::$logFile, 'a');
139
-		if ((fileperms(self::$logFile) & 0777) != 0640) {
140
-			@chmod(self::$logFile, 0640);
141
-		}
142
-		if ($handle) {
143
-			fwrite($handle, $entry."\n");
144
-			fclose($handle);
145
-		} else {
146
-			// Fall back to error_log
147
-			error_log($entry);
148
-		}
149
-		if (php_sapi_name() === 'cli-server') {
150
-			error_log($message, 4);
151
-		}
152
-	}
81
+        // default to ISO8601
82
+        $format = $config->getValue('logdateformat', \DateTime::ATOM);
83
+        $logTimeZone = $config->getValue('logtimezone', 'UTC');
84
+        try {
85
+            $timezone = new \DateTimeZone($logTimeZone);
86
+        } catch (\Exception $e) {
87
+            $timezone = new \DateTimeZone('UTC');
88
+        }
89
+        $time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", ""));
90
+        if ($time === false) {
91
+            $time = new \DateTime(null, $timezone);
92
+        } else {
93
+            // apply timezone if $time is created from UNIX timestamp
94
+            $time->setTimezone($timezone);
95
+        }
96
+        $request = \OC::$server->getRequest();
97
+        $reqId = $request->getId();
98
+        $remoteAddr = $request->getRemoteAddress();
99
+        // remove username/passwords from URLs before writing the to the log file
100
+        $time = $time->format($format);
101
+        $url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
102
+        $method = is_string($request->getMethod()) ? $request->getMethod() : '--';
103
+        if($config->getValue('installed', false)) {
104
+            $user = \OC_User::getUser() ? \OC_User::getUser() : '--';
105
+        } else {
106
+            $user = '--';
107
+        }
108
+        $userAgent = $request->getHeader('User-Agent');
109
+        if ($userAgent === '') {
110
+            $userAgent = '--';
111
+        }
112
+        $version = $config->getValue('version', '');
113
+        $entry = compact(
114
+            'reqId',
115
+            'level',
116
+            'time',
117
+            'remoteAddr',
118
+            'user',
119
+            'app',
120
+            'method',
121
+            'url',
122
+            'message',
123
+            'userAgent',
124
+            'version'
125
+        );
126
+        // PHP's json_encode only accept proper UTF-8 strings, loop over all
127
+        // elements to ensure that they are properly UTF-8 compliant or convert
128
+        // them manually.
129
+        foreach($entry as $key => $value) {
130
+            if(is_string($value)) {
131
+                $testEncode = json_encode($value);
132
+                if($testEncode === false) {
133
+                    $entry[$key] = utf8_encode($value);
134
+                }
135
+            }
136
+        }
137
+        $entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
138
+        $handle = @fopen(self::$logFile, 'a');
139
+        if ((fileperms(self::$logFile) & 0777) != 0640) {
140
+            @chmod(self::$logFile, 0640);
141
+        }
142
+        if ($handle) {
143
+            fwrite($handle, $entry."\n");
144
+            fclose($handle);
145
+        } else {
146
+            // Fall back to error_log
147
+            error_log($entry);
148
+        }
149
+        if (php_sapi_name() === 'cli-server') {
150
+            error_log($message, 4);
151
+        }
152
+    }
153 153
 
154
-	/**
155
-	 * get entries from the log in reverse chronological order
156
-	 * @param int $limit
157
-	 * @param int $offset
158
-	 * @return array
159
-	 */
160
-	public static function getEntries($limit=50, $offset=0) {
161
-		self::init();
162
-		$minLevel = \OC::$server->getSystemConfig()->getValue("loglevel", \OCP\Util::WARN);
163
-		$entries = array();
164
-		$handle = @fopen(self::$logFile, 'rb');
165
-		if ($handle) {
166
-			fseek($handle, 0, SEEK_END);
167
-			$pos = ftell($handle);
168
-			$line = '';
169
-			$entriesCount = 0;
170
-			$lines = 0;
171
-			// Loop through each character of the file looking for new lines
172
-			while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
173
-				fseek($handle, $pos);
174
-				$ch = fgetc($handle);
175
-				if ($ch == "\n" || $pos == 0) {
176
-					if ($line != '') {
177
-						// Add the first character if at the start of the file,
178
-						// because it doesn't hit the else in the loop
179
-						if ($pos == 0) {
180
-							$line = $ch.$line;
181
-						}
182
-						$entry = json_decode($line);
183
-						// Add the line as an entry if it is passed the offset and is equal or above the log level
184
-						if ($entry->level >= $minLevel) {
185
-							$lines++;
186
-							if ($lines > $offset) {
187
-								$entries[] = $entry;
188
-								$entriesCount++;
189
-							}
190
-						}
191
-						$line = '';
192
-					}
193
-				} else {
194
-					$line = $ch.$line;
195
-				}
196
-				$pos--;
197
-			}
198
-			fclose($handle);
199
-		}
200
-		return $entries;
201
-	}
154
+    /**
155
+     * get entries from the log in reverse chronological order
156
+     * @param int $limit
157
+     * @param int $offset
158
+     * @return array
159
+     */
160
+    public static function getEntries($limit=50, $offset=0) {
161
+        self::init();
162
+        $minLevel = \OC::$server->getSystemConfig()->getValue("loglevel", \OCP\Util::WARN);
163
+        $entries = array();
164
+        $handle = @fopen(self::$logFile, 'rb');
165
+        if ($handle) {
166
+            fseek($handle, 0, SEEK_END);
167
+            $pos = ftell($handle);
168
+            $line = '';
169
+            $entriesCount = 0;
170
+            $lines = 0;
171
+            // Loop through each character of the file looking for new lines
172
+            while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
173
+                fseek($handle, $pos);
174
+                $ch = fgetc($handle);
175
+                if ($ch == "\n" || $pos == 0) {
176
+                    if ($line != '') {
177
+                        // Add the first character if at the start of the file,
178
+                        // because it doesn't hit the else in the loop
179
+                        if ($pos == 0) {
180
+                            $line = $ch.$line;
181
+                        }
182
+                        $entry = json_decode($line);
183
+                        // Add the line as an entry if it is passed the offset and is equal or above the log level
184
+                        if ($entry->level >= $minLevel) {
185
+                            $lines++;
186
+                            if ($lines > $offset) {
187
+                                $entries[] = $entry;
188
+                                $entriesCount++;
189
+                            }
190
+                        }
191
+                        $line = '';
192
+                    }
193
+                } else {
194
+                    $line = $ch.$line;
195
+                }
196
+                $pos--;
197
+            }
198
+            fclose($handle);
199
+        }
200
+        return $entries;
201
+    }
202 202
 
203
-	/**
204
-	 * @return string
205
-	 */
206
-	public static function getLogFilePath() {
207
-		return self::$logFile;
208
-	}
203
+    /**
204
+     * @return string
205
+     */
206
+    public static function getLogFilePath() {
207
+        return self::$logFile;
208
+    }
209 209
 }
Please login to merge, or discard this patch.