VOOZH about

URL: https://deepwiki.com/friendsofhyperf/components/2.5-event-lifecycle-and-eventhandlelistener

⇱ Event Lifecycle and EventHandleListener | friendsofhyperf/components | DeepWiki


Loading...
Last indexed: 14 February 2026 (15d5ca)
Menu

Event Lifecycle and EventHandleListener

This page documents how the Sentry integration observes application events throughout their lifecycle to create distributed traces, transactions, and breadcrumbs. The system uses two coordinated EventHandleListener classes that intercept 30+ Hyperf event types to provide comprehensive observability without requiring manual instrumentation.

For information about AOP-based instrumentation of method calls, see AOP-Based Instrumentation. For details on message queue tracing and carrier injection, see Message Queue and Async Job Tracing. For transaction/span architecture concepts, see Distributed Tracing Architecture.

Dual Listener Architecture

The Sentry integration employs two separate EventHandleListener classes with distinct responsibilities, registered at different priority levels to ensure correct execution order:

Listener ClassPriorityPurposeConfiguration Prefix
FriendsOfHyperf\Sentry\Tracing\Listener\EventHandleListenerPHP_INT_MAXCreates transactions and spans for distributed tracingsentry.tracing.*
FriendsOfHyperf\Sentry\Listener\EventHandleListenerPHP_INT_MAX - 1Captures breadcrumbs and exceptions for contextsentry.breadcrumbs.*

The tracing listener executes first to establish transaction contexts before the breadcrumb listener adds supplementary information. Both listeners observe the same event types but perform complementary actions.

Sources: src/sentry/src/ConfigProvider.php64-74 src/sentry/src/Tracing/Listener/EventHandleListener.php64 src/sentry/src/Listener/EventHandleListener.php42

Listener Registration and Priority


Sources: src/sentry/src/ConfigProvider.php62-74

Event Categories and Lifecycle Processing

The listeners observe events across seven major categories, each with distinct lifecycle phases:

HTTP and RPC Request Events

The request lifecycle involves four events that bracket the entire request handling:

Event ClassPhaseTracing ActionBreadcrumb Action
HttpEvent\RequestReceivedPre-processingCreate transaction, start request.received spanNone
RpcEvent\RequestReceivedPre-processingCreate transaction, start request.received spanNone
HttpEvent\RequestHandledPost-processingSet HTTP status, inject trace ID headerNone
RpcEvent\RequestHandledPost-processingSet HTTP status, inject trace ID to RPC contextNone
HttpEvent\RequestTerminatedCleanupN/ACapture exception if present
RpcEvent\RequestTerminatedCleanupN/ACapture exception if present

Request Transaction Flow:


Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php267-364 src/sentry/src/Listener/EventHandleListener.php258-277

Command Execution Lifecycle

Console command events create transactions with argument and option metadata:


The command transaction uses CoContainer to store the parent transaction span associated with the command instance for retrieval during the AfterExecute event.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php366-459 src/sentry/src/Listener/EventHandleListener.php280-348

Crontab Task Lifecycle

Crontab events create transactions for scheduled task execution:


The transaction includes metadata about the crontab rule, schedule type, singleton settings, and one-server execution constraints.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php507-552

AsyncQueue Job Processing

AsyncQueue events restore trace context from the carrier injected by AsyncQueueJobMessageAspect:

EventPhaseAction
AsyncQueueEvent\BeforeHandlePre-processingExtract carrier from parent coroutine, create transaction
AsyncQueueEvent\AfterHandleSuccess(Transaction finishes via defer)
AsyncQueueEvent\RetryHandleRetry(Transaction finishes via defer)
AsyncQueueEvent\FailedHandleFailureSet transaction status to InternalError

The carrier is retrieved from the parent coroutine context using SentryContext::getCarrier(Coroutine::parentId()), where it was stored by the producer aspect.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php685-730

AMQP Message Processing

AMQP consumers extract trace context from the application_headers property:


