Skip to content

Commit 1667a3a

Browse files
authored
fix(agent-observability): fall back to OTEL_EXPORTER_OTLP_ENDPOINT for unsampled spans (#738)
- When `OTEL_EXPORTER_OTLP_ENDPOINT` is set but `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` is not, `_export_unsampled_span_for_agent_observability` now correctly falls back to the base endpoint instead of silently skipping
1 parent e3e14cf commit 1667a3a

3 files changed

Lines changed: 51 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ If your change does not need a CHANGELOG entry, add the "skip changelog" label t
1212

1313
## Unreleased
1414

15+
- fix(agent-observability): fall back to OTEL_EXPORTER_OTLP_ENDPOINT for unsampled spans; also export unsampled spans to non-AWS endpoints
16+
([#738](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/738))
1517
- feat: auto-detect and mutually exclude AWS native vs third-party agentic instrumentors; add `AWS_AGENTIC_INSTRUMENTATION_OPT_IN` env var to override auto-detection
1618
([#729](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/729))
1719
- fix(lambda-layer): align context propagation with JS — delegate to global propagator so W3C traceparent is no longer ignored when X-Ray active tracing is enabled

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/aws_opentelemetry_configurator.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogRecordExporter, LogRecordExporter
6565
from opentelemetry.sdk.environment_variables import (
6666
_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED,
67+
OTEL_EXPORTER_OTLP_ENDPOINT,
6768
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL,
6869
OTEL_EXPORTER_OTLP_PROTOCOL,
6970
OTEL_TRACES_SAMPLER_ARG,
@@ -331,11 +332,20 @@ def _export_unsampled_span_for_agent_observability(trace_provider: TracerProvide
331332
return
332333

333334
traces_endpoint = os.environ.get(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
334-
if traces_endpoint and _is_aws_otlp_endpoint(traces_endpoint, XRAY_SERVICE):
335+
if not traces_endpoint:
336+
base_endpoint = os.environ.get(OTEL_EXPORTER_OTLP_ENDPOINT)
337+
if base_endpoint:
338+
traces_endpoint = base_endpoint.rstrip("/") + "/v1/traces"
339+
if not traces_endpoint:
340+
return
341+
342+
if _is_aws_otlp_endpoint(traces_endpoint, XRAY_SERVICE):
335343
endpoint, region = _extract_endpoint_and_region_from_otlp_endpoint(traces_endpoint)
336344
span_exporter = _create_aws_otlp_exporter(endpoint=endpoint, service=XRAY_SERVICE, region=region)
345+
else:
346+
span_exporter = OTLPSpanExporter(endpoint=traces_endpoint)
337347

338-
trace_provider.add_span_processor(BatchUnsampledSpanProcessor(span_exporter=span_exporter))
348+
trace_provider.add_span_processor(BatchUnsampledSpanProcessor(span_exporter=span_exporter))
339349

340350

341351
def _is_defer_to_workers_enabled():

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test_aws_opentelementry_configurator.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,43 @@ def test_export_unsampled_span_for_agent_observability(self):
11021102
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
11031103
os.environ.pop("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", None)
11041104

1105+
mock_tracer_provider.reset_mock()
1106+
1107+
os.environ["AGENT_OBSERVABILITY_ENABLED"] = "true"
1108+
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:4318"
1109+
_export_unsampled_span_for_agent_observability(mock_tracer_provider, Resource.get_empty())
1110+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 1)
1111+
processor = mock_tracer_provider.add_span_processor.call_args_list[0].args[0]
1112+
self.assertIsInstance(processor, BatchUnsampledSpanProcessor)
1113+
self.assertEqual(processor.span_exporter._endpoint, "http://localhost:4318/v1/traces")
1114+
1115+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
1116+
os.environ.pop("OTEL_EXPORTER_OTLP_ENDPOINT", None)
1117+
1118+
mock_tracer_provider.reset_mock()
1119+
1120+
os.environ["AGENT_OBSERVABILITY_ENABLED"] = "true"
1121+
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://xray.us-west-2.amazonaws.com"
1122+
_export_unsampled_span_for_agent_observability(mock_tracer_provider, Resource.get_empty())
1123+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 1)
1124+
1125+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
1126+
os.environ.pop("OTEL_EXPORTER_OTLP_ENDPOINT", None)
1127+
1128+
mock_tracer_provider.reset_mock()
1129+
1130+
os.environ["AGENT_OBSERVABILITY_ENABLED"] = "true"
1131+
os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = "https://xray.us-east-1.amazonaws.com/v1/traces"
1132+
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:4318"
1133+
_export_unsampled_span_for_agent_observability(mock_tracer_provider, Resource.get_empty())
1134+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 1)
1135+
processor = mock_tracer_provider.add_span_processor.call_args_list[0].args[0]
1136+
self.assertIsInstance(processor, BatchUnsampledSpanProcessor)
1137+
1138+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
1139+
os.environ.pop("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", None)
1140+
os.environ.pop("OTEL_EXPORTER_OTLP_ENDPOINT", None)
1141+
11051142
# pylint: disable=no-self-use
11061143
def test_export_unsampled_span_for_agent_observability_uses_aws_exporter(self):
11071144
"""Test that OTLPAwsSpanExporter is used for AWS endpoints"""

0 commit comments

Comments
 (0)