$sentry_dsn, 'traces_sample_rate' => ( isset($sentry_traces_sample_rate) ? $sentry_traces_sample_rate : 0.2 ), ]); \Sentry\configureScope(function (\Sentry\State\Scope $scope): void { global $auth_user; $scope->setUser([ 'id' => isset($auth_user) && $auth_user?$auth_user['uid']:null, 'email' => isset($auth_user) && $auth_user?$auth_user['mail']:null, 'segment' => isset($auth_user) && $auth_user?$auth_user['type']:null, 'ip_address' => $_SERVER['REMOTE_ADDR'], ]); }); } /** * Log an exception or a message in Sentry * @param string|Throwable $msg * @return void */ function log_in_sentry($msg) { global $sentry_dsn; if (!isset($sentry_dsn) || !$sentry_dsn) { Log :: trace('Sentry DSN not configured, do not log this error'); return; } if (is_string($msg)) { Log :: debug('Error logged in Sentry'); \Sentry\captureMessage($msg); } elseif ($msg instanceof Exception) { Log :: debug('Exception logged in Sentry'); \Sentry\captureException($msg); } } /** * Log a PHP error in Sentry * @param int $errno The error number * @param string $msg The error message * @return void */ function log_php_error_in_sentry($errno, $msg) { global $sentry_php_error_types; if ( isset($sentry_php_error_types) && is_array($sentry_php_error_types) && in_array($errno, $sentry_php_error_types) ) log_in_sentry($msg); } /* * Performance monitoring */ class SentryTransaction { /** * The Sentry transaction object * @var \Sentry\Tracing\Transaction */ private $transaction; /** * The Sentry transaction context object * @var \Sentry\Tracing\TransactionContext */ private $context; /** * Constructor: start a Sentry transaction * @param string|null $op The operation name * @param string|null $name The transaction name * @return void */ public function __construct($op=null, $name=null) { // Setup context for the full transaction $this->context = new \Sentry\Tracing\TransactionContext(); $this->context->setName( $name?$name: (php_sapi_name()=='cli'?'CLI execution':'HTTP request') ); $this->context->setOp( $op?$op: (php_sapi_name()=='cli'?'cli.command':'http.request') ); // Start the transaction $this->transaction = \Sentry\startTransaction($this->context); // Set the current transaction as the current span so we can retrieve it later \Sentry\SentrySdk::getCurrentHub()->setSpan($this->transaction); } /** * Destructor: Stop the current Sentry transaction * @return void */ public function __destruct() { SentrySpan :: finishAll(); $this->transaction->finish(); } } /** * Internal Sentry Span object implementation * This internal implementation principally permit to keep trace of new span parent * and list of started spans. */ class SentrySpan { /** * Keep trace of started Sentry spans * @var array */ private static $_started_spans = array(); /** * The unique ID of the Sentry span * Note: internal ID used as key in self::$_started_spans * @var int|null */ private $id = null; /** * The parent of the Sentry span * @var mixed */ private $parent = null; /** * The context of the Sentry span * @var null|\Sentry\Tracing\SpanContext */ private $context = null; /** * The Sentry span object * @var mixed */ private $span = null; /** * Sentry span constructor * @param string|null $op The operation name * @param string|null $name The span name * @return void */ public function __construct($op, $name) { $this -> parent = \Sentry\SentrySdk::getCurrentHub()->getSpan(); // Check if we have a parent span (this is the case if we started a transaction earlier) if (is_null($this -> parent)) return; while (is_null($this -> id)) { $this -> id = rand(); if (isset(self :: $_started_spans[$this -> id])) $this -> id = null; } $this -> context = new \Sentry\Tracing\SpanContext(); $this -> context->setOp($op); $this -> context->setDescription($name); $this -> span = $this->parent->startChild($this -> context); // Set the current span to the span we just started \Sentry\SentrySdk::getCurrentHub()->setSpan($this -> span); self :: $_started_spans[$this -> id] = $this; } /** * Finish the span (if started) * @return void */ public function finish() { if (!$this -> span) return; $this -> span -> finish(); unset(self::$_started_spans[$this -> id]); \Sentry\SentrySdk::getCurrentHub()->setSpan($this -> parent); } /** * Finish all started spans * @see SentryTransaction::__destruct() * @return void */ public static function finishAll() { foreach (array_reverse(self :: $_started_spans) as $id => $span) $span -> finish(); } } # vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab