2023-01-29 18:17:50 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace EesyPHP;
|
|
|
|
|
|
|
|
use Throwable;
|
|
|
|
use Exception;
|
|
|
|
|
|
|
|
class SentryIntegration {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sentry DSN
|
|
|
|
* @var string|null
|
|
|
|
*/
|
|
|
|
protected static $dsn = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Types of PHP error to log in Sentry
|
|
|
|
* @see https://www.php.net/manual/fr/errorfunc.constants.php
|
|
|
|
* @var array<int>
|
|
|
|
*/
|
2023-03-01 16:22:11 +01:00
|
|
|
protected static $php_error_types;
|
2023-01-29 18:17:50 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialization
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-03-01 16:22:11 +01:00
|
|
|
public static function init() {
|
2023-03-01 11:01:54 +01:00
|
|
|
// In phpstan context, do not initialize
|
2023-07-26 16:51:16 +02:00
|
|
|
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) // @phpstan-ignore-line
|
2023-03-01 11:01:54 +01:00
|
|
|
return;
|
2023-03-01 16:22:11 +01:00
|
|
|
// Set config default values
|
|
|
|
App :: set_default(
|
|
|
|
'sentry',
|
|
|
|
array(
|
|
|
|
'dsn' => null,
|
|
|
|
'traces_sample_rate' => 0.2,
|
|
|
|
'php_error_types' => array(
|
|
|
|
'E_ERROR', 'E_PARSE', 'E_CORE_ERROR', 'E_COMPILE_ERROR', 'E_USER_ERROR',
|
|
|
|
'E_RECOVERABLE_ERROR', 'E_DEPRECATED',
|
2023-01-29 18:17:50 +01:00
|
|
|
),
|
2023-03-01 16:22:11 +01:00
|
|
|
)
|
|
|
|
);
|
2024-12-13 15:18:20 +01:00
|
|
|
|
|
|
|
self :: $dsn = App::get('sentry.dsn');
|
|
|
|
if (!self :: $dsn) {
|
|
|
|
Log :: trace("SentryIntegration::init(): no DSN configured");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-01 16:22:11 +01:00
|
|
|
\Sentry\init([
|
2024-12-13 15:18:20 +01:00
|
|
|
'dsn' => self :: $dsn,
|
2023-03-01 16:22:11 +01:00
|
|
|
'traces_sample_rate' => App::get('sentry.traces_sample_rate', null, 'float'),
|
2023-01-29 18:17:50 +01:00
|
|
|
]);
|
|
|
|
|
|
|
|
\Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
|
|
|
|
$scope->setUser([
|
2023-02-25 05:02:27 +01:00
|
|
|
'username' => Auth::user()?Auth::user()->username:null,
|
2023-02-14 01:21:52 +01:00
|
|
|
'ip_address' => php_sapi_name()=='cli'?null:$_SERVER['REMOTE_ADDR'],
|
2023-01-29 18:17:50 +01:00
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
2023-02-08 02:27:15 +01:00
|
|
|
self :: $php_error_types = array();
|
2023-03-01 16:22:11 +01:00
|
|
|
foreach(App::get('sentry.php_error_types', null, 'array') as $php_error_type) {
|
2023-02-08 02:27:15 +01:00
|
|
|
if (is_string($php_error_type) && defined($php_error_type))
|
|
|
|
$php_error_type = constant($php_error_type);
|
|
|
|
if (!is_int($php_error_type)) continue;
|
|
|
|
if (in_array($php_error_type, self :: $php_error_types)) continue;
|
|
|
|
self :: $php_error_types[] = $php_error_type;
|
|
|
|
}
|
2023-01-29 18:17:50 +01:00
|
|
|
set_error_handler(
|
|
|
|
array('EesyPHP\\SentryIntegration', 'on_php_error'),
|
|
|
|
E_ALL
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log an exception or a message in Sentry
|
|
|
|
* @param string|Throwable $message
|
|
|
|
* @param array $extra_args Extra arguments to use to compute message using sprintf
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public static function log($message, ...$extra_args) {
|
|
|
|
if (!self :: $dsn) {
|
|
|
|
Log :: trace('Sentry DSN not configured, do not log this error');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (is_string($message)) {
|
|
|
|
// Extra arguments passed, format message using sprintf
|
|
|
|
if ($extra_args) {
|
|
|
|
$message = call_user_func_array(
|
|
|
|
'sprintf',
|
|
|
|
array_merge(array($message), $extra_args)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Log :: debug('Error logged in Sentry');
|
|
|
|
\Sentry\captureMessage($message);
|
|
|
|
}
|
|
|
|
elseif ($message instanceof Exception) {
|
|
|
|
Log :: debug('Exception logged in Sentry');
|
|
|
|
\Sentry\captureException($message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log a PHP error in Sentry
|
|
|
|
* Note: method design to be used as callable by set_error_handler()
|
|
|
|
* @param int $errno The error number
|
|
|
|
* @param string $errstr The error message
|
|
|
|
* @param string $errfile The filename that the error was raised in
|
|
|
|
* @param int $errline The line number where the error was raised
|
|
|
|
* @return false Return false to let the normal error handler continues.
|
|
|
|
*/
|
|
|
|
public static function on_php_error($errno, $errstr, $errfile, $errline) {
|
|
|
|
if (in_array($errno, self :: $php_error_types))
|
|
|
|
self :: log(
|
2024-01-23 19:23:10 +01:00
|
|
|
"A PHP error occurred : [%s] %s\nFile : %s (line : %d)",
|
2023-01-29 18:17:50 +01:00
|
|
|
Log :: errno2type($errno), $errstr, $errfile, $errline
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|