@aws/aws-distro-opentelemetry-node-autoinstrumentation
Version:
This package provides Amazon Web Services distribution of the OpenTelemetry Node Instrumentation, which allows for auto-instrumentation of NodeJS applications.
158 lines (155 loc) • 9.27 kB
JavaScript
;
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.instrumentations = exports.instrumentationConfigs = exports.setAwsDefaultEnvironmentVariables = void 0;
// 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. Thus we temporarily remove this env var to avoid the unwanted log.
let useXraySampler = false;
if (process.env.OTEL_TRACES_SAMPLER === 'xray') {
delete process.env.OTEL_TRACES_SAMPLER;
useXraySampler = true;
}
const api_1 = require("@opentelemetry/api");
const api_logs_1 = require("@opentelemetry/api-logs");
const auto_instrumentations_node_1 = require("@opentelemetry/auto-instrumentations-node");
const core_1 = require("@opentelemetry/core");
const opentelemetry = require("@opentelemetry/sdk-node");
const aws_opentelemetry_configurator_1 = require("./aws-opentelemetry-configurator");
const instrumentation_1 = require("./instrumentation/instrumentation-langchain/instrumentation");
const instrumentation_2 = require("./instrumentation/instrumentation-openai-agents/instrumentation");
const instrumentation_3 = require("./instrumentation/instrumentation-vercel-ai/instrumentation");
const instrumentation_patch_1 = require("./patches/instrumentation-patch");
const utils_1 = require("./utils");
const logLevelEnv = (0, core_1.getStringFromEnv)('OTEL_LOG_LEVEL');
const logLevel = logLevelEnv ? (0, core_1.diagLogLevelFromString)(logLevelEnv) : undefined;
api_1.diag.setLogger(new api_1.DiagConsoleLogger(), logLevel);
/*
Sets up default environment variables and apply patches
Set default OTEL_EXPORTER_OTLP_PROTOCOL to be `http/protobuf` to remain consistent with other ADOT languages. This must be run before
`configurator.configure()`, which will use this value to create an OTel Metric Exporter that is used for the customized AWS Span Procesors.
The default value of OTEL_EXPORTER_OTLP_PROTOCOL should be `http/protobuf`:
https://github.com/open-telemetry/opentelemetry-js/blob/34003c9b7ef7e7e95e86986550d1c7fb6c1c56c6/packages/opentelemetry-core/src/utils/environment.ts#L233
Also sets default OTEL_PROPAGATORS to ensure good compatibility with X-Ray and Application Signals.
This file may also be used to apply patches to upstream instrumentation - usually these are stopgap measures until we can contribute
long-term changes to upstream.
*/
function setAwsDefaultEnvironmentVariables() {
if (!process.env.OTEL_EXPORTER_OTLP_PROTOCOL) {
process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
}
if (!process.env.OTEL_PROPAGATORS) {
// Propagators are run in the order they are configured.
// xray is set after baggage in case xray propagator depends on the result of the baggage header extraction.
process.env.OTEL_PROPAGATORS = 'baggage,xray,tracecontext';
}
if (!process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS) {
// Disable the following instrumentations by default
// This auto-instrumentation for the `fs` module generates many low-value spans. `dns` is similar.
// https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1344#issuecomment-1618993178
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'fs,dns';
}
if ((0, utils_1.isAgentObservabilityEnabled)()) {
if (!process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS) {
// Assume users only need aws-sdk, aws-lambda, and our custom GenAI instrumentations,
// as well as instrumentations that are manually set-up outside of OpenTelemetry.
process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS = `aws-lambda,aws-sdk,http,undici,${instrumentation_1.INSTRUMENTATION_SHORT_NAME},${instrumentation_2.INSTRUMENTATION_SHORT_NAME},${instrumentation_3.INSTRUMENTATION_SHORT_NAME}`;
}
// Set exporter defaults
if (!process.env.OTEL_TRACES_EXPORTER) {
process.env.OTEL_TRACES_EXPORTER = 'otlp';
}
if (!process.env.OTEL_LOGS_EXPORTER) {
process.env.OTEL_LOGS_EXPORTER = 'otlp';
}
if (!process.env.OTEL_METRICS_EXPORTER) {
process.env.OTEL_METRICS_EXPORTER = 'awsemf';
}
// Set GenAI capture content default
if (!process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT) {
process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = 'true';
}
// Set sampler default
if (!process.env.OTEL_TRACES_SAMPLER && !useXraySampler) {
process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_on';
}
// Disable AWS Application Signals by default
if (!process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED) {
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'false';
}
if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {
const region = (0, utils_1.getAwsRegionFromEnvironment)();
if (region) {
if (!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) {
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = `https://xray.${region}.amazonaws.com/v1/traces`;
}
if (!process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) {
process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = `https://logs.${region}.amazonaws.com/v1/logs`;
}
}
else {
api_1.diag.error('AWS region could not be determined. OTLP endpoints will not be automatically configured. Please set AWS_REGION environment variable or configure OTLP endpoints manually.');
}
}
}
}
exports.setAwsDefaultEnvironmentVariables = setAwsDefaultEnvironmentVariables;
setAwsDefaultEnvironmentVariables();
exports.instrumentationConfigs = {
'@opentelemetry/instrumentation-aws-lambda': {
eventContextExtractor: instrumentation_patch_1.customExtractor,
},
'@opentelemetry/instrumentation-aws-sdk': {
suppressInternalInstrumentation: true,
},
'@opentelemetry/instrumentation-mongoose': {
suppressInternalInstrumentation: true,
},
};
exports.instrumentations = (0, auto_instrumentations_node_1.getNodeAutoInstrumentations)(exports.instrumentationConfigs);
const captureMessageContent = process.env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT !== 'false';
exports.instrumentations.push(new instrumentation_1.LangChainInstrumentation({ captureMessageContent }));
exports.instrumentations.push(new instrumentation_2.OpenAIAgentsInstrumentation({ captureMessageContent }));
exports.instrumentations.push(new instrumentation_3.VercelAIInstrumentation({ captureMessageContent }));
// Apply instrumentation patches
(0, instrumentation_patch_1.applyInstrumentationPatches)(exports.instrumentations);
const configurator = new aws_opentelemetry_configurator_1.AwsOpentelemetryConfigurator(exports.instrumentations, useXraySampler);
const configuration = configurator.configure();
const sdk = new opentelemetry.NodeSDK(configuration);
// The OpenTelemetry Authors code
// We need to copy OpenTelemetry's register.ts file in order to provide the configuration
// created by AwsOpentelemetryConfigurator, which cannot be done by otherwise. In the long term,
// we wish to make contributions to upstream to improve customizability of the Node auto-instrumentation.
try {
sdk.start();
api_1.diag.info('Setting TraceProvider for instrumentations at the end of initialization');
for (const instrumentation of exports.instrumentations) {
instrumentation.setTracerProvider(api_1.trace.getTracerProvider());
instrumentation.setMeterProvider(api_1.metrics.getMeterProvider());
if (instrumentation.setLoggerProvider) {
instrumentation.setLoggerProvider(api_logs_1.logs.getLoggerProvider());
}
}
api_1.diag.debug(`Environment variable OTEL_PROPAGATORS is set to '${process.env.OTEL_PROPAGATORS}'`);
api_1.diag.debug(`Environment variable OTEL_EXPORTER_OTLP_PROTOCOL is set to '${process.env.OTEL_EXPORTER_OTLP_PROTOCOL}'`);
api_1.diag.info('AWS Distro of OpenTelemetry automatic instrumentation started successfully');
}
catch (error) {
api_1.diag.error('Error initializing AWS Distro of OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry', error);
}
process.on('SIGTERM', () => {
sdk
.shutdown()
.then(() => api_1.diag.debug('AWS Distro of OpenTelemetry SDK terminated'))
.catch(error => api_1.diag.error('Error terminating AWS Distro of OpenTelemetry SDK', error));
});
// END The OpenTelemetry Authors code
// Respect original `OTEL_TRACES_SAMPLER` as we previously deleted it temporarily for value `xray`
if (useXraySampler) {
process.env.OTEL_TRACES_SAMPLER = 'xray';
}
//# sourceMappingURL=register.js.map