UNPKG

@azure/monitor-opentelemetry

Version:
94 lines 3.59 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { trace } from "@opentelemetry/api"; import { Logger } from "../shared/logging/index.js"; import { GEN_AI_OPERATION_INVOKE_AGENT, GEN_AI_OPERATION_NAME, MAIN_AGENT_ONEND_MAPPING, MAIN_AGENT_ONSTART_MAPPING, } from "../utils/genaiAttributes.js"; /** * Azure Monitor Span Processor. * @internal */ export class AzureMonitorSpanProcessor { _metricHandler; constructor(metricHandler) { this._metricHandler = metricHandler; } forceFlush() { return Promise.resolve(); } onStart(span, parentContext) { try { this._propagateMainAgentAttributesFromParent(span, parentContext); } catch (error) { Logger.getInstance().warn("Error while propagating main agent attributes onStart", error); } this._metricHandler.markSpanAsProcessed(span); } onEnd(span) { try { this._applyInvokeAgentMainAgentFallback(span); } catch (error) { Logger.getInstance().warn("Error while applying main agent fallback onEnd", error); } try { this._metricHandler.recordSpan(span); } catch (error) { Logger.getInstance().warn("Error while recording span", error); } } _propagateMainAgentAttributesFromParent(span, parentContext) { const parentSpan = trace.getSpan(parentContext); if (!parentSpan) { return; } // The Span returned by trace.getSpan may be a non-recording span or a // foreign implementation that does not expose `attributes`. Only proceed // when the parent looks like a ReadableSpan with readable attributes. const parentAttributes = parentSpan.attributes; if (!parentAttributes) { return; } for (const { target, primary, fallback } of MAIN_AGENT_ONSTART_MAPPING) { const primaryValue = parentAttributes[primary]; if (primaryValue !== undefined) { span.setAttribute(target, primaryValue); continue; } const fallbackValue = parentAttributes[fallback]; if (fallbackValue !== undefined) { span.setAttribute(target, fallbackValue); } } } _applyInvokeAgentMainAgentFallback(span) { const attributes = span.attributes; if (!attributes || attributes[GEN_AI_OPERATION_NAME] !== GEN_AI_OPERATION_INVOKE_AGENT) { return; } // Only check the four target attributes defined by the spec rather than // scanning every key on the span. for (const { target } of MAIN_AGENT_ONEND_MAPPING) { if (attributes[target] !== undefined) { return; } } // The processor runs before BatchSpanProcessor, so mutating the span's // attributes map here is observed by the exporter. Assigning into // `attributes` directly avoids depending on the ReadableSpan also being a // writable Span (and on `setAttribute` being a no-op once the span has // ended). const writableAttributes = attributes; for (const { target, source } of MAIN_AGENT_ONEND_MAPPING) { const value = attributes[source]; if (value !== undefined) { writableAttributes[target] = value; } } } shutdown() { return Promise.resolve(); } } //# sourceMappingURL=spanProcessor.js.map