Skip to content

Commit 704dcb6

Browse files
authored
Merge branch 'main' into setup-unsampled-span-pipeline
2 parents 173849a + aed584f commit 704dcb6

File tree

10 files changed

+654
-8
lines changed

10 files changed

+654
-8
lines changed

.github/workflows/release-lambda.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
default: 'us-east-1, us-east-2, us-west-1, us-west-2, ap-south-1, ap-northeast-3, ap-northeast-2, ap-southeast-1, ap-southeast-2, ap-northeast-1, ca-central-1, eu-central-1, eu-west-1, eu-west-2, eu-west-3, eu-north-1, sa-east-1, af-south-1, ap-east-1, ap-south-2, ap-southeast-3, ap-southeast-4, eu-central-2, eu-south-1, eu-south-2, il-central-1, me-central-1, me-south-1'
1313

1414
env:
15-
COMMERCIAL_REGIONS: us-east-1, us-east-2, us-west-1, us-west-2, ap-south-1, ap-northeast-3, ap-northeast-2, ap-southeast-1, ap-southeast-2, ap-northeast-1, ca-central-1, eu-central-1, eu-west-1, eu-west-2, eu-west-3, eu-north-1, sa-east-1
15+
COMMERCIAL_REGIONS: us-east-1, us-east-2, us-west-1, us-west-2, ap-south-1, ap-northeast-3, ap-northeast-2, ap-southeast-1, ap-southeast-2, ap-northeast-1, ca-central-1, eu-central-1, eu-west-1, eu-west-2, eu-west-3, eu-north-1, sa-east-1, ap-southeast-5, ap-southeast-7, mx-central-1, ca-west-1, cn-north-1, cn-northwest-1
1616
LAYER_NAME: AWSOpenTelemetryDistroPython
1717

1818
permissions:

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,32 @@ def is_installed(req: str) -> bool:
3535
def is_agent_observability_enabled() -> bool:
3636
"""Is the Agentic AI monitoring flag set to true?"""
3737
return os.environ.get(AGENT_OBSERVABILITY_ENABLED, "false").lower() == "true"
38+
39+
40+
def get_aws_region() -> str:
41+
"""Get AWS region using botocore session.
42+
43+
botocore automatically checks in the following priority order:
44+
1. AWS_REGION environment variable
45+
2. AWS_DEFAULT_REGION environment variable
46+
3. AWS CLI config file (~/.aws/config)
47+
4. EC2 instance metadata service
48+
49+
Returns:
50+
The AWS region if found, None otherwise.
51+
"""
52+
if is_installed("botocore"):
53+
try:
54+
from botocore import session # pylint: disable=import-outside-toplevel
55+
56+
botocore_session = session.Session()
57+
if botocore_session.region_name:
58+
return botocore_session.region_name
59+
except (ImportError, AttributeError):
60+
# botocore failed to determine region
61+
pass
62+
63+
_logger.warning(
64+
"AWS region not found. Please set AWS_REGION environment variable or configure AWS CLI with 'aws configure'."
65+
)
66+
return None

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@
102102
# UDP package size is not larger than 64KB
103103
LAMBDA_SPAN_EXPORT_BATCH_SIZE = 10
104104

105+
OTEL_TRACES_EXPORTER = "OTEL_TRACES_EXPORTER"
106+
OTEL_LOGS_EXPORTER = "OTEL_LOGS_EXPORTER"
107+
OTEL_METRICS_EXPORTER = "OTEL_METRICS_EXPORTER"
108+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
109+
OTEL_TRACES_SAMPLER = "OTEL_TRACES_SAMPLER"
110+
OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "OTEL_PYTHON_DISABLED_INSTRUMENTATIONS"
111+
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED = "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED"
112+
105113
_logger: Logger = getLogger(__name__)
106114

107115

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44
import sys
55
from logging import Logger, getLogger
66

7+
from amazon.opentelemetry.distro._utils import get_aws_region, is_agent_observability_enabled
8+
from amazon.opentelemetry.distro.aws_opentelemetry_configurator import (
9+
APPLICATION_SIGNALS_ENABLED_CONFIG,
10+
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
11+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
12+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
13+
OTEL_LOGS_EXPORTER,
14+
OTEL_METRICS_EXPORTER,
15+
OTEL_PYTHON_DISABLED_INSTRUMENTATIONS,
16+
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED,
17+
OTEL_TRACES_EXPORTER,
18+
OTEL_TRACES_SAMPLER,
19+
)
720
from amazon.opentelemetry.distro.patches._instrumentation_patch import apply_instrumentation_patches
821
from opentelemetry.distro import OpenTelemetryDistro
922
from opentelemetry.environment_variables import OTEL_PROPAGATORS, OTEL_PYTHON_ID_GENERATOR
@@ -65,5 +78,44 @@ def _configure(self, **kwargs):
6578
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION, "base2_exponential_bucket_histogram"
6679
)
6780

