class RequestSubscriber in Raven: Sentry Integration 3.x
Same name and namespace in other branches
- 8.2 src/EventSubscriber/RequestSubscriber.php \Drupal\raven\EventSubscriber\RequestSubscriber
Initializes Raven logger so Sentry functions can be called.
Hierarchy
- class \Drupal\raven\EventSubscriber\RequestSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface, \Symfony\Component\DependencyInjection\ContainerAwareInterface, TrustedCallbackInterface uses \Symfony\Component\DependencyInjection\ContainerAwareTrait
Expanded class hierarchy of RequestSubscriber
1 string reference to 'RequestSubscriber'
1 service uses RequestSubscriber
File
- src/
EventSubscriber/ RequestSubscriber.php, line 22
Namespace
Drupal\raven\EventSubscriberView source
class RequestSubscriber implements EventSubscriberInterface, ContainerAwareInterface, TrustedCallbackInterface {
use ContainerAwareTrait;
/**
* Config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface|null
*/
protected $configFactory;
/**
* {@inheritdoc}
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface|null
*/
protected $container;
/**
* Raven logger service.
*
* @var \Drupal\raven\Logger\Raven|null
*/
protected $logger;
/**
* Time service.
*
* @var \Drupal\Component\Datetime\TimeInterface|null
*/
protected $time;
/**
* The transaction for HTTP requests.
*
* @var \Sentry\Tracing\Transaction|null
*/
public $transaction;
/**
* Constructs the request subscriber.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory object.
* @param \Drupal\raven\Logger\Raven $logger
* The logger service.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
*/
public function __construct(ConfigFactoryInterface $config_factory = NULL, Raven $logger = NULL, TimeInterface $time = NULL) {
$this->configFactory = $config_factory;
$this->logger = $logger;
$this->time = $time;
}
/**
* Starts a transaction if performance tracing is enabled.
*
* @todo In Drupal 9+ the event should actually be RequestEvent.
*/
public function onRequest(KernelEvent $event) {
$method = method_exists($event, 'isMainRequest') ? 'isMainRequest' : 'isMasterRequest';
if (!$event
->{$method}() || !$this->configFactory) {
return;
}
$config = $this->configFactory
->get('raven.settings');
if (!$config
->get('request_tracing') || !$this->logger || !$this->logger
->getClient()) {
return;
}
$request = $event
->getRequest();
$sentryTraceHeader = $request->headers
->get('sentry-trace');
$transactionContext = $sentryTraceHeader && method_exists(TransactionContext::class, 'fromSentryTrace') ? TransactionContext::fromSentryTrace($sentryTraceHeader) : new TransactionContext();
$transactionContext
->setName($request
->getMethod() . ' ' . $request
->getUri());
$transactionContext
->setOp('http.server');
$transactionContext
->setTags([
'http.method' => $request
->getMethod(),
'http.url' => $request
->getUri(),
]);
$transactionContext
->setStartTimestamp($this->time
->getRequestMicroTime());
$this->transaction = \Sentry\startTransaction($transactionContext);
SentrySdk::getCurrentHub()
->setSpan($this->transaction);
if ($config
->get('database_tracing')) {
foreach (Database::getAllConnectionInfo() as $key => $info) {
Database::startLog('raven', $key);
}
}
}
/**
* Performance tracing.
*
* @todo In Drupal 9+ the event should actually be TerminateEvent.
*/
public function onTerminate(KernelEvent $event) {
if (!$this->transaction) {
return;
}
if (method_exists($event, 'getResponse')) {
$this->transaction
->setHttpStatus($event
->getResponse()
->getStatusCode());
}
if ($this->configFactory
->get('raven.settings')
->get('database_tracing')) {
$this
->collectDatabaseLog();
}
$this->transaction
->finish();
}
/**
* If database was initialized, create a span for each logged query.
*/
public function collectDatabaseLog() {
if (!$this->transaction || !$this->container || !$this->container
->initialized('database')) {
return;
}
$connections = [];
foreach (Database::getAllConnectionInfo() as $key => $info) {
try {
$database = Database::getConnection('default', $key);
if ($logger = $database
->getLogger()) {
$connections[$key] = $logger
->get('raven');
}
} catch (\Exception $e) {
// Could not connect.
}
}
foreach ($connections as $key => $queries) {
foreach ($queries as $query) {
if (empty($query['start'])) {
// Older versions of Drupal do not record query start time.
return;
}
$context = new SpanContext();
$context
->setOp('sql.query');
$context
->setDescription($query['query']);
$context
->setTags([
'database' => $key,
]);
$context
->setStartTimestamp($query['start']);
$context
->setEndTimestamp($query['start'] + $query['time']);
$this->transaction
->startChild($context);
}
}
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = [
'onRequest',
222,
];
$events[KernelEvents::TERMINATE][] = [
'onTerminate',
222,
];
return $events;
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks() {
return [
'getTraceparent',
];
}
/**
* Callback for returning the Sentry trace string as renderable array.
*/
public function getTraceParent() {
$markup = '';
if (class_exists(SentrySdk::class)) {
if ($span = SentrySdk::getCurrentHub()
->getSpan()) {
$markup = $span
->toTraceparent();
}
}
return [
'#markup' => $markup,
];
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
RequestSubscriber:: |
protected | property | Config factory. | |
RequestSubscriber:: |
protected | property | ||
RequestSubscriber:: |
protected | property | Raven logger service. | |
RequestSubscriber:: |
protected | property | Time service. | |
RequestSubscriber:: |
public | property | The transaction for HTTP requests. | |
RequestSubscriber:: |
public | function | If database was initialized, create a span for each logged query. | |
RequestSubscriber:: |
public static | function | Registers the methods in this class that should be listeners. | |
RequestSubscriber:: |
public | function | Callback for returning the Sentry trace string as renderable array. | |
RequestSubscriber:: |
public | function | Starts a transaction if performance tracing is enabled. | |
RequestSubscriber:: |
public | function | Performance tracing. | |
RequestSubscriber:: |
public static | function |
Lists the trusted callbacks provided by the implementing class. Overrides TrustedCallbackInterface:: |
|
RequestSubscriber:: |
public | function | Constructs the request subscriber. | |
TrustedCallbackInterface:: |
constant | Untrusted callbacks throw exceptions. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger silenced E_USER_DEPRECATION errors. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger E_USER_WARNING errors. |