Skip to content

Commit f3d5edb

Browse files
authored
[Logs] Workaround to avoid unwanted OTel log when OTEL_TRACES_SAMPLER = xray (#81)
*Issue #, if available:* Short-term workaround to avoid Upsteam OTel emitting logs such as: - `OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on".` OTel dependencies will always load a default Sampler configuration. Although unused, that load process will read the `OTEL_TRACES_SAMPLER` value and may emit the above log, which is unwanted for `xray` value. `xray` does not yet exist in upstream OTel, but in ADOT, we define it as valid. Thus we temporarily remove this env var to avoid the unwanted log only if `xray` is set in that Env Var. When `xray` sampler is available in upstream, this workaround should be removed. *Description of changes:* - Unset `process.env.OTEL_TRACES_SAMPLER` if equal to `xray`, then use boolean variable to enable `xray` sampler instead of Env Var. Restore Env Var value later. - Add log to state that `AWS XRay Sampler enabled`, if enabled *Testing:* - Tested that the log `OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on".` doesn't appear in this repo's sample app. Before: ``` node --require '@aws/aws-distro-opentelemetry-node-autoinstrumentation/register' sample-app-express-server.js 'pollingInterval' is undefined or too small. Defaulting to 300 seconds OTEL_TRACES_EXPORTER is empty. Using default otlp exporter. AWS Application Signals enabled. AWS Application Signals metrics export interval capped to 60000 OTEL_LOGS_EXPORTER is empty. Using default otlp exporter. OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". Setting TraceProvider for instrumentations at the end of initialization OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". ... OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". AWS Distro of OpenTelemetry automatic instrumentation started successfully Listening for requests on http://localhost:8080 ... OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on". ``` After: ``` node --require '@aws/aws-distro-opentelemetry-node-autoinstrumentation/register' sample-app-express-server.js AWS XRay Sampler enabled 'pollingInterval' is undefined or too small. Defaulting to 300 seconds OTEL_TRACES_EXPORTER is empty. Using default otlp exporter. AWS Application Signals enabled. AWS Application Signals metrics export interval capped to 60000 OTEL_LOGS_EXPORTER is empty. Using default otlp exporter. Setting TraceProvider for instrumentations at the end of initialization AWS Distro of OpenTelemetry automatic instrumentation started successfully Listening for requests on http://localhost:8080 ``` By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent 246e6ea commit f3d5edb

File tree

2 files changed

+51
-33
lines changed

2 files changed

+51
-33
lines changed

aws-distro-opentelemetry-node-autoinstrumentation/src/aws-opentelemetry-configurator.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class AwsOpentelemetryConfigurator {
104104
* @constructor
105105
* @param {Instrumentation[]} instrumentations - Auto-Instrumentations to be added to the ADOT Config
106106
*/
107-
public constructor(instrumentations: Instrumentation[]) {
107+
public constructor(instrumentations: Instrumentation[], useXraySampler: boolean = false) {
108108
/*
109109
* Set and Detect Resources via Resource Detectors
110110
*
@@ -167,7 +167,9 @@ export class AwsOpentelemetryConfigurator {
167167
// https://github.com/aws-observability/aws-otel-java-instrumentation/blob/a011b8cc29ee32b7f668c04ccfdf64cd30de467c/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsTracerCustomizerProvider.java#L36
168168
this.idGenerator = new AWSXRayIdGenerator();
169169

170-
this.sampler = AwsOpentelemetryConfigurator.customizeSampler(customBuildSamplerFromEnv(this.resource));
170+
this.sampler = AwsOpentelemetryConfigurator.customizeSampler(
171+
customBuildSamplerFromEnv(this.resource, useXraySampler)
172+
);
171173

172174
// default SpanProcessors with Span Exporters wrapped inside AwsMetricAttributesSpanExporter
173175
const awsSpanProcessorProvider: AwsSpanProcessorProvider = new AwsSpanProcessorProvider(this.resource);
@@ -291,37 +293,36 @@ export class AwsOpentelemetryConfigurator {
291293
}
292294
}
293295

294-
export function customBuildSamplerFromEnv(resource: Resource): Sampler {
295-
switch (process.env.OTEL_TRACES_SAMPLER) {
296-
case 'xray': {
297-
const samplerArgumentEnv: string | undefined = process.env.OTEL_TRACES_SAMPLER_ARG;
298-
let endpoint: string | undefined = undefined;
299-
let pollingInterval: number | undefined = undefined;
300-
301-
if (samplerArgumentEnv !== undefined) {
302-
const args: string[] = samplerArgumentEnv.split(',');
303-
for (const arg of args) {
304-
const equalIndex: number = arg.indexOf('=');
305-
if (equalIndex === -1) {
306-
continue;
307-
}
308-
const keyValue: string[] = [arg.substring(0, equalIndex), arg.substring(equalIndex + 1)];
309-
if (keyValue[0] === 'endpoint') {
310-
endpoint = keyValue[1];
311-
} else if (keyValue[0] === 'polling_interval') {
312-
pollingInterval = Number(keyValue[1]);
313-
if (isNaN(pollingInterval)) {
314-
pollingInterval = undefined;
315-
diag.error('polling_interval in OTEL_TRACES_SAMPLER_ARG must be a valid number');
316-
}
296+
export function customBuildSamplerFromEnv(resource: Resource, useXraySampler: boolean = false): Sampler {
297+
if (useXraySampler || process.env.OTEL_TRACES_SAMPLER === 'xray') {
298+
const samplerArgumentEnv: string | undefined = process.env.OTEL_TRACES_SAMPLER_ARG;
299+
let endpoint: string | undefined = undefined;
300+
let pollingInterval: number | undefined = undefined;
301+
302+
if (samplerArgumentEnv !== undefined) {
303+
const args: string[] = samplerArgumentEnv.split(',');
304+
for (const arg of args) {
305+
const equalIndex: number = arg.indexOf('=');
306+
if (equalIndex === -1) {
307+
continue;
308+
}
309+
const keyValue: string[] = [arg.substring(0, equalIndex), arg.substring(equalIndex + 1)];
310+
if (keyValue[0] === 'endpoint') {
311+
endpoint = keyValue[1];
312+
} else if (keyValue[0] === 'polling_interval') {
313+
pollingInterval = Number(keyValue[1]);
314+
if (isNaN(pollingInterval)) {
315+
pollingInterval = undefined;
316+
diag.error('polling_interval in OTEL_TRACES_SAMPLER_ARG must be a valid number');
317317
}
318318
}
319319
}
320-
321-
diag.debug(`XRay Sampler Endpoint: ${endpoint}`);
322-
diag.debug(`XRay Sampler Polling Interval: ${pollingInterval}`);
323-
return new AwsXRayRemoteSampler({ resource: resource, endpoint: endpoint, pollingInterval: pollingInterval });
324320
}
321+
322+
diag.info('AWS XRay Sampler enabled');
323+
diag.debug(`XRay Sampler Endpoint: ${endpoint}`);
324+
diag.debug(`XRay Sampler Polling Interval: ${pollingInterval}`);
325+
return new AwsXRayRemoteSampler({ resource: resource, endpoint: endpoint, pollingInterval: pollingInterval });
325326
}
326327

327328
return buildSamplerFromEnv();

aws-distro-opentelemetry-node-autoinstrumentation/src/register.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.
44

5-
import { DiagConsoleLogger, diag, trace } from '@opentelemetry/api';
5+
// Short-term workaround to avoid Upsteam OTel emitting logs such as:
6+
// - `OTEL_TRACES_SAMPLER value "xray invalid, defaulting to always_on".`
7+
// OTel dependencies will always load a default Sampler configuration. Although unused, that
8+
// load process will read the `OTEL_TRACES_SAMPLER` value and may emit the above log, which is
9+
// unwanted for `xray` value. Thus we temporarily remove this env var to avoid the unwanted log.
10+
let useXraySampler = false;
11+
if (process.env.OTEL_TRACES_SAMPLER === 'xray') {
12+
delete process.env.OTEL_TRACES_SAMPLER;
13+
useXraySampler = true;
14+
}
15+
16+
import { diag, DiagConsoleLogger, trace } from '@opentelemetry/api';
617
import { getNodeAutoInstrumentations, InstrumentationConfigMap } from '@opentelemetry/auto-instrumentations-node';
718
import { Instrumentation } from '@opentelemetry/instrumentation';
819
import * as opentelemetry from '@opentelemetry/sdk-node';
@@ -56,7 +67,7 @@ const instrumentations: Instrumentation[] = getNodeAutoInstrumentations(instrume
5667
// Apply instrumentation patches
5768
applyInstrumentationPatches(instrumentations);
5869

59-
const configurator: AwsOpentelemetryConfigurator = new AwsOpentelemetryConfigurator(instrumentations);
70+
const configurator: AwsOpentelemetryConfigurator = new AwsOpentelemetryConfigurator(instrumentations, useXraySampler);
6071
const configuration: Partial<opentelemetry.NodeSDKConfiguration> = configurator.configure();
6172

6273
const sdk: opentelemetry.NodeSDK = new opentelemetry.NodeSDK(configuration);
@@ -67,14 +78,15 @@ const sdk: opentelemetry.NodeSDK = new opentelemetry.NodeSDK(configuration);
6778
// we wish to make contributions to upstream to improve customizability of the Node auto-instrumentation.
6879
try {
6980
sdk.start();
81+
82+
diag.info('Setting TraceProvider for instrumentations at the end of initialization');
7083
for (const instrumentation of instrumentations) {
71-
diag.info('Set TraceProvider for instrumentations at the end of initialization');
7284
instrumentation.setTracerProvider(trace.getTracerProvider());
7385
}
7486

75-
diag.info('AWS Distro of OpenTelemetry automatic instrumentation started successfully');
7687
diag.debug(`Environment variable OTEL_PROPAGATORS is set to '${process.env.OTEL_PROPAGATORS}'`);
7788
diag.debug(`Environment variable OTEL_EXPORTER_OTLP_PROTOCOL is set to '${process.env.OTEL_EXPORTER_OTLP_PROTOCOL}'`);
89+
diag.info('AWS Distro of OpenTelemetry automatic instrumentation started successfully');
7890
} catch (error) {
7991
diag.error(
8092
'Error initializing AWS Distro of OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry',
@@ -90,3 +102,8 @@ process.on('SIGTERM', () => {
90102
});
91103

92104
// END The OpenTelemetry Authors code
105+
106+
// Respect original `OTEL_TRACES_SAMPLER` as we previously deleted it temporarily for value `xray`
107+
if (useXraySampler) {
108+
process.env.OTEL_TRACES_SAMPLER = 'xray';
109+
}

0 commit comments

Comments
 (0)