Skip to content

Commit 7814fe6

Browse files
authored
Auto-Configure ADOT SDK Defaults for Agent Observability (#195)
*Issue #, if available:* *Description of changes:* 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 83a1c85 commit 7814fe6

File tree

4 files changed

+174
-11
lines changed

4 files changed

+174
-11
lines changed

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

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Instrumentation } from '@opentelemetry/instrumentation';
1919
import * as opentelemetry from '@opentelemetry/sdk-node';
2020
import { AwsOpentelemetryConfigurator } from './aws-opentelemetry-configurator';
2121
import { applyInstrumentationPatches, customExtractor } from './patches/instrumentation-patch';
22+
import { getAwsRegionFromEnvironment, isAgentObservabilityEnabled } from './utils';
2223

2324
diag.setLogger(new DiagConsoleLogger(), opentelemetry.core.getEnv().OTEL_LOG_LEVEL);
2425

@@ -36,18 +37,68 @@ This file may also be used to apply patches to upstream instrumentation - usuall
3637
long-term changes to upstream.
3738
*/
3839

39-
export function setAwsDefaultEnvironmentVariables(): void {
40+
export function setAwsDefaultEnvironmentVariables() {
4041
if (!process.env.OTEL_EXPORTER_OTLP_PROTOCOL) {
4142
process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
4243
}
4344
if (!process.env.OTEL_PROPAGATORS) {
4445
process.env.OTEL_PROPAGATORS = 'xray,tracecontext';
4546
}
46-
// Disable the following instrumentations by default
47-
// This auto-instrumentation for the `fs` module generates many low-value spans. `dns` is similar.
48-
// https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1344#issuecomment-1618993178
4947
if (!process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS) {
50-
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'fs,dns';
48+
if (isAgentObservabilityEnabled()) {
49+
// Assume users only need instrumentations that are manually set-up outside of OpenTelemetry
50+
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS =
51+
'amqplib,aws-lambda,aws-sdk,bunyan,cassandra-driver,connect,cucumber,dataloader,dns,express,fastify,fs,generic-pool,graphql,grpc,hapi,http,ioredis,kafkajs,knex,koa,lru-memoizer,memcached,mongodb,mongoose,mysql2,mysql,nestjs-core,net,pg,pino,redis,redis-4,restify,router,socket.io,tedious,undici,winston';
52+
} else {
53+
// Disable the following instrumentations by default
54+
// This auto-instrumentation for the `fs` module generates many low-value spans. `dns` is similar.
55+
// https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1344#issuecomment-1618993178
56+
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'fs,dns';
57+
}
58+
}
59+
60+
if (isAgentObservabilityEnabled()) {
61+
// Set exporter defaults
62+
if (!process.env.OTEL_TRACES_EXPORTER) {
63+
process.env.OTEL_TRACES_EXPORTER = 'otlp';
64+
}
65+
if (!process.env.OTEL_LOGS_EXPORTER) {
66+
process.env.OTEL_LOGS_EXPORTER = 'otlp';
67+
}
68+
if (!process.env.OTEL_METRICS_EXPORTER) {
69+
process.env.OTEL_METRICS_EXPORTER = 'awsemf';
70+
}
71+
72+
// Set GenAI capture content default
73+
if (!process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT) {
74+
process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = 'true';
75+
}
76+
77+
// Set sampler default
78+
if (!process.env.OTEL_TRACES_SAMPLER && !useXraySampler) {
79+
process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_on';
80+
}
81+
82+
// Disable AWS Application Signals by default
83+
if (!process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED) {
84+
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'false';
85+
}
86+
87+
// Set OTLP endpoints with AWS region if not already set
88+
const region = getAwsRegionFromEnvironment();
89+
if (region) {
90+
if (!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) {
91+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = `https://xray.${region}.amazonaws.com/v1/traces`;
92+
}
93+
94+
if (!process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) {
95+
process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = `https://logs.${region}.amazonaws.com/v1/logs`;
96+
}
97+
} else {
98+
diag.error(
99+
'AWS region could not be determined. OTLP endpoints will not be automatically configured. Please set AWS_REGION environment variable or configure OTLP endpoints manually.'
100+
);
101+
}
51102
}
52103
}
53104
setAwsDefaultEnvironmentVariables();

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { diag } from '@opentelemetry/api';
5+
46
const AGENT_OBSERVABILITY_ENABLED = 'AGENT_OBSERVABILITY_ENABLED';
57

68
// Bypass `readonly` restriction of a Type.
@@ -33,3 +35,23 @@ export const isAgentObservabilityEnabled = () => {
3335

3436
return agentObservabilityEnabled.toLowerCase() === 'true';
3537
};
38+
39+
/**
40+
* Get AWS region from environment or boto3 session.
41+
* Returns the AWS region in the following priority order:
42+
* 1. AWS_REGION environment variable
43+
* 2. AWS_DEFAULT_REGION environment variable
44+
* 3. undefined if no region can be determined
45+
*/
46+
export const getAwsRegionFromEnvironment = (): string | undefined => {
47+
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
48+
if (region) {
49+
return region;
50+
}
51+
52+
diag.warn(
53+
'AWS region not found in environment variables (AWS_REGION, AWS_DEFAULT_REGION). Please set AWS_REGION environment variable explicitly.'
54+
);
55+
56+
return undefined;
57+
};

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

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,30 @@ describe('Register', function () {
2323
NodeSDK.prototype.start = originalPrototypeStart;
2424
});
2525

26-
it('Tests AWS Default Environment Variables', () => {
27-
this.beforeEach(() => {
26+
describe('Tests AWS Default Environment Variables', () => {
27+
beforeEach(() => {
2828
delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL;
2929
delete process.env.OTEL_PROPAGATORS;
3030
delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS;
31+
32+
delete process.env.AWS_REGION;
33+
delete process.env.AGENT_OBSERVABILITY_ENABLED;
34+
delete process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT;
35+
delete process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT;
36+
delete process.env.OTEL_TRACES_EXPORTER;
37+
delete process.env.OTEL_LOGS_EXPORTER;
38+
delete process.env.OTEL_METRICS_EXPORTER;
39+
40+
delete process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT;
41+
delete process.env.OTEL_TRACES_SAMPLER;
42+
delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED;
3143
});
3244

3345
it('sets AWS Default Environment Variables', () => {
3446
setAwsDefaultEnvironmentVariables();
3547
expect(process.env.OTEL_EXPORTER_OTLP_PROTOCOL).toEqual('http/protobuf');
3648
expect(process.env.OTEL_PROPAGATORS).toEqual('xray,tracecontext');
37-
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('fs');
49+
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('fs,dns');
3850
});
3951

4052
it('Does not set AWS Default Environment Variables', () => {
@@ -46,6 +58,71 @@ describe('Register', function () {
4658
expect(process.env.OTEL_PROPAGATORS).toEqual('customPropagators');
4759
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('customDisabledInstrumentations');
4860
});
61+
62+
it('Configures with AgentObservabilityEnabled with unset region', () => {
63+
process.env.AGENT_OBSERVABILITY_ENABLED = 'true';
64+
65+
setAwsDefaultEnvironmentVariables();
66+
67+
expect(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).toBeUndefined();
68+
expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBeUndefined();
69+
});
70+
71+
it('Configures with AgentObservabilityEnabled with set region', () => {
72+
process.env.AWS_REGION = 'us-west-2';
73+
process.env.AGENT_OBSERVABILITY_ENABLED = 'true';
74+
75+
setAwsDefaultEnvironmentVariables();
76+
77+
expect(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).toEqual('https://xray.us-west-2.amazonaws.com/v1/traces');
78+
expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toEqual('https://logs.us-west-2.amazonaws.com/v1/logs');
79+
});
80+
81+
it('Configures defaults when AgentObservabilityEnabled is true', () => {
82+
process.env.AWS_REGION = 'us-east-1';
83+
process.env.AGENT_OBSERVABILITY_ENABLED = 'true';
84+
85+
setAwsDefaultEnvironmentVariables();
86+
87+
expect(process.env.OTEL_TRACES_EXPORTER).toEqual('otlp');
88+
expect(process.env.OTEL_LOGS_EXPORTER).toEqual('otlp');
89+
expect(process.env.OTEL_METRICS_EXPORTER).toEqual('awsemf');
90+
expect(process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT).toEqual('true');
91+
expect(process.env.OTEL_TRACES_SAMPLER).toEqual('parentbased_always_on');
92+
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual(
93+
'amqplib,aws-lambda,aws-sdk,bunyan,cassandra-driver,connect,cucumber,dataloader,dns,express,fastify,fs,generic-pool,graphql,grpc,hapi,http,ioredis,kafkajs,knex,koa,lru-memoizer,memcached,mongodb,mongoose,mysql2,mysql,nestjs-core,net,pg,pino,redis,redis-4,restify,router,socket.io,tedious,undici,winston'
94+
);
95+
expect(process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED).toEqual('false');
96+
expect(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).toEqual('https://xray.us-east-1.amazonaws.com/v1/traces');
97+
expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toEqual('https://logs.us-east-1.amazonaws.com/v1/logs');
98+
});
99+
100+
it('Respects user configuration when AgentObservabilityEnabled is false', () => {
101+
process.env.AWS_REGION = 'us-east-1';
102+
delete process.env.AGENT_OBSERVABILITY_ENABLED;
103+
process.env.OTEL_TRACES_SAMPLER = 'traceidratio';
104+
105+
setAwsDefaultEnvironmentVariables();
106+
expect(process.env.OTEL_TRACES_SAMPLER).toEqual('traceidratio');
107+
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('fs,dns');
108+
expect(process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED).toBeUndefined();
109+
});
110+
111+
it('Respects user configuration when AgentObservabilityEnabled is true', () => {
112+
// Enable agent observability
113+
process.env.AGENT_OBSERVABILITY_ENABLED = 'true';
114+
115+
// Set custom values for some environment variables
116+
process.env.OTEL_TRACES_SAMPLER = 'traceidratio';
117+
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'a,b,c,d';
118+
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'true';
119+
120+
setAwsDefaultEnvironmentVariables();
121+
122+
expect(process.env.OTEL_TRACES_SAMPLER).toEqual('traceidratio');
123+
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('a,b,c,d');
124+
expect(process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED).toEqual('true');
125+
});
49126
});
50127

51128
it('can load auto instrumentation from command line', () => {
@@ -89,7 +166,7 @@ describe('Register', function () {
89166
);
90167

91168
// eslint-disable-next-line @typescript-eslint/typedef
92-
const packageJson = require('./../../package.json');
169+
const packageJson = require('./../package.json');
93170
const DISTRO_VERSION: string = packageJson.version;
94171
assert.ok(
95172
proc.stdout.includes(`'telemetry.auto.version': '${DISTRO_VERSION}-aws'`),

aws-distro-opentelemetry-node-autoinstrumentation/test/utils.test.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import expect from 'expect';
5-
import { isAgentObservabilityEnabled } from '../src/utils';
5+
import { getAwsRegionFromEnvironment, isAgentObservabilityEnabled } from '../src/utils';
66

77
describe('Utils', function () {
88
beforeEach(() => {
99
delete process.env.AGENT_OBSERVABILITY_ENABLED;
10-
delete process.env.AWS_REGION;
1110
delete process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT;
1211
delete process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT;
12+
delete process.env.AWS_REGION;
13+
delete process.env.AWS_DEFAULT_REGION;
1314
});
1415

1516
it('Test isAgentObservabilityEnabled to be True', () => {
@@ -39,4 +40,16 @@ describe('Utils', function () {
3940
delete process.env.AGENT_OBSERVABILITY_ENABLED;
4041
expect(isAgentObservabilityEnabled()).toBeFalsy();
4142
});
43+
44+
it('Test getAwsRegion from AWS_REGION env var', () => {
45+
process.env.AWS_REGION = 'us-west-2';
46+
process.env.AWS_DEFAULT_REGION = 'eu-west-1';
47+
expect(getAwsRegionFromEnvironment()).toEqual('us-west-2');
48+
});
49+
50+
it('Test getAwsRegion from AWS_REGION env var', () => {
51+
delete process.env.AWS_REGION;
52+
process.env.AWS_DEFAULT_REGION = 'eu-west-1';
53+
expect(getAwsRegionFromEnvironment()).toEqual('eu-west-1');
54+
});
4255
});

0 commit comments

Comments
 (0)