Skip to content

Events

Drupal\native_observability\Event\NativeObservabilityEvents defines two event name constants:

Constant Value Event class Dispatched from
TRACE_RECORDED native_observability.trace_recorded Drupal\native_observability\Event\TraceRecordedEvent DatabaseTraceStorage::insert(), right after the trace row is inserted
TRACES_DELETED native_observability.traces_deleted Drupal\native_observability\Event\TracesDeletedEvent TraceDeleteAllConfirmForm, after a bulk deletion completes

Both events are dispatched synchronously, within the same request that triggered them. There is no deferred or queued delivery.

TraceRecordedEvent

final class TraceRecordedEvent extends Event {
  public function __construct(array $trace);
  public function getTrace(): array;
}

getTrace() returns the same associative array that was written to native_observability_trace:

Key Type Notes
id int The auto-increment ID of the inserted row
request_id string ULID request correlation ID
method string HTTP method
path string Request path
route_name string\|null Drupal route machine name
status_code int\|null HTTP response status code
is_ajax int 1 or 0
duration_ms int\|null Request duration in milliseconds
started_at int Unix timestamp
ended_at null Reserved, always NULL on this event

TracesDeletedEvent

final class TracesDeletedEvent extends Event {
  public function __construct(int $deleted_count);
  public function getDeletedCount(): int;
}

getDeletedCount() returns the number of trace rows removed by the bulk delete operation.

Example subscriber

The subscriber below lives in a custom module (my_module) and logs a warning for every request slower than 3 seconds. It follows the same shape as native_observability_spans's own TracesDeletedSubscriber: a final class implementing EventSubscriberInterface, with an explicit logger channel argument and public: true plus the event_subscriber tag, both required by Drupal's event-subscriber compiler pass.

my_module/src/EventSubscriber/SlowTraceSubscriber.php:

<?php

declare(strict_types=1);

namespace Drupal\my_module\EventSubscriber;

use Drupal\native_observability\Event\NativeObservabilityEvents;
use Drupal\native_observability\Event\TraceRecordedEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Logs a warning for every trace slower than the configured threshold.
 */
final class SlowTraceSubscriber implements EventSubscriberInterface {

  private const THRESHOLD_MS = 3000;

  public function __construct(
    private readonly LoggerInterface $logger,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      NativeObservabilityEvents::TRACE_RECORDED => 'onTraceRecorded',
    ];
  }

  public function onTraceRecorded(TraceRecordedEvent $event): void {
    $trace = $event->getTrace();
    $durationMs = (int) ($trace['duration_ms'] ?? 0);

    if ($durationMs < self::THRESHOLD_MS) {
      return;
    }

    $this->logger->warning('Slow request: @method @path took @duration ms (status @status).', [
      '@method' => $trace['method'] ?? 'UNKNOWN',
      '@path' => $trace['path'] ?? '',
      '@duration' => $durationMs,
      '@status' => $trace['status_code'] ?? 'n/a',
    ]);
  }

}

my_module/my_module.services.yml:

services:
  logger.channel.my_module:
    class: Drupal\Core\Logger\LoggerChannel
    factory: ['@logger.factory', 'get']
    arguments: ['my_module']

  my_module.slow_trace_subscriber:
    class: Drupal\my_module\EventSubscriber\SlowTraceSubscriber
    public: true
    arguments:
      $logger: '@logger.channel.my_module'
    tags:
      - { name: event_subscriber }

No other wiring is required. my_module does not need to declare a dependency on native_observability in its .info.yml for the subscriber to work, but it should: the event class is only autoloadable, and the event only fires, while native_observability is installed.