LaunchDarkly PHP OpenTelemetry integration 0.1.0

TracingHook extends Hook
in package

LaunchDarkly feature flag evaluation hook that enriches OpenTelemetry spans with `feature_flag` events whenever a flag is evaluated.

When a LaunchDarkly SDK variation call runs inside an active OpenTelemetry span, this hook attaches a feature_flag span event carrying the required semantic-convention attributes (feature_flag.key, feature_flag.provider.name, feature_flag.context.id) as well as any enabled optional attributes:

  • feature_flag.result.value when TracingHookOptions::$includeValue is true. The value is serialized per self::serializeValue().
  • feature_flag.result.variationIndex when the evaluation produced a variation index (emitted as an integer primitive).
  • feature_flag.result.reason.inExperiment when the evaluation reason is part of an experiment. Omitted when false.
  • feature_flag.set.id when an environment ID is available, sourced from TracingHookOptions::$environmentId when configured, or otherwise from EvaluationSeriesContext::$environmentId (which the LaunchDarkly SDK populates from polling-response metadata when fetching directly from LaunchDarkly). The configuration path takes precedence when both are set.

When no span is active, the hook is a no-op.

Experimental: when TracingHookOptions::$addSpans is enabled, beforeEvaluation also creates a dedicated OpenTelemetry span named LDClient.<method> (where <method> is the raw variation method name, e.g. variation, variationDetail, migrationVariation) that wraps the variation call. The wrapper span carries only the feature_flag.key and feature_flag.context.id attributes; all other attributes remain on the feature_flag span event. afterEvaluation detaches the wrapper span's context and ends it BEFORE attaching the feature_flag event, so the event lands on the caller's surrounding span rather than on the wrapper.

The wrapper span and the scope used to restore the caller's context are threaded between beforeEvaluation and afterEvaluation through the hook $data array under the reserved keys identified by the self::DATA_KEY_SPAN and self::DATA_KEY_SCOPE class constants. Other hooks must not write to those keys. On exit from afterEvaluation the keys are removed from $data so downstream stages are not surprised by OpenTelemetry objects in their inputs.

The hook is registered on an LDClient via the SDK's hooks configuration and is safe to share across threads/requests.

Tags
psalm-api

Table of Contents

__construct()  : mixed
Construct a tracing hook.
afterEvaluation()  : array<string, mixed>
Attach a `feature_flag` span event to the currently active span describing the evaluation that just completed.
beforeEvaluation()  : array<string, mixed>
Experimental. When {@see TracingHookOptions::$addSpans} is enabled, start a wrapper span named `LDClient.<method>` around the upcoming variation call and attach its context so subsequent work is nested beneath it. The wrapper span carries only `feature_flag.key` and `feature_flag.context.id`; all other attributes belong on the `feature_flag` event.
getMetadata()  : Metadata
Return the hook's identification metadata.

Methods

__construct()

Construct a tracing hook.

public __construct([TracingHookOptions $options = new TracingHookOptions() ][, TracerInterface|null $tracer = null ]) : mixed
Parameters
$options : TracingHookOptions = new TracingHookOptions()

Configuration for the optional attributes emitted on the feature_flag event and for the experimental addSpans wrapper-span behavior. Defaults to an options object with all optional features disabled.

$tracer : TracerInterface|null = null

Tracer used by the experimental addSpans path to create wrapper spans for every variation call. When null, a tracer named launchdarkly is acquired from the global OpenTelemetry tracer provider via Globals::tracerProvider(). Primarily a test injection point; production callers should leave this null.

Return values
mixed

afterEvaluation()

Attach a `feature_flag` span event to the currently active span describing the evaluation that just completed.

public afterEvaluation(EvaluationSeriesContext $seriesContext, array<string, mixed> $data, EvaluationDetail $detail) : array<string, mixed>

Runs in this order:

  1. If TracingHookOptions::$addSpans is enabled and beforeEvaluation stashed a wrapper span and scope under the reserved $data keys, detach the scope then end the wrapper span. This MUST happen before step 2 so the event below lands on the caller's surrounding span, not on our wrapper.
  2. Look up the currently active span. If the span context is invalid (no active span, or a NonRecordingSpan with an invalid context), return without emitting anything.
  3. Build the attribute map: the three required attributes always, plus any optional attributes whose gates are satisfied.
  4. Call Span::addEvent('feature_flag', $attributes).

The reserved $data keys are removed before returning so downstream hook stages do not observe OpenTelemetry objects in their inputs.

Parameters
$seriesContext : EvaluationSeriesContext

Flag key, context, and method for the evaluation.

$data : array<string, mixed>

Hook state threaded from beforeEvaluation; may contain the reserved keys self::DATA_KEY_SPAN and self::DATA_KEY_SCOPE when addSpans is on.

$detail : EvaluationDetail

Evaluation result — drives the optional attributes.

Tags
see
Hook::afterEvaluation()
Return values
array<string, mixed>

The $data array with the reserved keys stripped.

beforeEvaluation()

Experimental. When {@see TracingHookOptions::$addSpans} is enabled, start a wrapper span named `LDClient.<method>` around the upcoming variation call and attach its context so subsequent work is nested beneath it. The wrapper span carries only `feature_flag.key` and `feature_flag.context.id`; all other attributes belong on the `feature_flag` event.

public beforeEvaluation(EvaluationSeriesContext $seriesContext, array<string, mixed> $data) : array<string, mixed>

The span and the scope used to detach its context are stashed under self::DATA_KEY_SPAN and self::DATA_KEY_SCOPE in the returned $data so afterEvaluation can tear them down in the correct order.

When addSpans is disabled, $data is returned unchanged.

The span name is the raw PHP SDK method string (variation, variationDetail, migrationVariation), which yields LDClient.variation and friends. Aligning the method-name casing is a concern for the core PHP Server-Side SDK and is tracked separately.

Parameters
$seriesContext : EvaluationSeriesContext
$data : array<string, mixed>
Return values
array<string, mixed>

getMetadata()

Return the hook's identification metadata.

public getMetadata() : Metadata

The name is used by the LaunchDarkly SDK when it logs errors raised from this hook so the offending hook can be identified among the (possibly many) registered hooks.

Tags
see
Hook::getMetadata()
Return values
Metadata

Metadata whose name is the fixed string "LaunchDarkly Tracing Hook".

Search results