Passed
Push — master ( 74f9e2...c6d721 )
by Christoph
04:03 queued 01:59
created

SentryReporterAdapter   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 86
rs 10
c 0
b 0
f 0
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A report() 0 10 3
A collect() 0 7 1
A buildSentryContext() 0 26 5
A __construct() 0 8 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @author Christoph Wurst <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\Sentry\Reporter;
26
27
use Exception;
28
use OCA\Sentry\Helper\CredentialStoreHelper;
29
use OCP\Authentication\Exceptions\CredentialsUnavailableException;
30
use OCP\IConfig;
31
use OCP\ILogger;
32
use OCP\IUserSession;
33
use OCP\Support\CrashReport\ICollectBreadcrumbs;
0 ignored issues
show
Bug introduced by
The type OCP\Support\CrashReport\ICollectBreadcrumbs was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use OCP\Support\CrashReport\IReporter;
35
use Raven_Client;
36
use Throwable;
37
38
class SentryReporterAdapter implements IReporter, ICollectBreadcrumbs {
39
40
	/** @var IUserSession */
41
	protected $userSession;
42
43
	/** @var Raven_Client */
44
	protected $client;
45
46
	/** @var CredentialStoreHelper */
47
	private $credentialStoreHelper;
48
49
	/** @var array mapping of log levels */
50
	protected $levels = [
51
		ILogger::DEBUG => 'debug',
52
		ILogger::INFO => 'info',
53
		ILogger::WARN => 'warning',
54
		ILogger::ERROR => 'error',
55
		ILogger::FATAL => 'fatal',
56
	];
57
58
	/** @var int */
59
	protected $minimumLogLevel;
60
61
	public function __construct(Raven_Client $client,
62
								IUserSession $userSession,
63
								IConfig $config,
64
								CredentialStoreHelper $credentialStoreHelper) {
65
		$this->client = $client;
66
		$this->userSession = $userSession;
67
		$this->minimumLogLevel = (int)$config->getSystemValue('sentry.minimum.log.level', ILogger::WARN);
68
		$this->credentialStoreHelper = $credentialStoreHelper;
69
	}
70
71
	/**
72
	 * Report an (unhandled) exception to Sentry
73
	 *
74
	 * @param Exception|Throwable $exception
75
	 * @param array $context
76
	 */
77
	public function report($exception, array $context = []) {
78
		if (isset($context['level'])
79
			&& $context['level'] < $this->minimumLogLevel) {
80
			// TODO: report as breadcrumb instead?
81
			return;
82
		}
83
84
		$sentryContext = $this->buildSentryContext($context);
85
86
		$this->client->captureException($exception, $sentryContext);
87
	}
88
89
	protected function buildSentryContext(array $context): array {
90
		$sentryContext = [];
91
		$sentryContext['tags'] = [];
92
93
		if (isset($context['level'])) {
94
			$sentryContext['level'] = $this->levels[$context['level']];
95
		}
96
		if (isset($context['app'])) {
97
			$sentryContext['tags']['app'] = $context['app'];
98
		}
99
100
		$user = $this->userSession->getUser();
101
		if (!is_null($user)) {
102
			$sentryContext['user'] = [
103
				'id' => $user->getUID(),
104
			];
105
106
			// Try to obtain the login name as well
107
			try {
108
				$credentials = $this->credentialStoreHelper->getLoginCredentials();
109
				$sentryContext['user']['username'] = $credentials->getLoginName();
110
			} catch (CredentialsUnavailableException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
111
112
			}
113
		}
114
		return $sentryContext;
115
	}
116
117
	public function collect(string $message, string $category, array $context = []) {
118
		$sentryContext = $this->buildSentryContext($context);
119
120
		$sentryContext['message'] = $message;
121
		$sentryContext['category'] = $category;
122
123
		$this->client->breadcrumbs->record($sentryContext);
124
	}
125
126
}
127