enhanced-adot-node-autoinstrumentation
Version:
This package provides Amazon Web Services distribution of the OpenTelemetry Node Instrumentation, which allows for auto-instrumentation of NodeJS applications.
272 lines (269 loc) • 13.2 kB
TypeScript
import { LoggerProvider } from '@opentelemetry/sdk-logs';
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
/**
* Utility class for handling Large Language Objects (LLO) in OpenTelemetry spans.
*
* LLOHandler performs three primary functions:
* 1. Identifies Large Language Objects (LLO) content in spans
* 2. Extracts and transforms these attributes into OpenTelemetry Gen AI Events
* 3. Filters LLO from spans to maintain privacy and reduce span size
*
* Supported frameworks and their attribute patterns:
* - Standard Gen AI:
* - gen_ai.prompt.{n}.content: Structured prompt content
* - gen_ai.prompt.{n}.role: Role for prompt content (system, user, assistant, etc.)
* - gen_ai.completion.{n}.content: Structured completion content
* - gen_ai.completion.{n}.role: Role for completion content (usually assistant)
*
* - Traceloop:
* - traceloop.entity.input: Input text for LLM operations
* - traceloop.entity.output: Output text from LLM operations
* - traceloop.entity.name: Name of the entity processing the LLO
* - crewai.crew.tasks_output: Tasks output data from CrewAI (uses gen_ai.system if available)
* - crewai.crew.result: Final result from CrewAI crew (uses gen_ai.system if available)
*
* - OpenLit:
* - gen_ai.prompt: Direct prompt text (treated as user message)
* - gen_ai.completion: Direct completion text (treated as assistant message)
* - gen_ai.content.revised_prompt: Revised prompt text (treated as system message)
* - gen_ai.agent.actual_output: Output from CrewAI agent (treated as assistant message)
*
* - OpenInference:
* - input.value: Direct input prompt
* - output.value: Direct output response
* - llm.input_messages.{n}.message.content: Individual structured input messages
* - llm.input_messages.{n}.message.role: Role for input messages
* - llm.output_messages.{n}.message.content: Individual structured output messages
* - llm.output_messages.{n}.message.role: Role for output messages
* - llm.model_name: Model name used for the LLM operation
*/
export declare class LLOHandler {
private loggerProvider;
private eventLoggerProvider;
private eventLogger;
/**
* Initialize an LLOHandler with the specified logger provider.
*
* This constructor sets up the event logger provider, configures the event logger,
* and initializes the patterns used to identify LLO attributes.
*
* @param loggerProvider The OpenTelemetry LoggerProvider used for emitting events.
* Global LoggerProvider instance injected from our AwsOpenTelemetryConfigurator
*/
constructor(loggerProvider: LoggerProvider);
/**
* Processes a sequence of spans to extract and filter LLO attributes.
*
* For each span, this method:
* 1. Extracts LLO attributes and emits them as Gen AI Events
* 2. Filters out LLO attributes from the span to maintain privacy
* 3. Processes any LLO attributes in span events
* 4. Preserves non-LLO attributes in the span
*
* Handles LLO attributes from multiple frameworks:
* - Standard Gen AI (structured prompt/completion pattern)
* - Traceloop (entity input/output pattern)
* - OpenLit (direct prompt/completion pattern)
* - OpenInference (input/output value and structured messages pattern)
*
* @param spans An array of OpenTelemetry ReadableSpan objects to process
* @returns {ReadableSpan[]} Modified spans with LLO attributes removed
*/
processSpans(spans: ReadableSpan[]): ReadableSpan[];
/**
* Process events within a span to extract and filter LLO attributes.
*
* For each event in the span, this method:
* 1. Emits LLO attributes found in event attributes as Gen AI Events
* 2. Filters out LLO attributes from event attributes
* 3. Creates updated events with filtered attributes
* 4. Replaces the original span events with updated events
*
* This ensures that LLO attributes are properly handled even when they appear
* in span events rather than directly in the span's attributes.
*
* @param span The ReadableSpan to process events for
*/
processSpanEvents(span: ReadableSpan): void;
/**
* Extract Gen AI Events from LLO attributes and emit them via the event logger.
*
* This method:
* 1. Collects LLO attributes from multiple frameworks using specialized extractors
* 2. Converts each LLO attribute into appropriate Gen AI Events
* 3. Emits all collected events through the event logger
*
* Supported frameworks:
* - Standard Gen AI: Structured prompt/completion with roles
* - Traceloop: Entity input/output and CrewAI outputs
* - OpenLit: Direct prompt/completion/revised prompt and agent outputs
* - OpenInference: Direct values and structured messages
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span timestamps
*/
private emitLloAttributes;
/**
* Create a new attributes dictionary with LLO attributes removed.
* This method creates a new dictionary containing only non-LLO attributes,
* preserving the original values while filtering out sensitive LLO content.
* This helps maintain privacy and reduces the size of spans.
*
* @param attributes Span or event attributes
* @returns {Attributes} New Attributes with LLO attributes removed
*/
private filterAttributes;
/**
* Determine if an attribute key contains LLO content based on pattern matching.
*
* Checks attribute keys against two types of patterns:
* 1. Exact match patterns (complete string equality):
* - Traceloop: "traceloop.entity.input", "traceloop.entity.output"
* - OpenLit: "gen_ai.prompt", "gen_ai.completion", "gen_ai.content.revised_prompt"
* - OpenInference: "input.value", "output.value"
*
* 2. Regex match patterns (regular expression matching):
* - Standard Gen AI: "gen_ai.prompt.{n}.content", "gen_ai.completion.{n}.content"
* - OpenInference: "llm.input_messages.{n}.message.content", "llm.output_messages.{n}.message.content"
*
* @param key The attribute key to check
* @returns {boolean} true if the key matches any LLO pattern, false otherwise
*/
private isLloAttribute;
/**
* Extract Gen AI Events from structured prompt attributes.
*
* Processes attributes matching the pattern `gen_ai.prompt.{n}.content` and their
* associated `gen_ai.prompt.{n}.role` attributes to create appropriate events.
*
* Event types are determined by the role:
* 1. `system` → `gen_ai.system.message` Event
* 2. `user` → `gen_ai.user.message` Event
* 3. `assistant` → `gen_ai.assistant.message` Event
* 4. `function` → `gen_ai.{gen_ai.system}.message` custom Event
* 5. `unknown` → `gen_ai.{gen_ai.system}.message` custom Event
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span.startTime
* @returns {Event[]} Events created from prompt attributes
*/
private extractGenAiPromptEvents;
/**
* Extract Gen AI Events from structured completion attributes.
*
* Processes attributes matching the pattern `gen_ai.completion.{n}.content` and their
* associated `gen_ai.completion.{n}.role` attributes to create appropriate events.
*
* Event types are determined by the role:
* 1. `assistant` → `gen_ai.assistant.message` Event (most common)
* 2. Other roles → `gen_ai.{gen_ai.system}.message` custom Event
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span.endTime
* @returns {Event[]} Events created from completion attributes
*/
private extractGenAiCompletionEvents;
/**
* Extract Gen AI Events from Traceloop attributes.
*
* Processes Traceloop-specific attributes:
* - `traceloop.entity.input`: Input data (uses span.startTime)
* - `traceloop.entity.output`: Output data (uses span.endTime)
* - `traceloop.entity.name`: Used as the gen_ai.system value when gen_ai.system isn't available
* - `crewai.crew.tasksOutput`: Tasks output data from CrewAI (uses span.endTime)
* - `crewai.crew.result`: Final result from CrewAI crew (uses span.endTime)
*
* Creates generic `gen_ai.{entity_name}.message` events for both input and output,
* and assistant message events for CrewAI outputs.
*
* For CrewAI-specific attributes (crewai.crew.tasks_output and crewai.crew.result),
* uses span's gen_ai.system attribute if available, otherwise falls back to traceloop.entity.name.
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span timestamps
* @returns {Event[]} Events created from Traceloop attributes
*/
private extractTraceloopEvents;
/**
* Extract Gen AI Events from OpenLit direct attributes.
* OpenLit uses direct key-value pairs for LLO attributes:
* - `gen_ai.prompt`: Direct prompt text (treated as user message)
* - `gen_ai.completion`: Direct completion text (treated as assistant message)
* - `gen_ai.content.revised_prompt`: Revised prompt text (treated as system message)
* - `gen_ai.agent.actual_output`: Output from CrewAI agent (treated as assistant message)
* The event timestamps are set based on attribute type:
* - Prompt and revised prompt: span.startTime
* - Completion and agent output: span.endTime
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span timestamps
* @returns {Event[]} Events created from OpenLit attributes
*/
private extractOpenlitSpanEventAttributes;
/**
* Extract Gen AI Events from OpenInference attributes.
*
* OpenInference uses two patterns for LLO attributes:
* 1. Direct values:
* - `input.value`: Direct input prompt (treated as user message)
* - `output.value`: Direct output response (treated as assistant message)
*
* 2. Structured messages:
* - `llm.input_messages.{n}.message.content`: Individual input messages
* - `llm.input_messages.{n}.message.role`: Role for input message
* - `llm.output_messages.{n}.message.content`: Individual output messages
* - `llm.output_messages.{n}.message.role`: Role for output message
*
* The LLM model name is extracted from the `llm.model_name` attribute
* instead of `gen_ai.system` which other frameworks use.
*
* Event timestamps are set based on message type:
* - Input messages: span.startTime
* - Output messages: span.endTime
*
* @param span The source ReadableSpan containing the attributes
* @param attributes Attributes to process
* @param eventTimestamp Optional timestamp to override span timestamps
* @returns {Event[]} Events created from OpenInference attributes
*/
private extractOpeninferenceAttributes;
/**
* Map a message role to the appropriate event name.
*
* @param role The role of the message (system, user, assistant, etc.)
* @param genAiSystem The gen_ai system identifier
* @returns {string} The appropriate event name for the given role
*/
private getEventNameForRole;
/**
* Determine the appropriate timestamp to use for an event.
*
* @param span The source span
* @param eventTimestamp Optional override timestamp
* @param isInput Whether this is an input (true) or output (false) message
* @returns {number} The timestamp to use for the event
*/
private getTimestamp;
/**
* Create and return a Gen AI Event with the specified parameters.
*
* This helper method constructs a fully configured OpenTelemetry Event object
* that includes all necessary fields for proper event propagation and context.
*
* @param name Event type name (e.g., gen_ai.system.message, gen_ai.user.message)
* @param spanCtx Span context to extract trace/span IDs from
* @param timestamp Timestamp for the event (nanoseconds)
* @param attributes Additional attributes to include with the event
* @param data Event body containing content and role information
* @param span A ReadableSpan associated with the Span context
* @returns {Event}: A fully configured OpenTelemetry Gen AI Event object with proper trace context propagation
*/
private getGenAiEvent;
}
export declare function createContextKey(description: string): symbol;
//# sourceMappingURL=llo-handler.d.ts.map