Skip to content

Commit 2fab31a

Browse files
committed
Add BaggageSpanProcessor to populate baggage attributes into OTel spans for Agentic AI cases
1 parent 8644e08 commit 2fab31a

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

aws-opentelemetry-distro/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ classifiers = [
2626
dependencies = [
2727
"opentelemetry-api == 1.27.0",
2828
"opentelemetry-sdk == 1.27.0",
29+
"opentelemetry-processor-baggage == 0.48b0",
2930
"opentelemetry-exporter-otlp-proto-grpc == 1.27.0",
3031
"opentelemetry-exporter-otlp-proto-http == 1.27.0",
3132
"opentelemetry-propagator-b3 == 1.27.0",

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter as OTLPHttpOTLPMetricExporter
3434
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
3535
from opentelemetry.metrics import set_meter_provider
36+
from opentelemetry.processor.baggage import ALLOW_ALL_BAGGAGE_KEYS, BaggageSpanProcessor
3637
from opentelemetry.sdk._configuration import (
3738
_get_exporter_names,
3839
_get_id_generator,
@@ -407,6 +408,11 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
407408
if _is_lambda_environment():
408409
provider.add_span_processor(AwsLambdaSpanProcessor())
409410

411+
# Add baggage attributes to span attributes to support AI Agent use cases
412+
# enabling additional data like session ID in spans.
413+
if is_agent_observability_enabled():
414+
provider.add_span_processor(BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS))
415+
410416
if not _is_application_signals_enabled():
411417
return
412418

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
5151
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter as OTLPHttpOTLPMetricExporter
5252
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
53+
from opentelemetry.processor.baggage import BaggageSpanProcessor
5354
from opentelemetry.sdk.environment_variables import OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG
5455
from opentelemetry.sdk.metrics._internal.export import PeriodicExportingMetricReader
5556
from opentelemetry.sdk.resources import Resource
@@ -340,6 +341,29 @@ def test_customize_span_exporter_with_agent_observability(self):
340341
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
341342
os.environ.pop(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, None)
342343

344+
def test_customize_span_processors_with_agent_observability(self):
345+
mock_tracer_provider: TracerProvider = MagicMock()
346+
347+
# Test that BaggageSpanProcessor is not added when agent observability is disabled
348+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
349+
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
350+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 0)
351+
352+
# Reset mock for next test
353+
mock_tracer_provider.reset_mock()
354+
355+
# Test that BaggageSpanProcessor is added when agent observability is enabled
356+
os.environ["AGENT_OBSERVABILITY_ENABLED"] = "true"
357+
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
358+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 1)
359+
360+
# Verify the added processor is BaggageSpanProcessor
361+
added_processor = mock_tracer_provider.add_span_processor.call_args_list[0].args[0]
362+
self.assertIsInstance(added_processor, BaggageSpanProcessor)
363+
364+
# Clean up
365+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
366+
343367
def test_customize_span_exporter_sigv4(self):
344368

345369
traces_good_endpoints = [
@@ -574,9 +598,18 @@ def capture_exporter(*args, **kwargs):
574598

575599
def test_customize_span_processors(self):
576600
mock_tracer_provider: TracerProvider = MagicMock()
601+
# Clean up environment to ensure consistent test state
602+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
603+
os.environ.pop("OTEL_AWS_APPLICATION_SIGNALS_ENABLED", None)
604+
os.environ.pop("OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED", None)
605+
577606
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
578607
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 0)
579608

609+
# Reset mock for next test
610+
mock_tracer_provider.reset_mock()
611+
612+
# Test application signals only
580613
os.environ.setdefault("OTEL_AWS_APPLICATION_SIGNALS_ENABLED", "True")
581614
os.environ.setdefault("OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED", "False")
582615
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
@@ -586,8 +619,27 @@ def test_customize_span_processors(self):
586619
second_processor: SpanProcessor = mock_tracer_provider.add_span_processor.call_args_list[1].args[0]
587620
self.assertIsInstance(second_processor, AwsSpanMetricsProcessor)
588621

622+
# Reset mock for next test
623+
mock_tracer_provider.reset_mock()
624+
625+
# Test both agent observability and application signals enabled
626+
os.environ.setdefault("AGENT_OBSERVABILITY_ENABLED", "true")
627+
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
628+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 3)
629+
630+
# Verify processors are added in the expected order
631+
processors = [call.args[0] for call in mock_tracer_provider.add_span_processor.call_args_list]
632+
self.assertIsInstance(processors[0], BaggageSpanProcessor) # Agent observability processor added first
633+
self.assertIsInstance(processors[1], AttributePropagatingSpanProcessor) # Application signals processors
634+
self.assertIsInstance(processors[2], AwsSpanMetricsProcessor)
635+
589636
def test_customize_span_processors_lambda(self):
590637
mock_tracer_provider: TracerProvider = MagicMock()
638+
# Clean up environment to ensure consistent test state
639+
os.environ.pop("AGENT_OBSERVABILITY_ENABLED", None)
640+
os.environ.pop("OTEL_AWS_APPLICATION_SIGNALS_ENABLED", None)
641+
os.environ.pop("AWS_LAMBDA_FUNCTION_NAME", None)
642+
591643
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
592644
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 0)
593645

0 commit comments

Comments
 (0)