Client

The SDK component responsible for event creation, integration management, and transport dispatch.

Statusstable
Version2.2.0(changelog)

The Client is the SDK component responsible for building Sentry events from captured data and dispatching them to the Transport. It is configured once during Sentry.init() and manages the integration lifecycle.

The Client is stateless with respect to contextual data — it receives the Scope at capture time and merges scope data into the event. The Client does hold configuration (options) and owns its transport and integrations.

In the Hub & Scope model, the Client was bound to a Hub. In the current Scopes model, the Client is resolved via the scope chain.

Related specs:

  • Configuration — client options, environment variables, debug mode, sampling
  • Integrations — integration interface, lifecycle, and defaults
  • Hooks — lifecycle hooks, before_send, before_breadcrumb
  • Errors — error capture, exception interface, wire format
  • Scopes — scope chain and client resolution
  • Transport — envelope delivery
  • Envelopes — wire format
  • Attributes — attribute type system

  • Stateless: The Client does not hold contextual data (tags, breadcrumbs, user). All contextual data comes from scopes, which are passed to the Client at capture time.

  • Transport delegation: The Client builds the event; the Transport sends it. The Client MUST NOT implement network I/O directly — it delegates to its Transport (or TelemetryProcessor, if present).

  • NoOpClient: A Client that performs no operations. Present on the global scope before Sentry.init() is called, ensuring that getClient() never returns null.

  • Disabled SDK: The SDK is considered disabled when the Client has no transport, or when no DSN is configured. In this state, event processors, configure_scope callbacks, and breadcrumb recording SHOULD NOT be invoked.


Stablespecified since 1.0.0

Sentry.init(options) MUST create a Client, configure its transport, and set up integrations. The Client is then set on the global scope, replacing the NoOpClient.

Before Sentry.init() is called, a NoOpClient MUST be present on the global scope. (since 2.0.0)

SDKs MUST accept an empty DSN as valid configuration. If initialized with an empty or missing DSN, the SDK MUST NOT send any data over the network. Depending on the platform, the SDK MAY reduce its runtime footprint to a minimum.

Calling Sentry.init() multiple times is permitted for testing. Behavior in production beyond application startup is undefined.

The Client is considered active when it has a configured transport. When active, the Client processes captured events through the event pipeline.

MethodDescription
close(timeout)Flush the transport queue for up to timeout seconds. The Client SHOULD be disabled or disposed after close returns.
flush(timeout)Flush the transport queue for up to timeout seconds. The Client remains usable.

Both methods MUST block for at most timeout seconds. If the transport includes a TelemetryProcessor, flushing MUST first forward all buffered items to the transport, then flush the transport itself.

Stablespecified since 2.0.0

A Client MUST always be available — getClient() MUST NOT return null.

Client resolution walks the scope chain:

  1. Check the current scope
  2. Check the isolation scope
  3. Check the global scope
  4. Fall back to NoOpClient (should not happen if init() was called)

Users MAY bind a different Client to any scope via scope.setClient(client).

See Scopes: Client Resolution for details.

Stablespecified since 1.0.0

When captureEvent, captureException, or captureMessage is called, the Client processes the event through the following pipeline. The event MAY be discarded at any stage, stopping further processing.

  1. Disabled check: If the SDK is disabled (no transport / no DSN), discard immediately.
  2. Sampling: Apply the configured sample_rate. Events MAY be randomly discarded. When discarded, the Client MUST record a client report with discard reason sample_rate.
  3. Scope application: Obtain the current, isolation, and global scopes. Merge scope data onto the event in the defined order. Invoke event processors in registration order. Any processor returning null discards the event (client report reason: event_processor).
  4. before_send hook: Invoke the user-configured callback. Returning null discards the event (client report reason: before_send). This hook MUST only apply to error events. For transactions, use before_send_transaction. For logs, use before_send_log. See Hooks for details.
  5. Transport: Pass the event to the transport (or TelemetryProcessor). The transport MAY discard due to missing DSN, full queue, or rate limiting.

MethodDescription
Client(options) / Client.from_config(options)Construct a Client with the given options.

MethodDescription
capture_event(event, scope)Merge event with scope data, run through event pipeline, dispatch to transport.
capture_exception(exception, scope)Convert exception to event, then capture.
capture_message(message, level, scope)Convert message to event, then capture.

MethodDescription
close(timeout)Flush and disable.
flush(timeout)Flush without disabling.

See Configuration for the full set of client options, environment variables, and sampling behavior.


VersionDateSummary
2.2.02025-02-24Restructured into sub-specs for integrations, hooks, and configuration
2.1.02024-09-23Added integration lifecycle (setupOnce, setup, afterAllSetup, preprocessEvent, processEvent)
2.0.02024-02-14Breaking — Client decoupled from Hub; resolved via scope chain; NoOpClient before init
1.1.02022-11-17Added session lifecycle (start_session, end_session)
1.0.02020-05-04Initial spec — stateless event creator with capture_event, close, flush, transport delegation
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").