Skip to content

Commit 03877f1

Browse files
committed
removed aws span and logs exporter
1 parent 69d225c commit 03877f1

File tree

6 files changed

+158
-136
lines changed

6 files changed

+158
-136
lines changed

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

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
AwsMetricAttributesSpanExporterBuilder,
2222
)
2323
from amazon.opentelemetry.distro.aws_span_metrics_processor_builder import AwsSpanMetricsProcessorBuilder
24-
from amazon.opentelemetry.distro.exporter.otlp.aws.logs.otlp_aws_logs_exporter import OTLPAwsLogExporter
25-
from amazon.opentelemetry.distro.exporter.otlp.aws.traces.otlp_aws_span_exporter import OTLPAwsSpanExporter
24+
from amazon.opentelemetry.distro.exporter.otlp.aws.common.aws_auth_session import AwsAuthSession
2625
from amazon.opentelemetry.distro.otlp_udp_exporter import OTLPUdpSpanExporter
2726
from amazon.opentelemetry.distro.sampler.aws_xray_remote_sampler import AwsXRayRemoteSampler
2827
from amazon.opentelemetry.distro.scope_based_exporter import ScopeBasedPeriodicExportingMetricReader
@@ -89,10 +88,14 @@
8988
SYSTEM_METRICS_INSTRUMENTATION_SCOPE_NAME = "opentelemetry.instrumentation.system_metrics"
9089
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
9190
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
91+
OTEL_EXPORTER_OTLP_LOGS_HEADERS = "OTEL_EXPORTER_OTLP_LOGS_HEADERS"
9292

9393
AWS_TRACES_OTLP_ENDPOINT_PATTERN = r"https://xray\.([a-z0-9-]+)\.amazonaws\.com/v1/traces$"
9494
AWS_LOGS_OTLP_ENDPOINT_PATTERN = r"https://logs\.([a-z0-9-]+)\.amazonaws\.com/v1/logs$"
9595

96+
AWS_OTLP_LOGS_GROUP_HEADER = "x-aws-log-group"
97+
AWS_OTLP_LOGS_STREAM_HEADER = "x-aws-log-stream"
98+
9699
# UDP package size is not larger than 64KB
97100
LAMBDA_SPAN_EXPORT_BATCH_SIZE = 10
98101

@@ -173,6 +176,11 @@ def _init_logging(
173176
resource: Resource = None,
174177
):
175178

179+
# Provides a default OTLP log exporter when none is specified.
180+
# This is the behavior for the logs exporters for other languages.
181+
if not exporters:
182+
exporters.setdefault("otlp", OTLPLogExporter)
183+
176184
provider = LoggerProvider(resource=resource)
177185
set_logger_provider(provider)
178186

@@ -339,17 +347,20 @@ def _customize_sampler(sampler: Sampler) -> Sampler:
339347

340348

