Skip to content

Commit fa3b2e0

Browse files
authored
Merge branch 'main' into issue-688-fix
2 parents 62a3ef1 + c15e8fe commit fa3b2e0

51 files changed

Lines changed: 4162 additions & 657 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.coveragerc

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
[run]
22
; This flag writes per-process coverage data files so subprocess coverage
3-
; can be combined with the main test process by pytest-cov. Works with COVERAGE_PROCESS_START in
3+
; can be combined with the main test process by pytest-cov. Works with COVERAGE_PROCESS_START in
44
; tox.ini env variable
55
; see: https://coverage.readthedocs.io/en/6.5.0/cmd.html#combining-data-files-coverage-combine
66
parallel = true
77

8+
[paths]
9+
; Normalize installed package paths back to source tree so coverage data
10+
; from different tox envs can be combined into a single report
11+
source =
12+
aws-opentelemetry-distro/src/amazon
13+
.tox/3.*/lib/python*/site-packages/amazon
14+
*/site-packages/amazon
15+
816
[report]
917
include_namespace_packages = true
1018
fail_under = 95.00
11-
precision = 2
19+
precision = 2
20+
; Exclude test files that share the amazon namespace and pip build artifacts
21+
; from coverage measurement so only source code is reported
22+
omit =
23+
*/tests/*
24+
*/pip-build-env-*/*

.coveragerc-py314

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; Python 3.14 coverage config. See .coveragerc for details on shared settings.
2+
3+
[run]
4+
parallel = true
5+
6+
[paths]
7+
source =
8+
aws-opentelemetry-distro/src/amazon
9+
.tox/3.*/lib/python*/site-packages/amazon
10+
*/site-packages/amazon
11+
12+
[report]
13+
include_namespace_packages = true
14+
fail_under = 95.00
15+
precision = 2
16+
omit =
17+
*/instrumentation/crewai/*
18+
*/tests/*
19+
*/pip-build-env-*/*

.coveragerc-py39

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
11
[run]
2-
omit =
3-
*/instrumentation/crewai/*
4-
*/instrumentation/langchain/*
5-
*/instrumentation/mcp/*
2+
; This flag writes per-process coverage data files so subprocess coverage
3+
; can be combined with the main test process by pytest-cov. Works with COVERAGE_PROCESS_START in
4+
; tox.ini env variable
5+
; see: https://coverage.readthedocs.io/en/6.5.0/cmd.html#combining-data-files-coverage-combine
6+
parallel = true
7+
8+
[paths]
9+
; Normalize installed package paths back to source tree so coverage data
10+
; from different tox envs can be combined into a single report
11+
source =
12+
aws-opentelemetry-distro/src/amazon
13+
.tox/3.*/lib/python*/site-packages/amazon
14+
*/site-packages/amazon
615

716
[report]
817
include_namespace_packages = true
918
fail_under = 95.00
1019
precision = 2
20+
; Exclude framework instrumentation not installed on 3.9,
21+
; test files that share the amazon namespace, and pip build artifacts
22+
; so only source code is reported
23+
omit =
24+
*/instrumentation/crewai/*
25+
*/instrumentation/llama_index/*
26+
*/instrumentation/langchain/*
27+
*/instrumentation/mcp/*
28+
*/instrumentation/openai_agents/*
29+
*/tests/*
30+
*/pip-build-env-*/*

.github/actions/set_up/action.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ runs:
4343
if: ${{ inputs.run_unit_tests == 'true' }}
4444
shell: bash
4545
run: |
46-
ENV_NAME="${{ inputs.python_version }}-test-${{ inputs.package_name }}"
47-
echo "Running tox env: $ENV_NAME"
48-
tox -e "$ENV_NAME" -- -ra
46+
PY_VERSION="${{ inputs.python_version }}"
47+
# we intend for new or unrecognized Python versions to fail if a new Python version is added to the test
48+
# to ensure they are not silently skipped from testing
49+
ENVS=$(tox list -q | grep "^${PY_VERSION}-test-" | sed 's/ .*//' | tr '\n' ',' | sed 's/,$//' || true)
50+
echo "Running tox envs: $ENVS"
51+
tox --parallel auto --parallel-live -e "$ENVS" -- -v
52+
53+
- name: Combine and check coverage
54+
if: ${{ inputs.run_unit_tests == 'true' }}
55+
shell: bash
56+
run: |
57+
pip install coverage
58+
if [ "${{ inputs.python_version }}" = "3.9" ]; then
59+
RCFILE=.coveragerc-py39
60+
elif [ "${{ inputs.python_version }}" = "3.14" ]; then
61+
RCFILE=.coveragerc-py314
62+
else
63+
RCFILE=.coveragerc
64+
fi
65+
coverage combine --rcfile=$RCFILE
66+
coverage report --rcfile=$RCFILE

CHANGELOG.md

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

1313
## Unreleased
1414

