UNPKG

@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
"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