341349
def _customize_span_exporter(span_exporter: SpanExporter, resource: Resource) -> SpanExporter:
350+
traces_endpoint = os.environ.get(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
342351
if _is_lambda_environment():
343352
# Override OTLP http default endpoint to UDP
344-
if isinstance(span_exporter, OTLPSpanExporter) and os.getenv(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) is None:
353+
if isinstance(span_exporter, OTLPSpanExporter) and traces_endpoint is None:
345354
traces_endpoint = os.environ.get(AWS_XRAY_DAEMON_ADDRESS_CONFIG, "127.0.0.1:2000")
346355
span_exporter = OTLPUdpSpanExporter(endpoint=traces_endpoint)
347356

348-
if is_aws_otlp_endpoint(os.environ.get(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT), "xray"):
349-
_logger.info("Detected using AWS OTLP XRay Endpoint.")
357+
if is_aws_otlp_endpoint(traces_endpoint, "xray"):
358+
_logger.info("Detected using AWS OTLP Traces Endpoint.")
350359

351360
if isinstance(span_exporter, OTLPSpanExporter):
352-
span_exporter = OTLPAwsSpanExporter(endpoint=os.getenv(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT))
361+
span_exporter = OTLPSpanExporter(
362+
endpoint=traces_endpoint, session=AwsAuthSession(traces_endpoint.split(".")[1], "xray")
363+
)
353364

354365
else:
355366
_logger.warning(
@@ -364,11 +375,18 @@ def _customize_span_exporter(span_exporter: SpanExporter, resource: Resource) ->
364375

365376

366377
def _customize_logs_exporter(log_exporter: LogExporter, resource: Resource) -> LogExporter:
367-
if is_aws_otlp_endpoint(os.environ.get(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT), "logs"):
378+
logs_endpoint = os.environ.get(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)
379+
380+
if is_aws_otlp_endpoint(logs_endpoint, "logs"):
368381
_logger.info("Detected using AWS OTLP Logs Endpoint.")
369382

370-
if isinstance(log_exporter, OTLPLogExporter):
371-
return OTLPAwsLogExporter(endpoint=os.getenv(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT))
383+
if isinstance(log_exporter, OTLPLogExporter) and validate_logs_headers():
384+
return OTLPLogExporter(endpoint=logs_endpoint, session=AwsAuthSession(logs_endpoint.split(".")[1], "logs"))
385+
386+
_logger.warning(
387+
"Improper configuration see: please export/set "
388+
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/protobuf and OTEL_LOGS_EXPORTER=otlp"
389+
)
372390

373391
return log_exporter
374392

@@ -504,6 +522,37 @@ def is_aws_otlp_endpoint(otlp_endpoint: str = None, service: str = "xray") -> bo
504522
return bool(re.match(pattern, otlp_endpoint.lower()))
505523

506524

525+
def validate_logs_headers() -> bool:
526+
"""Checks if x-aws-log-group and x-aws-log-stream are present in the headers in order to send logs to
527+
AWS OTLP Logs endpoint."""
528+
529+
logs_headers = os.environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS)
530+
531+
if not logs_headers:
532+
_logger.warning(
533+
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS "
534+
"to include x-aws-log-group and x-aws-log-stream"
535+
)
536+
return False
537+
538+
filtered_log_headers_count = 0
539+
540+
for pair in logs_headers.split(","):
541+
if "=" in pair:
542+
key = pair.split("=", 1)[0]
543+
if key == AWS_OTLP_LOGS_GROUP_HEADER or key == AWS_OTLP_LOGS_STREAM_HEADER:
544+
filtered_log_headers_count += 1
545+
546+
if filtered_log_headers_count != 2:
547+
_logger.warning(
548+
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS "
549+
"to have values for x-aws-log-group and x-aws-log-stream"
550+
)
551+
return False
552+
553+
return True
554+
555+
507556
def _get_metric_export_interval():
508557
export_interval_millis = float(os.environ.get(METRIC_EXPORT_INTERVAL_CONFIG, DEFAULT_METRIC_EXPORT_INTERVAL))
509558
_logger.debug("Span Metrics export interval: %s", export_interval_millis)

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/otlp/aws/common/aws_auth_session.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,34 @@
1111

1212

1313
class AwsAuthSession(requests.Session):
14+
"""
15+
A custom requests Session that adds AWS SigV4 authentication to HTTP requests.
16+
17+
This class extends the standard requests.Session to automatically sign requests
18+
with AWS Signature Version 4 (SigV4) authentication. It's specifically designed
19+
for use with the OpenTelemetry Logs and Traces exporters that send data to AWS OTLP endpoints:
20+
X-Ray (traces) and CloudWatch Logs.
21+
22+
The session requires botocore to be installed for signing headers. If botocore
23+
is not available, the session will fall back to standard unauthenticated requests
24+
and log an error message.
25+
26+
Usage:
27+
session = AwsAuthSession(aws_region="us-west-2", service="logs")
28+
response = session.request("POST", "https://logs.us-west-2.amazonaws.com/v1/logs",
29+
data=payload, headers=headers)
30+
31+
Args:
32+
aws_region (str): The AWS region to use for signing (e.g., "us-east-1")
33+
service (str): The AWS service name for signing (e.g., "logs" or "xray")
34+
"""
1435

1536
def __init__(self, aws_region, service):
1637

1738
self._has_required_dependencies = False
1839

1940
# Requires botocore to be installed to sign the headers. However,
20-
# some users might not need to use this exporter. In order not conflict
41+
# some users might not need to use this authenticator. In order not conflict
2142
# with existing behavior, we check for botocore before initializing this exporter.
2243

2344
if aws_region and service and is_installed("botocore"):

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/otlp/aws/logs/otlp_aws_logs_exporter.py

Lines changed: 0 additions & 45 deletions
This file was deleted.

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

Lines changed: 0 additions & 45 deletions
This file was deleted.

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test_otlp_aws_exporter.py renamed to aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test_aws_auth_session.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
from botocore.credentials import Credentials
88

99
from amazon.opentelemetry.distro.exporter.otlp.aws.common.aws_auth_session import AwsAuthSession
10-
from amazon.opentelemetry.distro.exporter.otlp.aws.logs.otlp_aws_logs_exporter import OTLPAwsLogExporter
11-
from amazon.opentelemetry.distro.exporter.otlp.aws.traces.otlp_aws_span_exporter import OTLPAwsSpanExporter
12-
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
13-
from opentelemetry.exporter.otlp.proto.http.trace_exporter import DEFAULT_COMPRESSION, DEFAULT_TIMEOUT, OTLPSpanExporter
10+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import DEFAULT_COMPRESSION, DEFAULT_TIMEOUT
1411
from opentelemetry.exporter.otlp.proto.http.version import __version__
1512

1613
AWS_OTLP_TRACES_ENDPOINT = "https://xray.us-east-1.amazonaws.com/v1/traces"
@@ -25,19 +22,7 @@
2522
mock_credentials = Credentials(access_key="test_access_key", secret_key="test_secret_key", token="test_session_token")
2623

2724

28-
class TestAwsExporter(TestCase):
29-
30-
def test_sigv4_exporter_init_default(self):
31-
"""Tests that the Sigv4 exporters is is still an instance of upstream's exporter"""
32-
33-
test_cases = [
34-
[OTLPAwsSpanExporter(endpoint=AWS_OTLP_TRACES_ENDPOINT), AWS_OTLP_TRACES_ENDPOINT, OTLPSpanExporter],
35-
[OTLPAwsLogExporter(endpoint=AWS_OTLP_LOGS_ENDPOINT), AWS_OTLP_LOGS_ENDPOINT, OTLPLogExporter],
36-
]
37-
38-
for tc in test_cases:
39-
self.validate_exporter_extends_http_exporter(exporter=tc[0], endpoint=tc[1], exporter_type=tc[2])
40-
25+
class TestAwsAuthSession(TestCase):
4126
@patch("pkg_resources.get_distribution", side_effect=ImportError("test error"))
4227
@patch.dict("sys.modules", {"botocore": None}, clear=False)
4328
@patch("requests.Session.request", return_value=requests.Response())

0 commit comments

Comments
 (0)