From 3d4adaa4d331f5425ec1a914d6aaea1bb70dd9b4 Mon Sep 17 00:00:00 2001 From: Adriana Knight Date: Tue, 27 Oct 2026 15:58:25 -0400 Subject: [PATCH] fix(client): stamp launchdarkly.project_id on the telemetry resource The OTel resource now identifies the project with launchdarkly.project_id, set to the resolved SDK key, in place of highlight.project_id. LaunchDarkly Observability reads launchdarkly.project_id ahead of highlight.project_id, so ingestion is unchanged, and the resource carries one project id. Co-Authored-By: Claude Opus 5.5 --- .../client/src/launchdarkly_ai_server/lifecycle.py | 4 ++-- packages/client/tests/test_evaluations_spans.py | 4 ++-- packages/client/tests/test_lifecycle.py | 12 +++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/client/src/launchdarkly_ai_server/lifecycle.py b/packages/client/src/launchdarkly_ai_server/lifecycle.py index 9b87cbe7..e7bb8fc7 100644 --- a/packages/client/src/launchdarkly_ai_server/lifecycle.py +++ b/packages/client/src/launchdarkly_ai_server/lifecycle.py @@ -114,7 +114,7 @@ def _setup_telemetry(sdk_key: str, options: InitClientOptions | None = None) -> if OTel packages are not installed (graceful degradation). This function: - - Stamps ``service.name``, ``highlight.project_id``, and (when set) + - Stamps ``service.name``, ``launchdarkly.project_id``, and (when set) ``deployment.environment`` resource attributes, mirroring the TS SDK. - Registers W3C trace context and baggage propagators. - Configures GZIP compression on the OTLP exporter. @@ -152,7 +152,7 @@ def _setup_telemetry(sdk_key: str, options: InitClientOptions | None = None) -> resource_attrs: dict[str, str] = { "service.name": opts.get("serviceName") or os.environ.get("LD_SERVICE_NAME", "python-sdk"), - "highlight.project_id": sdk_key, + "launchdarkly.project_id": sdk_key, } environment = opts.get("environment") or os.environ.get("LD_ENVIRONMENT") if environment: diff --git a/packages/client/tests/test_evaluations_spans.py b/packages/client/tests/test_evaluations_spans.py index 4dd806d3..cefd9bba 100644 --- a/packages/client/tests/test_evaluations_spans.py +++ b/packages/client/tests/test_evaluations_spans.py @@ -92,7 +92,7 @@ def _install_provider( resource=Resource.create( { "service.name": "python-sdk", - "highlight.project_id": "sdk-key", + "launchdarkly.project_id": "sdk-key", } ) ) @@ -347,7 +347,7 @@ async def handler( ] for span in spans: assert span.resource is not None - assert span.resource.attributes["highlight.project_id"] == "sdk-key" + assert span.resource.attributes["launchdarkly.project_id"] == "sdk-key" assert_row_attributes(span.attributes) assert span.status.status_code == StatusCode.OK diff --git a/packages/client/tests/test_lifecycle.py b/packages/client/tests/test_lifecycle.py index dd4da8ac..187ca9c5 100644 --- a/packages/client/tests/test_lifecycle.py +++ b/packages/client/tests/test_lifecycle.py @@ -768,13 +768,19 @@ def _spy_create(attributes: dict | None = None) -> Resource: return created_resources, mock_exporter_cls - def test_stamps_highlight_project_id(self) -> None: - """highlight.project_id resource attribute must equal the resolved SDK key.""" + def test_stamps_launchdarkly_project_id(self) -> None: + """launchdarkly.project_id resource attribute must equal the resolved SDK key.""" created_resources, _ = self._setup_with_mock_exporter("my-sdk-key") assert any( - r.get("highlight.project_id") == "my-sdk-key" for r in created_resources + r.get("launchdarkly.project_id") == "my-sdk-key" for r in created_resources ) + def test_stamps_no_highlight_project_id(self) -> None: + """launchdarkly.project_id is the only project id the resource carries.""" + created_resources, _ = self._setup_with_mock_exporter("my-sdk-key") + assert created_resources + assert all("highlight.project_id" not in r for r in created_resources) + def test_registers_w3c_propagators(self) -> None: """init_client must register a CompositePropagator with W3C trace context and baggage propagators.""" from opentelemetry import propagate