81+
if is_agent_observability_enabled():
82+
# "otlp" is already native OTel default, but we set them here to be explicit
83+
# about intended configuration for agent observability
84+
os.environ.setdefault(OTEL_TRACES_EXPORTER, "otlp")
85+
os.environ.setdefault(OTEL_LOGS_EXPORTER, "otlp")
86+
os.environ.setdefault(OTEL_METRICS_EXPORTER, "awsemf")
87+
88+
# Set GenAI capture content default
89+
os.environ.setdefault(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, "true")
90+
91+
# Set OTLP endpoints with AWS region if not already set
92+
region = get_aws_region()
93+
if region:
94+
os.environ.setdefault(
95+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, f"https://xray.{region}.amazonaws.com/v1/traces"
96+
)
97+
os.environ.setdefault(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, f"https://logs.{region}.amazonaws.com/v1/logs")
98+
else:
99+
_logger.warning(
100+
"AWS region could not be determined. OTLP endpoints will not be automatically configured. "
101+
"Please set AWS_REGION environment variable or configure OTLP endpoints manually."
102+
)
103+
104+
# Set sampler default
105+
os.environ.setdefault(OTEL_TRACES_SAMPLER, "parentbased_always_on")
106+
107+
# Set disabled instrumentations default
108+
os.environ.setdefault(
109+
OTEL_PYTHON_DISABLED_INSTRUMENTATIONS,
110+
"http,sqlalchemy,psycopg2,pymysql,sqlite3,aiopg,asyncpg,mysql_connector,"
111+
"botocore,boto3,urllib3,requests,starlette",
112+
)
113+
114+
# Set logging auto instrumentation default
115+
os.environ.setdefault(OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true")
116+
117+
# Disable AWS Application Signals by default
118+
os.environ.setdefault(APPLICATION_SIGNALS_ENABLED_CONFIG, "false")
119+
68120
if kwargs.get("apply_patches", True):
69121
apply_instrumentation_patches()

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/otlp/aws/traces/otlp_aws_span_exporter.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4-
from typing import Dict, Optional
4+
import logging
5+
from typing import Dict, Optional, Sequence
56

7+
from amazon.opentelemetry.distro._utils import is_agent_observability_enabled
68
from amazon.opentelemetry.distro.exporter.otlp.aws.common.aws_auth_session import AwsAuthSession
9+
from amazon.opentelemetry.distro.llo_handler import LLOHandler
10+
from opentelemetry._logs import get_logger_provider
711
from opentelemetry.exporter.otlp.proto.http import Compression
812
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
913
from opentelemetry.sdk._logs import LoggerProvider
14+
from opentelemetry.sdk.trace import ReadableSpan
15+
from opentelemetry.sdk.trace.export import SpanExportResult
16+
17+
logger = logging.getLogger(__name__)
1018

1119

1220
class OTLPAwsSpanExporter(OTLPSpanExporter):
@@ -23,6 +31,7 @@ def __init__(
2331
):
2432
self._aws_region = None
2533
self._logger_provider = logger_provider
34+
self._llo_handler = None
2635

2736
if endpoint:
2837
self._aws_region = endpoint.split(".")[1]
@@ -38,3 +47,29 @@ def __init__(
3847
compression,
3948
session=AwsAuthSession(aws_region=self._aws_region, service="xray"),
4049
)
50+
51+
def _ensure_llo_handler(self):
52+
"""Lazily initialize LLO handler when needed to avoid initialization order issues"""
53+
if self._llo_handler is None and is_agent_observability_enabled():
54+
if self._logger_provider is None:
55+
try:
56+
self._logger_provider = get_logger_provider()
57+
except Exception as exc: # pylint: disable=broad-exception-caught
58+
logger.debug("Failed to get logger provider: %s", exc)
59+
return False
60+
61+
if self._logger_provider:
62+
self._llo_handler = LLOHandler(self._logger_provider)
63+
return True
64+
65+
return self._llo_handler is not None
66+
67+
def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
68+
try:
69+
if is_agent_observability_enabled() and self._ensure_llo_handler():
70+
llo_processed_spans = self._llo_handler.process_spans(spans)
71+
return super().export(llo_processed_spans)
72+
except Exception: # pylint: disable=broad-exception-caught
73+
return SpanExportResult.FAILURE
74+
75+
return super().export(spans)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
from opentelemetry.sdk._logs import LoggerProvider
4+
5+
6+
class LLOHandler:
7+
"""
8+
Utility class for handling Large Language Objects (LLO) in OpenTelemetry spans.
9+
10+
LLOHandler performs three primary functions:
11+
1. Identifies input/output prompt content in spans
12+
2. Extracts and transforms these attributes into an OpenTelemetry Gen AI Event
13+
3. Filters input/output prompts from spans to maintain privacy and reduce span size
14+
15+
This LLOHandler supports the following third-party instrumentation libraries:
16+
- Strands
17+
- OpenInference
18+
- Traceloop/OpenLLMetry
19+
- OpenLIT
20+
"""
21+
22+
def __init__(self, logger_provider: LoggerProvider):
23+
"""
24+
Initialize an LLOHandler with the specified logger provider.
25+
26+
This constructor sets up the event logger provider, configures the event logger,
27+
and initializes the patterns used to identify LLO attributes.
28+
29+
Args:
30+
logger_provider: The OpenTelemetry LoggerProvider used for emitting events.
31+
Global LoggerProvider instance injected from our AwsOpenTelemetryConfigurator
32+
"""

0 commit comments

Comments
 (0)