15+
- fix(langchain-instrumentor): expand provider detection for all supported LLM providers
16+
([#702](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/702))
17+
- feat: add LLO handler support for gen_ai.input.messages, gen_ai.output.messages, and gen_ai.system_instructions
18+
([#699](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/699))
19+
- feat: suppress redundant HTTP/ASGI and initialization spans in MCP instrumentation
20+
([#695](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/695))
21+
- feat: [BREAKING CHANGE] introduce AWS_AGENTIC_OBSERVABILITY_OPT_IN and refactor agent observability config
22+
([#691](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/691))
1523
- feat: propagate HTTP context for MCP requests and prefix all span names with mcp
1624
([#683](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/683))
1725
- feat: add threading instrumentation dependency
1826
([#685](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/685))
1927
- feat: add openai-agents-v2 instrumentation dependency
2028
([#684](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/684))
29+
- feat: add BaggageSpanProcessor by default in ADOT
30+
([#687](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/687))
2131
- feat: Rewrite CrewAI instrumentation using Event based approach
2232
([#681](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/681))
2333

@@ -37,6 +47,8 @@ If your change does not need a CHANGELOG entry, add the "skip changelog" label t
3747
([#658](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/658))
3848
- Fix AwsCloudWatchOtlpBatchLogRecordProcessor custom _export not being invoked; rename otlp_aws_logs_exporter to otlp_aws_log_record_exporter
3949
([#611](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/611))
50+
- Add native LlamaIndex instrumentation support
51+
([#595](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/595))
4052
- Add native CrewAI instrumentation support
4153
([#586](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/586))
4254

aws-opentelemetry-distro/pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ aws_configurator = "amazon.opentelemetry.distro.aws_opentelemetry_configurator:A
105105
aws_distro = "amazon.opentelemetry.distro.aws_opentelemetry_distro:AwsOpenTelemetryDistro"
106106

107107
[project.entry-points.opentelemetry_instrumentor]
108+
aws_llama-index = "amazon.opentelemetry.distro.instrumentation.llama_index:LlamaIndexInstrumentor"
108109
aws_crewai = "amazon.opentelemetry.distro.instrumentation.crewai:CrewAIInstrumentor"
109110
aws_langchain = "amazon.opentelemetry.distro.instrumentation.langchain:LangChainInstrumentor"
110111
aws_mcp = "amazon.opentelemetry.distro.instrumentation.mcp:McpInstrumentor"
112+
# Wraps the upstream OTel OpenAI Agents instrumentor under a unique entry point name.
113+
# This allows us to disable 3rd party "openai_agents" entry points in the opt-in path
114+
# while keeping OpenAI Agents instrumentation active via this alias.
115+
aws_openai_agents = "opentelemetry.instrumentation.openai_agents:OpenAIAgentsInstrumentor"
111116

112117
[project.urls]
113118
Homepage = "https://github.com/aws-observability/aws-otel-python-instrumentation/tree/main/aws-opentelemetry-distro"

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
_logger: Logger = getLogger(__name__)
1212

13+
# Maintained for backwards compatibility. New users should use AWS_AGENTIC_OBSERVABILITY_OPT_IN instead.
1314
AGENT_OBSERVABILITY_ENABLED = "AGENT_OBSERVABILITY_ENABLED"
15+
AWS_AGENTIC_OBSERVABILITY_OPT_IN = "AWS_AGENTIC_OBSERVABILITY_OPT_IN"
1416
OTEL_METRICS_ADD_APPLICATION_SIGNALS_DIMENSIONS = "OTEL_METRICS_ADD_APPLICATION_SIGNALS_DIMENSIONS"
1517

1618

@@ -35,10 +37,20 @@ def is_installed(req: str) -> bool:
3537

3638

3739
def is_agent_observability_enabled() -> bool:
38-
"""Is the Agentic AI monitoring flag set to true?"""
40+
# Maintained for backwards compatibility. New users should use AWS_AGENTIC_OBSERVABILITY_OPT_IN instead.
3941
return os.environ.get(AGENT_OBSERVABILITY_ENABLED, "false").lower() == "true"
4042

4143

44+
def is_aws_agentic_observability_opt_in() -> bool:
45+
"""Is the AI observability opt-in flag set to true?"""
46+
return os.environ.get(AWS_AGENTIC_OBSERVABILITY_OPT_IN, "false").lower() == "true"
47+
48+
49+
def is_agentic_observability_enabled() -> bool:
50+
"""Returns True if either AGENT_OBSERVABILITY_ENABLED or AWS_AGENTIC_OBSERVABILITY_OPT_IN is set to true."""
51+
return is_agent_observability_enabled() or is_aws_agentic_observability_opt_in()
52+
53+
4254
def should_add_application_signals_dimensions() -> bool:
4355
"""Should Service and Environment Application Signals dimensions be added to EMF logs?"""
4456
return os.environ.get(OTEL_METRICS_ADD_APPLICATION_SIGNALS_DIMENSIONS, "true").lower() == "true"

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

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from amazon.opentelemetry.distro._aws_attribute_keys import AWS_LOCAL_SERVICE, AWS_SERVICE_TYPE
1919
from amazon.opentelemetry.distro._aws_resource_attribute_configurator import get_service_attribute
20-
from amazon.opentelemetry.distro._utils import get_aws_session, is_agent_observability_enabled
20+
from amazon.opentelemetry.distro._utils import get_aws_session, is_agentic_observability_enabled
2121
from amazon.opentelemetry.distro.always_record_sampler import AlwaysRecordSampler
2222
from amazon.opentelemetry.distro.attribute_propagating_span_processor_builder import (
2323
AttributePropagatingSpanProcessorBuilder,
@@ -204,7 +204,7 @@ def _initialize_components():
204204
AwsEksResourceDetector(),
205205
AwsEcsResourceDetector(),
206206
]
207-
if not (_is_lambda_environment() or is_agent_observability_enabled())
207+
if not (_is_lambda_environment() or is_agentic_observability_enabled())
208208
else []
209209
)
210210

@@ -326,7 +326,7 @@ def _export_unsampled_span_for_lambda(trace_provider: TracerProvider, resource:
326326

327327

328328
def _export_unsampled_span_for_agent_observability(trace_provider: TracerProvider, resource: Resource = None):
329-
if not is_agent_observability_enabled():
329+
if not is_agentic_observability_enabled():
330330
return
331331

332332
traces_endpoint = os.environ.get(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
@@ -467,7 +467,7 @@ def _customize_log_record_processor(logger_provider: LoggerProvider, log_exporte
467467
if not log_exporter:
468468
return
469469

470-
if is_agent_observability_enabled():
470+
if is_agentic_observability_enabled():
471471
# pylint: disable=import-outside-toplevel
472472
from amazon.opentelemetry.distro.exporter.otlp.aws.logs._aws_cw_otlp_batch_log_record_processor import (
473473
AwsCloudWatchOtlpBatchLogRecordProcessor,
@@ -519,20 +519,18 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource, sam
519519
if _is_lambda_environment():
520520
provider.add_span_processor(AwsLambdaSpanProcessor())
521521

522-
# We always send 100% spans to Genesis platform for agent observability because
522+
# Propagates baggage entries matching OTEL_BAGGAGE_SPAN_ATTRIBUTE_KEYS into span attributes.
523+
baggage_keys: set[str] = _parse_otel_baggage_keys_env_var()
524+
525+
# We always send 100% spans to AgentCore Runtime platform for agent observability because
523526
# AI applications typically have low throughput traffic patterns and require
524527
# comprehensive monitoring to catch subtle failure modes like hallucinations
525528
# and quality degradation that sampling could miss.
526-
# Add session.id baggage attribute to span attributes to support AI Agent use cases
527-
# enabling session ID tracking in spans.
528-
if is_agent_observability_enabled():
529+
if is_agentic_observability_enabled():
529530
_export_unsampled_span_for_agent_observability(provider, resource)
530-
# propagates baggage entries matching OTEL_BAGGAGE_SPAN_ATTRIBUTE_KEYS into span attributes
531-
raw: str = os.environ.get(OTEL_BAGGAGE_SPAN_ATTRIBUTE_KEYS, "").strip()
532-
keys: set[str] = {k.strip() for k in raw.split(",") if k.strip()}
531+
baggage_keys.add("session.id")
533532

534-
keys.add("session.id")
535-
provider.add_span_processor(BaggageSpanProcessor(lambda key: key in keys))
533+
provider.add_span_processor(BaggageSpanProcessor(lambda key: key in baggage_keys))
536534

537535
if not _is_application_signals_enabled():
538536
return
@@ -635,7 +633,7 @@ def _customize_resource(resource: Resource) -> Resource:
635633

636634
custom_attributes = {AWS_LOCAL_SERVICE: service_name}
637635

638-
if is_agent_observability_enabled():
636+
if is_agentic_observability_enabled():
639637
# Add aws.service.type if it doesn't exist in the resource
640638
if resource and resource.attributes.get(AWS_SERVICE_TYPE) is None:
641639
# Set a default agent type for AI agent observability
@@ -737,6 +735,11 @@ def _fetch_logs_header() -> OtlpLogHeaderSetting:
737735
return _otlp_log_header_setting_cache
738736

739737

738+
def _parse_otel_baggage_keys_env_var() -> set[str]:
739+
raw: str = os.environ.get(OTEL_BAGGAGE_SPAN_ATTRIBUTE_KEYS, "").strip()
740+
return {k.strip() for k in raw.split(",") if k.strip()}
741+
742+
740743
def _clear_logs_header_cache():
741744
"""Clear the singleton cache for OtlpLogHeaderSetting. Used primarily for testing."""
742745
global _otlp_log_header_setting_cache # pylint: disable=global-statement
@@ -916,7 +919,7 @@ def _create_aws_otlp_exporter(endpoint: str, service: str, region: str):
916919
from amazon.opentelemetry.distro.exporter.otlp.aws.traces.otlp_aws_span_exporter import OTLPAwsSpanExporter
917920

918921
if service == XRAY_SERVICE:
919-
if is_agent_observability_enabled():
922+
if is_agentic_observability_enabled():
920923
# Span exporter needs an instance of logger provider in ai agent
921924
# observability case because we need to split input/output prompts
922925
# from span attributes and send them to the logs pipeline per

0 commit comments

Comments
 (0)