The listener checks if the AMQPMessage has an application_headers property containing the carrier JSON at key Constants::TRACE_CARRIER.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php554-622 src/sentry/src/Constants.php16

Kafka Message Processing

Kafka consumers extract trace context from message headers:

The process is similar to AMQP but uses RecordHeader instead of AMQPTable. The listener iterates through message headers to find one with key Constants::TRACE_CARRIER and deserializes the carrier from the header value.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php624-683

Database Query Events

Database events create spans within existing transactions and capture transaction lifecycle:

EventOpDescription
DbEvent\QueryExecuteddb.sql.queryRecords query with execution time, bindings, pool stats
DbEvent\TransactionBeginningdb.transactionCreates span for BEGIN statement
DbEvent\TransactionCommitteddb.transactionFinishes span with COMMIT description
DbEvent\TransactionRolledBackdb.transactionFinishes span with ROLLBACK description

Query spans include enriched metadata populated by DbConnectionAspect:

  • db.system: Driver name (mysql, pgsql, etc.)
  • db.name: Database name
  • db.operation.name: Parsed operation (SELECT, INSERT, etc.)
  • db.collection.name: Parsed table name
  • db.pool.name, db.pool.max, db.pool.idle, db.pool.using: Connection pool statistics
  • server.address, server.port: Server endpoint from SentryContext

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php170-265

Redis Command Events

Redis command execution creates spans with connection pool and server information:


The RedisConnectionAspect populates SentryContext with server address and port before the event fires, which the listener retrieves to include in span data.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php461-505 src/sentry/src/Tracing/Aspect/RedisConnectionAspect.php38-65

Transaction Creation Patterns

The tracing listener uses two primary functions to create transactions:

startTransaction() with continueTrace()

For events that may receive trace context from external sources (HTTP requests, message queues):

$carrier = Carrier::fromRequest($request);
$transaction = startTransaction(
 continueTrace($carrier->getSentryTrace(), $carrier->getBaggage())
 ->setName($name)
 ->setOp('http.server')
 ->setDescription($description)
 ->setOrigin('auto.request')
 ->setSource($source)
 ->setData($data)
);

The continueTrace() function creates a TransactionContext that preserves the parent trace ID and span ID from the carrier, enabling distributed tracing across service boundaries.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php306-314

startTransaction() with TransactionContext

For events that originate locally without external trace context (commands, crontabs):

$transaction = startTransaction(
 TransactionContext::make()
 ->setName($command->getName())
 ->setOp('console.command')
 ->setOrigin('auto.console')
 ->setSource(TransactionSource::task())
);

This creates a new root transaction with a fresh trace ID.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php378-392

Span Lifecycle Management with defer()

All transactions and child spans use Hyperf's defer() function to ensure proper cleanup after request/task completion:

defer(function () use ($transaction, $span) {
 $span->finish();
 SentrySdk::getCurrentHub()->setSpan($transaction);
 $transaction->finish();
});

This pattern guarantees that spans are closed even if exceptions occur, and ensures the correct order: child spans finish before their parent transaction.

Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php331-340

Trace Context Propagation

Carrier Extraction Patterns

The listener uses different extraction strategies based on the event source:

SourceExtraction MethodStorage Location
HTTP RequestCarrier::fromRequest($request)Headers: sentry-trace, baggage
AMQP MessageCarrier::fromJson($amqpTable['sentry.tracing.trace_carrier'])AMQPMessage application_headers
Kafka MessageCarrier::fromJson($header->getValue())RecordHeader with key TRACE_CARRIER
AsyncQueue JobSentryContext::getCarrier(Coroutine::parentId())Parent coroutine context

After extraction, the carrier is stored in SentryContext for access by other components:


Sources: src/sentry/src/Tracing/Listener/EventHandleListener.php305 src/sentry/src/Tracing/Listener/EventHandleListener.php570-572 src/sentry/src/Tracing/Listener/EventHandleListener.php636-639 src/sentry/src/Tracing/Listener/EventHandleListener.php691

Breadcrumb Collection

The breadcrumb listener adds contextual information without creating performance overhead. Breadcrumbs are collected for:

