Skip to content

Commit 6ffc78e

Browse files
authored
SigV4 Authentication Support for OTLP HTTP Logs Exporter (#1079)
**Background** Supporting ADOT auto instrumentation to automatically inject SigV4 authentication headers for outgoing export log requests to the allow exporting to the AWS Logs OTLP endpoint. Users will need to configure the following environment variables in order to enable and properly run this exporter: `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://logs.[AWS-REGION].amazonaws.com/v1/logs`; **required** ~`OTEL_AWS_LOG_GROUP=[CW-LOG-GROUP-NAME]` **required**~ ~`OTEL_AWS_LOG_STREAM=[CW-LOG-STREAM-NAME]` **required**~ `OTEL_EXPORTER_OTLP_LOGS_HEADERS`=`x-aws-log-group=[CW-LOG-GROUP-NAME],x-aws-log-stream=[CW-LOG-STREAM-NAME]` **required** `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/protobuf` **required or do not set env variable** `OTEL_LOGS_EXPORTER=otlp` **required or do not set env variable** `OTEL_METRICS_EXPORTER=none` **Description of changes:** 1. Added new `OtlpAwsLogsExporter` class which uses composition to extend upstream's `OtlpHttpLogsRecorderExporter` which is responsible for making the http client calls to export logs to the given endpoint. 2. The `OtlpAwsLogsExporter` customizes the headers by adding an intermediary step to sign the request with SigV4 authentication and injects the signed headers to the outgoing logs export request 3. In order to ensure we don't override any user configurations from environment variables, the `OtlpAwsLogsExporter` constructor copies all existing `LogsExporter` configurations create by upstream's instrumentation. 4. The ADOT auto instrumentation is now configured to automatically detect if a user is exporting to CW Logs OTLP Logs endpoint by checking if the environment variable `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` is configured to match this url pattern: `https://logs.[AWS-REGION].amazonaws.com/v1/logs` **Testing:** 1. E2E test done in an empty EC2 environment without configuring .aws credentials config file or setting AWS credentials in the environment variable 2. Manual testing was done by configuring the above environment variables and setting up the sample app locally with ADOT auto instrumentation and verified the spans in CW Logs. 3. The sample app was run and rerun 30 times and confirmed no issues with exporting the logs to the endpoint 4. Unit tests were added to verify functionality of OtlpAwsLogsExporter Further testing will be done with the Release tests. Example of a log exported using this exporter: ``` { "resource": { "attributes": { "telemetry.distro.version": "0.1.0-aws-SNAPSHOT", "host.image.id": "ami-0d61ea20f09848335", "process.command_args": [ "/usr/lib/jvm/java-17-amazon-corretto.x86_64/bin/java", "-javaagent:aws-opentelemetry-agent-0.1.0-SNAPSHOT.jar", "-jar", "springboot-0.1.0-SNAPSHOT.jar" ], "process.runtime.version": "17.0.14+7-LTS", "os.type": "linux", "process.pid": 4921, "host.type": "t2.large", "cloud.availability_zone": "us-west-2b", "telemetry.sdk.name": "opentelemetry", "telemetry.sdk.language": "java", "process.runtime.name": "OpenJDK Runtime Environment", "service.instance.id": "9c190d36-a727-4ae9-b050-5f416b0a30b8", "os.description": "Linux 5.10.235-227.919.amzn2.x86_64", "host.arch": "amd64", "host.name": "ip-172-31-42-50.us-west-2.compute.internal", "telemetry.sdk.version": "1.44.1", "cloud.platform": "aws_ec2", "host.id": "i-0cdb19c9ae754e7b7", "cloud.region": "us-west-2", "service.name": "TEST_SERVICE", "telemetry.distro.name": "opentelemetry-java-instrumentation", "cloud.provider": "aws", "cloud.account.id": "571600841604", "process.executable.path": "/usr/lib/jvm/java-17-amazon-corretto.x86_64/bin/java", "process.runtime.description": "Amazon.com Inc. OpenJDK 64-Bit Server VM 17.0.14+7-LTS" } }, "scope": { "name": "com.amazon.sampleapp.DemoController" }, "timeUnixNano": 1745366143259000000, "observedTimeUnixNano": 1745366143259133756, "severityNumber": 9, "severityText": "INFO", "body": "Executing aws-sdk-call", "flags": 1, "traceId": "68082c7f6d9883fcb601f34426c13382", "spanId": "7cff484e6682e5ea" } ``` By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 043b9ef commit 6ffc78e

File tree

11 files changed

+1207
-294
lines changed

11 files changed

+1207
-294
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.opentelemetry.javaagent.providers;
17+
18+
import static software.amazon.opentelemetry.javaagent.providers.AwsApplicationSignalsCustomizerProvider.*;
19+
20+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
21+
import java.util.Arrays;
22+
import java.util.logging.Level;
23+
import java.util.logging.Logger;
24+
import java.util.regex.Pattern;
25+
26+
/** Utilities class to validate ADOT environment variable configuration. */
27+
public final class AwsApplicationSignalsConfigValidator {
28+
private static final Logger logger =
29+
Logger.getLogger(AwsApplicationSignalsCustomizerProvider.class.getName());
30+
31+
/**
32+
* Is the given configuration correct to enable SigV4 for Logs?
33+
*
34+
* <ul>
35+
* <li><code>OTEL_EXPORTER_OTLP_LOGS_ENDPOINT</code>
36+
* =https://logs.[AWS-REGION].amazonaws.com/v1/logs
37+
* <li><code>OTEL_AWS_LOG_GROUP</code>=[CW-LOG-GROUP-NAME]
38+
* <li><code>OTEL_AWS_LOG_STREAM</code>=[CW-LOG-STREAM-NAME]
39+
* <li><code>OTEL_EXPORTER_OTLP_LOGS_PROTOCOL</code>=http/protobuf
40+
* <li><code>OTEL_LOGS_EXPORTER</code>=otlp
41+
* </ul>
42+
*
43+
* <p>NOTE: ** indicates that the environment variable must exactly match this value or must not
44+
* be set at all.
45+
*/
46+
static boolean isSigV4EnabledLogs(ConfigProperties config) {
47+
String logsEndpoint = config.getString(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT);
48+
String logsExporter = config.getString(OTEL_LOGS_EXPORTER);
49+
String logsProtocol = config.getString(OTEL_EXPORTER_OTLP_LOGS_PROTOCOL);
50+
String logsHeaders = config.getString(OTEL_EXPORTER_OTLP_LOGS_HEADERS);
51+
52+
if (!isSigv4ValidConfig(
53+
logsEndpoint,
54+
AWS_OTLP_LOGS_ENDPOINT_PATTERN,
55+
OTEL_LOGS_EXPORTER,
56+
logsExporter,
57+
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL,
58+
logsProtocol)) {
59+
return false;
60+
}
61+
62+
if (logsHeaders == null || logsHeaders.isEmpty()) {
63+
logger.warning(
64+
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS to include x-aws-log-group and x-aws-log-stream");
65+
66+
return false;
67+
}
68+
69+
long filteredLogHeaders =
70+
Arrays.stream(logsHeaders.split(","))
71+
.filter(
72+
pair -> {
73+
if (pair.contains("=")) {
74+
String key = pair.split("=", 2)[0];
75+
return key.equals(AWS_OTLP_LOGS_GROUP_HEADER)
76+
|| key.equals(AWS_OTLP_LOGS_STREAM_HEADER);
77+
}
78+
return false;
79+
})
80+
.count();
81+
82+
if (filteredLogHeaders != 2) {
83+
logger.warning(
84+
"Improper configuration: Please configure the environment variable OTEL_EXPORTER_OTLP_LOGS_HEADERS to have values for x-aws-log-group and x-aws-log-stream");
85+
return false;
86+
}
87+
88+
return true;
89+
}
90+
91+
/**
92+
* Is the given configuration correct to enable SigV4 for Traces?
93+
*
94+
* <ul>
95+
* <li><code>OTEL_EXPORTER_OTLP_TRACES_ENDPOINT</code>
96+
* =https://xray.[AWS-REGION].amazonaws.com/v1/traces
97+
* <li><code>OTEL_EXPORTER_OTLP_TRACES_PROTOCOL</code>=http/protobuf **
98+
* <li><code>OTEL_TRACES_EXPORTER</code>=otlp **
99+
* </ul>
100+
*
101+
* <p>NOTE: ** indicates that the environment variable must exactly match this value or must not
102+
* be set at all.
103+
*/
104+
static boolean isSigV4EnabledTraces(ConfigProperties config) {
105+
String tracesEndpoint = config.getString(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);
106+
String tracesExporter = config.getString(OTEL_TRACES_EXPORTER);
107+
String tracesProtocol = config.getString(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL);
108+
109+
return isSigv4ValidConfig(
110+
tracesEndpoint,
111+
AWS_OTLP_TRACES_ENDPOINT_PATTERN,
112+
OTEL_TRACES_EXPORTER,
113+
tracesExporter,
114+
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL,
115+
tracesProtocol);
116+
}
117+
118+
/**
119+
* Determines if the required configurations for the signal type is correct. These environment
120+
* variables must exactly match this value or must not be set at all.
121+
*
122+
* <ul>
123+
* <li><code>OTEL_EXPORTER_OTLP_{SIGNAL}_ENDPOINT</code>=[AWS OTLP LOGS or TRACES endpoint]
124+
* <li><code>OTEL_EXPORTER_OTLP_{SIGNAL}_PROTOCOL</code>=http/protobuf
125+
* <li><code>OTEL_{SIGNAL}_EXPORTER</code>=otlp
126+
* </ul>
127+
*/
128+
private static boolean isSigv4ValidConfig(
129+
String endpoint,
130+
String endpointPattern,
131+
String exporterType,
132+
String exporter,
133+
String protocolConfig,
134+
String protocol) {
135+
boolean isValidOtlpEndpoint;
136+
try {
137+
isValidOtlpEndpoint =
138+
endpoint != null
139+
&& Pattern.compile(endpointPattern).matcher(endpoint.toLowerCase()).matches();
140+
141+
if (isValidOtlpEndpoint) {
142+
logger.log(Level.INFO, String.format("Detected using AWS OTLP Endpoint: %s.", endpoint));
143+
144+
if (exporter != null && !exporter.equals("otlp")) {
145+
logger.warning(
146+
String.format(
147+
"Improper configuration: Please configure your environment variables and export/set %s=otlp",
148+
exporterType));
149+
return false;
150+
}
151+
152+
if (protocol != null && !protocol.equals(OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL)) {
153+
logger.warning(
154+
String.format(
155+
"Improper configuration: Please configure your environment variables and export/set %s=%s",
156+
protocolConfig, OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL));
157+
return false;
158+
}
159+
160+
return true;
161+
}
162+
} catch (Exception e) {
163+
logger.warning(
164+
String.format(
165+
"Caught error while attempting to validate configuration to export to %s: %s",
166+
endpoint, e.getMessage()));
167+
}
168+
169+
return false;
170+
}
171+
}

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsApplicationSignalsCustomizerProvider.java

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.api.common.AttributesBuilder;
2020
import io.opentelemetry.contrib.awsxray.AlwaysRecordSampler;
2121
import io.opentelemetry.contrib.awsxray.ResourceHolder;
22+
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
2223
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
2324
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
2425
import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil;
@@ -28,6 +29,7 @@
2829
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
2930
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
3031
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
32+
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
3133
import io.opentelemetry.sdk.metrics.Aggregation;
3234
import io.opentelemetry.sdk.metrics.InstrumentType;
3335
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
@@ -52,7 +54,9 @@
5254
import java.util.Set;
5355
import java.util.logging.Level;
5456
import java.util.logging.Logger;
55-
import java.util.regex.Pattern;
57+
import javax.annotation.concurrent.Immutable;
58+
import software.amazon.opentelemetry.javaagent.providers.exporter.otlp.aws.logs.OtlpAwsLogsExporterBuilder;
59+
import software.amazon.opentelemetry.javaagent.providers.exporter.otlp.aws.traces.OtlpAwsSpanExporterBuilder;
5660

5761
/**
5862
* This customizer performs the following customizations:
@@ -69,21 +73,29 @@
6973
* otel.aws.application.signals.enabled or the environment variable
7074
* OTEL_AWS_APPLICATION_SIGNALS_ENABLED. This flag is disabled by default.
7175
*/
72-
public class AwsApplicationSignalsCustomizerProvider
76+
@Immutable
77+
public final class AwsApplicationSignalsCustomizerProvider
7378
implements AutoConfigurationCustomizerProvider {
7479
static final String AWS_LAMBDA_FUNCTION_NAME_CONFIG = "AWS_LAMBDA_FUNCTION_NAME";
75-
private static final String XRAY_OTLP_ENDPOINT_PATTERN =
76-
"^https://xray\\.([a-z0-9-]+)\\.amazonaws\\.com/v1/traces$";
7780

7881
private static final Duration DEFAULT_METRIC_EXPORT_INTERVAL = Duration.ofMinutes(1);
7982
private static final Logger logger =
8083
Logger.getLogger(AwsApplicationSignalsCustomizerProvider.class.getName());
8184

85+
static final String AWS_OTLP_TRACES_ENDPOINT_PATTERN =
86+
"^https://xray\\.([a-z0-9-]+)\\.amazonaws\\.com/v1/traces$";
87+
88+
static final String AWS_OTLP_LOGS_ENDPOINT_PATTERN =
89+
"^https://logs\\.([a-z0-9-]+)\\.amazonaws\\.com/v1/logs$";
90+
91+
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-OTLPEndpoint.html#CloudWatch-LogsEndpoint
92+
static final String AWS_OTLP_LOGS_GROUP_HEADER = "x-aws-log-group";
93+
static final String AWS_OTLP_LOGS_STREAM_HEADER = "x-aws-log-stream";
94+
8295
private static final String DEPRECATED_SMP_ENABLED_CONFIG = "otel.smp.enabled";
8396
private static final String DEPRECATED_APP_SIGNALS_ENABLED_CONFIG =
8497
"otel.aws.app.signals.enabled";
85-
private static final String APPLICATION_SIGNALS_ENABLED_CONFIG =
86-
"otel.aws.application.signals.enabled";
98+
static final String APPLICATION_SIGNALS_ENABLED_CONFIG = "otel.aws.application.signals.enabled";
8799

88100
private static final String OTEL_RESOURCE_PROVIDERS_AWS_ENABLED =
89101
"otel.resource.providers.aws.enabled";
@@ -99,9 +111,8 @@ public class AwsApplicationSignalsCustomizerProvider
99111
private static final String OTEL_JMX_TARGET_SYSTEM_CONFIG = "otel.jmx.target.system";
100112
private static final String OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_CONFIG =
101113
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
102-
private static final String OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL = "http/protobuf";
103-
private static final String OTEL_EXPORTER_OTLP_TRACES_PROTOCOL_CONFIG =
104-
"OTEL_EXPORTER_OTLP_TRACES_PROTOCOL";
114+
static final String OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL = "http/protobuf";
115+
105116
private static final String AWS_XRAY_DAEMON_ADDRESS_CONFIG = "AWS_XRAY_DAEMON_ADDRESS";
106117
private static final String DEFAULT_UDP_ENDPOINT = "127.0.0.1:2000";
107118
private static final String OTEL_DISABLED_RESOURCE_PROVIDERS_CONFIG =
@@ -110,14 +121,18 @@ public class AwsApplicationSignalsCustomizerProvider
110121
"otel.bsp.max.export.batch.size";
111122

112123
private static final String OTEL_METRICS_EXPORTER = "otel.metrics.exporter";
113-
private static final String OTEL_LOGS_EXPORTER = "otel.logs.exporter";
124+
static final String OTEL_LOGS_EXPORTER = "otel.logs.exporter";
125+
static final String OTEL_TRACES_EXPORTER = "otel.traces.exporter";
126+
static final String OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = "otel.exporter.otlp.traces.protocol";
127+
static final String OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = "otel.exporter.otlp.logs.protocol";
114128
private static final String OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT =
115129
"otel.aws.application.signals.exporter.endpoint";
116130
private static final String OTEL_EXPORTER_OTLP_PROTOCOL = "otel.exporter.otlp.protocol";
117-
private static final String OTEL_EXPORTER_OTLP_TRACES_ENDPOINT =
118-
"otel.exporter.otlp.traces.endpoint";
131+
static final String OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "otel.exporter.otlp.traces.endpoint";
132+
static final String OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "otel.exporter.otlp.logs.endpoint";
119133
private static final String OTEL_TRACES_SAMPLER = "otel.traces.sampler";
120134
private static final String OTEL_TRACES_SAMPLER_ARG = "otel.traces.sampler.arg";
135+
static final String OTEL_EXPORTER_OTLP_LOGS_HEADERS = "otel.exporter.otlp.logs.headers";
121136

122137
// UDP packet can be upto 64KB. To limit the packet size, we limit the exported batch size.
123138
// This is a bit of a magic number, as there is no simple way to tell how many spans can make a
@@ -132,53 +147,13 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) {
132147
autoConfiguration.addTracerProviderCustomizer(this::customizeTracerProviderBuilder);
133148
autoConfiguration.addMeterProviderCustomizer(this::customizeMeterProvider);
134149
autoConfiguration.addSpanExporterCustomizer(this::customizeSpanExporter);
150+
autoConfiguration.addLogRecordExporterCustomizer(this::customizeLogsExporter);
135151
}
136152

137153
static boolean isLambdaEnvironment() {
138154
return System.getenv(AWS_LAMBDA_FUNCTION_NAME_CONFIG) != null;
139155
}
140156

141-
static boolean isSigV4Enabled() {
142-
String otlpEndpoint = System.getenv(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_CONFIG);
143-
boolean isXrayOtlpEndpoint;
144-
try {
145-
isXrayOtlpEndpoint =
146-
otlpEndpoint != null
147-
&& Pattern.compile(XRAY_OTLP_ENDPOINT_PATTERN)
148-
.matcher(otlpEndpoint.toLowerCase())
149-
.matches();
150-
151-
if (isXrayOtlpEndpoint) {
152-
logger.log(Level.INFO, "Detected using AWS OTLP XRay Endpoint.");
153-
154-
String otlpTracesProtocol = System.getenv(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL_CONFIG);
155-
156-
if (otlpTracesProtocol == null
157-
|| !otlpTracesProtocol.equals(OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL)) {
158-
logger.info(
159-
String.format(
160-
"Improper configuration: Please configure your environment variables and export/set %s=%s",
161-
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL_CONFIG, OTEL_EXPORTER_HTTP_PROTOBUF_PROTOCOL));
162-
return false;
163-
}
164-
165-
logger.info(
166-
String.format(
167-
"Proper configuration detected: Now exporting trace span data to %s",
168-
otlpEndpoint));
169-
return true;
170-
}
171-
} catch (Exception e) {
172-
logger.log(
173-
Level.WARNING,
174-
String.format(
175-
"Caught error while attempting to validate configuration to export traces to XRay OTLP endpoint: %s",
176-
e.getMessage()));
177-
}
178-
179-
return false;
180-
}
181-
182157
private boolean isApplicationSignalsEnabled(ConfigProperties configProps) {
183158
return configProps.getBoolean(
184159
APPLICATION_SIGNALS_ENABLED_CONFIG,
@@ -374,8 +349,7 @@ private SdkMeterProviderBuilder customizeMeterProvider(
374349
return sdkMeterProviderBuilder;
375350
}
376351

377-
private SpanExporter customizeSpanExporter(
378-
SpanExporter spanExporter, ConfigProperties configProps) {
352+
SpanExporter customizeSpanExporter(SpanExporter spanExporter, ConfigProperties configProps) {
379353
// When running in Lambda, override the default OTLP exporter with UDP exporter
380354
if (isLambdaEnvironment()) {
381355
if (isOtlpSpanExporter(spanExporter)
@@ -391,15 +365,24 @@ private SpanExporter customizeSpanExporter(
391365
}
392366
}
393367

394-
// When running OTLP endpoint for X-Ray backend, use custom exporter for SigV4 authentication.
395-
if (isSigV4Enabled()) {
396-
// can cast here since we've checked that the environment variable is
397-
// set to http/protobuf
398-
spanExporter =
399-
OtlpAwsSpanExporterBuilder.create(
400-
(OtlpHttpSpanExporter) spanExporter,
401-
System.getenv(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_CONFIG))
402-
.build();
368+
if (AwsApplicationSignalsConfigValidator.isSigV4EnabledTraces(configProps)) {
369+
// can cast here since we've checked that the configuration for OTEL_TRACES_EXPORTER is otlp
370+
// and OTEL_EXPORTER_OTLP_TRACES_PROTOCOL is http/protobuf
371+
// so the given spanExporter will be an instance of OtlpHttpSpanExporter
372+
373+
try {
374+
spanExporter =
375+
OtlpAwsSpanExporterBuilder.create(
376+
(OtlpHttpSpanExporter) spanExporter,
377+
configProps.getString(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT))
378+
.build();
379+
} catch (Exception e) {
380+
// This technically should never happen as the validator checks for the correct env
381+
// variables
382+
throw new IllegalStateException(
383+
"Given SpanExporter is not an instance of OtlpHttpSpanExporter, please check that you have the correct environment variables: ",
384+
e);
385+
}
403386
}
404387

405388
if (isApplicationSignalsEnabled(configProps)) {
@@ -416,6 +399,30 @@ private boolean isOtlpSpanExporter(SpanExporter spanExporter) {
416399
|| spanExporter instanceof OtlpHttpSpanExporter;
417400
}
418401

402+
LogRecordExporter customizeLogsExporter(
403+
LogRecordExporter logsExporter, ConfigProperties configProps) {
404+
if (AwsApplicationSignalsConfigValidator.isSigV4EnabledLogs(configProps)) {
405+
// can cast here since we've checked that the configuration for OTEL_LOGS_EXPORTER is otlp and
406+
// OTEL_EXPORTER_OTLP_LOGS_PROTOCOL is http/protobuf
407+
// so the given logsExporter will be an instance of OtlpHttpLogRecorderExporter
408+
409+
try {
410+
return OtlpAwsLogsExporterBuilder.create(
411+
(OtlpHttpLogRecordExporter) logsExporter,
412+
configProps.getString(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT))
413+
.build();
414+
} catch (Exception e) {
415+
// This technically should never happen as the validator checks for the correct env
416+
// variables
417+
throw new IllegalStateException(
418+
"Given LogsExporter is not an instance of OtlpHttpLogRecordExporter, please check that you have the correct environment variables: ",
419+
e);
420+
}
421+
}
422+
423+
return logsExporter;
424+
}
425+
419426
private enum ApplicationSignalsExporterProvider {
420427
INSTANCE;
421428

0 commit comments

Comments
 (0)