Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
AwsMetricAttributesSpanExporterBuilder,
)
from amazon.opentelemetry.distro.aws_span_metrics_processor_builder import AwsSpanMetricsProcessorBuilder
from amazon.opentelemetry.distro.otlp_aws_span_exporter import OTLPAwsSpanExporter
from amazon.opentelemetry.distro.exporter.otlp_aws_span_exporter import OTLPAwsSpanExporter
from amazon.opentelemetry.distro.otlp_udp_exporter import OTLPUdpSpanExporter
from amazon.opentelemetry.distro.sampler.aws_xray_remote_sampler import AwsXRayRemoteSampler
from amazon.opentelemetry.distro.scope_based_exporter import ScopeBasedPeriodicExportingMetricReader
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ADOT X-Ray OTLP Trace Export Configuration

This guide explains how to automatically configure ADOT environment variables for exporting traces to [AWS X-Ray OTLP endpoint](https://docs.aws.amazon.com/xray/latest/devguide/xray-opentelemetry.html)

## Pre-requisites:
1. Transaction Search must be enabled in order to send spans to the Xray OTLP endpoint. See [this doc](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Transaction-Search-getting-started.html) on how to enable Transaction Search.

2. Ensure the AWS role in your application environment has [AWSXRayWriteOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSXrayWriteOnlyAccess.html) managed policy attached.

## Environment Variables

Set the following environment variables to **PROPERLY** configure trace export with SigV4 authentication:

```shell
# Set X-Ray endpoint (replace AWS_REGION with your region)
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://xray.<AWS_REGION>.amazonaws.com/v1/traces

# Configure OTLP export protocol
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=none
OTEL_LOGS_EXPORTER=none
OTEL_PYTHON_DISTRO=aws_distro
OTEL_PYTHON_CONFIGURATOR=aws_configurator
OTEL_RESOURCE_ATTRIBUTES="service.name=<YOUR_SERVICE_NAME>"

# Disable application signals (they will be generated in CloudWatch backend)
OTEL_AWS_APPLICATION_SIGNALS_ENABLED=false
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(
):

self._aws_region = None
self._has_dependencies = False

# Requires botocore to be installed to sign the headers. However,
# some users might not need to use this exporter. In order not conflict
Expand All @@ -52,6 +53,7 @@ def __init__(
# The only usecase for this class would be for ADOT Python Auto Instrumentation and that already validates
# the endpoint to be an XRay OTLP endpoint.
self._aws_region = endpoint.split(".")[1]
self._has_dependencies = True

else:
_logger.error(
Expand All @@ -74,23 +76,24 @@ def __init__(
# the same except if the endpoint is an XRay OTLP endpoint, we will sign the request
# with SigV4 in headers before sending it to the endpoint. Otherwise, we will skip signing.
def _export(self, serialized_data: bytes):
request = self.boto_aws_request.AWSRequest(
method="POST",
url=self._endpoint,
data=serialized_data,
headers={"Content-Type": "application/x-protobuf"},
)
if self._has_dependencies:
request = self.boto_aws_request.AWSRequest(
method="POST",
url=self._endpoint,
data=serialized_data,
headers={"Content-Type": "application/x-protobuf"},
)

credentials = self.boto_session.get_credentials()
credentials = self.boto_session.get_credentials()

if credentials is not None:
signer = self.boto_auth.SigV4Auth(credentials, AWS_SERVICE, self._aws_region)
if credentials is not None:
signer = self.boto_auth.SigV4Auth(credentials, AWS_SERVICE, self._aws_region)

try:
signer.add_auth(request)
self._session.headers.update(dict(request.headers))
try:
signer.add_auth(request)
self._session.headers.update(dict(request.headers))

except Exception as signing_error: # pylint: disable=broad-except
_logger.error("Failed to sign request: %s", signing_error)
except Exception as signing_error: # pylint: disable=broad-except
_logger.error("Failed to sign request: %s", signing_error)

return super()._export(serialized_data)
Loading