Database Query Breadcrumbs

Integration::addBreadcrumb(new Breadcrumb(
 Breadcrumb::LEVEL_INFO,
 Breadcrumb::TYPE_DEFAULT,
 'db.sql.query',
 $event->sql,
 [
 'connectionName' => $event->connectionName,
 'executionTimeMs' => $event->time,
 'bindings' => $event->bindings,
 'pool' => [
 'max' => $pool->getOption()->getMaxConnections(),
 'waiting' => $pool->getConnectionsInChannel(),
 'use' => $pool->getCurrentConnections(),
 ]
 ]
));

Sources: src/sentry/src/Listener/EventHandleListener.php165-199

Command Execution Breadcrumbs

Command breadcrumbs include input arguments and options if enabled:

$data = [];
if ($this->feature->isBreadcrumbEnabled('command_input')) {
 $input = (fn () => $this->input)->call($event->getCommand());
 $data['input'] = $this->extractConsoleCommandInput($input);
}

Integration::addBreadcrumb(new Breadcrumb(
 Breadcrumb::LEVEL_INFO,
 Breadcrumb::TYPE_DEFAULT,
 'command',
 'Starting command: ' . $event->getCommand()->getName(),
 $data
));

Sources: src/sentry/src/Listener/EventHandleListener.php292-307

Configuration and Feature Flags

The listeners respect configuration flags to enable/disable specific event processing:

Tracing Configuration

Located in sentry.php config under sentry.tracing.*:

KeyDefaultPurpose
sentry.tracing.requesttrueEnable HTTP/RPC request tracing
sentry.tracing.commandtrueEnable command execution tracing
sentry.tracing.crontabtrueEnable crontab task tracing
sentry.tracing.amqptrueEnable AMQP consumer tracing
sentry.tracing.kafkatrueEnable Kafka consumer tracing
sentry.tracing.async_queuetrueEnable AsyncQueue job tracing

Sources: src/sentry/publish/sentry.php135-144

Tracing Span Configuration

Located under sentry.tracing_spans.*:

KeyDefaultPurpose
sentry.tracing_spans.sql_queriestrueEnable query span creation
sentry.tracing_spans.redistrueEnable Redis command span creation
sentry.tracing_spans.dbtrueEnable database connection tracking

Sources: src/sentry/publish/sentry.php147-159

Breadcrumb Configuration

Located under sentry.breadcrumbs.*:

KeyDefaultPurpose
sentry.breadcrumbs.sql_queriestrueCollect query breadcrumbs
sentry.breadcrumbs.sql_bindingstrueInclude bindings in breadcrumbs
sentry.breadcrumbs.redistrueCollect Redis command breadcrumbs
sentry.breadcrumbs.commandtrueCollect command breadcrumbs
sentry.breadcrumbs.command_inputtrueInclude input in command breadcrumbs
sentry.breadcrumbs.async_queuetrueCollect queue job breadcrumbs

Sources: src/sentry/publish/sentry.php106-118

Feature Flag Evaluation

The Feature class provides helper methods used throughout the listeners:


Sources: src/sentry/src/Feature.php86-103

Ignored Commands and Transactions

Certain commands and transaction patterns are ignored by default:

Ignored Commands

Commands matching these patterns are excluded from tracing:


The listener uses Str::is($this->ignoreCommands, $event->getCommand()->getName()) to check if a command should be skipped.

Sources: src/sentry/publish/sentry.php125-132 src/sentry/src/Tracing/Listener/EventHandleListener.php369-371

Ignored Transactions

Transaction patterns that should not be sent to Sentry:


This filtering occurs at the Sentry SDK level using the before_send_transaction callback.

Sources: src/sentry/publish/sentry.php91-93

Event Processing Flow Summary


Sources: src/sentry/src/ConfigProvider.php62-74 src/sentry/src/Tracing/Listener/EventHandleListener.php78-168 src/sentry/src/Listener/EventHandleListener.php52-143

Refresh this wiki

On this page