Skip to content

feat: Propagate environment ID to evaluation hooks - #484

Draft
kinyoklion wants to merge 1 commit into
mainfrom
devin/1786489071-hook-environment-id
Draft

feat: Propagate environment ID to evaluation hooks#484
kinyoklion wants to merge 1 commit into
mainfrom
devin/1786489071-hook-environment-id

Conversation

@kinyoklion

Copy link
Copy Markdown
Member

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Implements the environmentId field of EvaluationSeriesContext from the hooks spec, which the OTel tracing hook uses for feature_flag.set.id. Mirrors launchdarkly/dotnet-core#81.

Describe the solution you've provided

EvaluationSeriesContext gains an optional environment_id, populated from the X-LD-EnvID response header sent by LaunchDarkly. Both data systems are supported, and each exposes it through a new DataSystem.environment_id property that the client reads when building the series context:

  • FDv2 already parsed the header into Basis.environment_id / Update.environment_id but discarded it; FDv2 now latches the last non-None value (including from initializer error headers).
  • FDv1 had no access to the header. Streaming reads it from the Start/Fault actions of the SSE client, polling reads it from the response headers, and both record it on DataSourceUpdateSinkImpl.

Sketch of the FDv1 path:

# streamingifisinstance(action, Start):
record_environment_id(self._data_source_update_sink, action.headers)
# polling
(all_data, headers) =self._get_all_data_with_headers()
record_environment_id(self._data_source_update_sink, headers)

Describe alternatives you've considered

Following the .NET implementation more literally, where the environment ID is stored as init metadata on the data store, would require optional extension interfaces on the public FeatureStore/DataSourceUpdateSink types. Instead, header handling stays inside the data sources and is surfaced by the data system, so externally implemented stores, sinks, feature requesters, and update processors continue to work unchanged (they simply report no environment ID).

Additional context

  • No change is needed in launchdarkly-eventsource: it already exposes response headers on Start and Fault (unlike the .NET event source, which needed feat: Report event source headers on open. dotnet-eventsource#104).
  • The async (experimental) client does not run hooks yet, so the async data source path is untouched.
  • The environmentId support in the OTel tracing hook lives in python-server-sdk-otel and is a follow-up.

Link to Devin session: https://app.devin.ai/sessions/bfe54128e2804a96bb100e6120e9a3ef
Requested by: @kinyoklion

Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
@kinyoklionkinyoklion self-assigned this Aug 11, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kinyoklion