@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.
143 lines • 7.52 kB
JavaScript
"use strict";
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAIAgentsInstrumentation = exports.INSTRUMENTATION_SHORT_NAME = exports.INSTRUMENTATION_NAME = void 0;
/* eslint-disable @typescript-eslint/no-explicit-any */
const api_1 = require("@opentelemetry/api");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const version_1 = require("../../version");
const tracing_processor_1 = require("./tracing-processor");
const utils_1 = require("../../utils");
exports.INSTRUMENTATION_NAME = '@aws/aws-distro-opentelemetry-instrumentation-openai-agents';
exports.INSTRUMENTATION_SHORT_NAME = 'aws_openai_agents';
const SUPPORTED_VERSIONS = ['>=0.1.0'];
class OpenAIAgentsInstrumentation extends instrumentation_1.InstrumentationBase {
constructor(config = {}) {
super(exports.INSTRUMENTATION_NAME, version_1.LIB_VERSION, config);
}
setConfig(config = {}) {
super.setConfig(Object.assign(Object.assign({}, config), { captureMessageContent: !!config.captureMessageContent }));
}
enable() {
if ((0, utils_1.isInstrumentationDisabled)(exports.INSTRUMENTATION_SHORT_NAME)) {
this._diag.debug(`${exports.INSTRUMENTATION_NAME} is disabled`);
return;
}
if (!(0, utils_1.isAgenticInstrumentationOptIn)()) {
const conflict = (0, utils_1.detectConflictingInstrumentation)(exports.INSTRUMENTATION_SHORT_NAME);
if (conflict) {
this._diag.info(`Skipping ${exports.INSTRUMENTATION_NAME}: third-party '${conflict}' detected. ` +
'Set AWS_AGENTIC_INSTRUMENTATION_OPT_IN=true to override.');
return;
}
}
super.enable();
}
_updateMetricInstruments() { }
init() {
const patchCore = (moduleExports) => this._wrapSdkTraceProvider(moduleExports);
const unpatchCore = (_moduleExports) => this._unpatch();
const patchCreateSpans = (moduleExports) => this._wrapCreateSpansWithOtelContext(moduleExports);
const unpatchCreateSpans = (moduleExports) => this._unwrapCreateSpansWithOtelContext(moduleExports);
return [
new instrumentation_1.InstrumentationNodeModuleDefinition('@openai/agents-core', SUPPORTED_VERSIONS, patchCore, unpatchCore, [
new instrumentation_1.InstrumentationNodeModuleFile('@openai/agents-core/dist/tracing/createSpans.mjs', SUPPORTED_VERSIONS, patchCreateSpans, unpatchCreateSpans),
new instrumentation_1.InstrumentationNodeModuleFile('@openai/agents-core/dist/tracing/createSpans.js', SUPPORTED_VERSIONS, patchCreateSpans, unpatchCreateSpans),
]),
];
}
_wrapSdkTraceProvider(moduleExports) {
// wraps SDK's (OpenAI's not OTel) global TraceProvider to register our OTel processor
// and ensure it survives when the SDK replaces processors at import time.
if (this._patchedProvider)
return moduleExports;
const getGlobalTraceProvider = moduleExports.getGlobalTraceProvider;
if (typeof getGlobalTraceProvider !== 'function') {
this._diag.warn('Could not find getGlobalTraceProvider on @openai/agents-core');
return moduleExports;
}
const provider = getGlobalTraceProvider();
const captureContent = !!this.getConfig().captureMessageContent;
this._processor = new tracing_processor_1.OpenTelemetryTracingProcessor(this.tracer, captureContent);
if (typeof provider.addProcessor === 'function') {
provider.addProcessor(this._processor);
}
const processor = this._processor;
// setProcessors replaces all registered processors and shuts down the old ones.
// setProcessors is called at import time to register its own exporter
// which would remove our processor. We patch it to always keep ours in the list.
// see: https://github.com/openai/openai-agents-js/blob/v0.8.5/packages/agents-core/src/tracing/processor.ts#L271-L277
// see: https://github.com/openai/openai-agents-js/blob/v0.8.5/packages/agents/src/index.ts#L8
this._wrap(provider, 'setProcessors', (original) => {
return function (_processors) {
original.call(this, [processor]);
processor.enable();
};
});
// The built-in onSpanStart is no-op so we never get notified when spans start.
// We patch createSpan to call our processor.onSpanStart so we can create OTel spans at the right time.
// see: https://github.com/openai/openai-agents-js/blob/v0.8.5/packages/agents-core/src/tracing/processor.ts#L209-L211
this._wrap(provider, 'createSpan', (original) => {
return function (spanOptions, parent) {
const span = original.call(this, spanOptions, parent);
if (!processor.disabled && span.spanId !== 'no-op') {
void processor.onSpanStart(span);
}
return span;
};
});
this._patchedProvider = provider;
this._diag.debug('Patched global TraceProvider');
return moduleExports;
}
// The withSpan functions run callbacks inside the SDK's own context
// which is separate from OTel context. We wrap them with context.with to make the OTel span
// active during the callback so downstream instrumentations see the correct parent.
// see: https://github.com/openai/openai-agents-js/blob/v0.8.5/packages/agents-core/src/tracing/createSpans.ts#L27-L54
_wrapCreateSpansWithOtelContext(moduleExports) {
const instrumentation = this;
for (const key of Object.keys(moduleExports)) {
if (typeof moduleExports[key] !== 'function')
continue;
if (!key.match(/^with\w+Span$/))
continue;
this._wrap(moduleExports, key, (original) => {
return function (fn, ...rest) {
return original.call(this, (sdkSpan) => {
const processor = instrumentation._processor;
if (!processor || processor.disabled)
return fn(sdkSpan);
const otelCtx = processor.getOtelContext(sdkSpan.spanId);
if (!otelCtx)
return fn(sdkSpan);
return api_1.context.with(otelCtx, () => fn(sdkSpan));
}, ...rest);
};
});
}
return moduleExports;
}
_unwrapCreateSpansWithOtelContext(moduleExports) {
for (const key of Object.keys(moduleExports)) {
if (typeof moduleExports[key] !== 'function')
continue;
if (!key.match(/^with\w+Span$/))
continue;
this._unwrap(moduleExports, key);
}
}
_unpatch() {
if (this._patchedProvider) {
this._unwrap(this._patchedProvider, 'createSpan');
this._unwrap(this._patchedProvider, 'setProcessors');
}
if (this._processor) {
this._processor.disable();
this._processor = undefined;
}
this._patchedProvider = undefined;
}
}
exports.OpenAIAgentsInstrumentation = OpenAIAgentsInstrumentation;
//# sourceMappingURL=instrumentation.js.map