Telemetry
The Telemetry module provides OpenTelemetry integration for operations
performed against a large language model provider by defining telemetry
attributes and utilities that follow the OpenTelemetry GenAI semantic
conventions.
Example
import { Telemetry } from "@effect/ai"import { Effect } from "effect"
// Add telemetry attributes to a spanconst addTelemetry = Effect.gen(function* () { const span = yield* Effect.currentSpan
Telemetry.addGenAIAnnotations(span, { system: "openai", operation: { name: "chat" }, request: { model: "gpt-4", temperature: 0.7, maxTokens: 1000 }, usage: { inputTokens: 100, outputTokens: 50 } })})Context
CurrentSpanTransformer
Context tag for providing a span transformer to large langauge model operations.
The CurrentSpanTransformer allows you to inject custom span transformation logic into AI operations, enabling application-specific telemetry and observability patterns.
Signature
declare class CurrentSpanTransformer extends any { constructor();}Example
import { Telemetry } from "@effect/ai"import * as Effect from "effect/Effect"
declare const myAIOperation: Effect.Effect<void>
// Create a custom span transformerconst loggingTransformer: Telemetry.SpanTransformer = (options) => { console.log(`AI request completed: ${options.response.length} part(s)`) options.response.forEach((part, index) => { console.log(`Part ${index}: ${part.type}`) })}
// Provide the transformer to your AI operationsconst program = myAIOperation.pipe( Effect.provideService( Telemetry.CurrentSpanTransformer, Telemetry.CurrentSpanTransformer.of(loggingTransformer) ))Models
AllAttributes type
All telemetry attributes which are part of the GenAI specification.
Signature
type AllAttributes = BaseAttributes & OperationAttributes & TokenAttributes & UsageAttributes & RequestAttributes & ResponseAttributesBaseAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.
Signature
interface BaseAttributes { readonly system?: string & {} | WellKnownSystem | null;}GenAITelemetryAttributeOptions type
Configuration options for GenAI telemetry attributes.
Combines base attributes with optional grouped attributes for comprehensive telemetry coverage of AI operations.
Signature
type GenAITelemetryAttributeOptions = BaseAttributes & { readonly operation?: OperationAttributes; readonly request?: RequestAttributes; readonly response?: ResponseAttributes; readonly token?: TokenAttributes; readonly usage?: UsageAttributes;}Example
import { Telemetry } from "@effect/ai"
const telemetryOptions: Telemetry.GenAITelemetryAttributeOptions = { system: "openai", operation: { name: "chat" }, request: { model: "gpt-4-turbo", temperature: 0.7, maxTokens: 2000 }, response: { id: "chatcmpl-123", model: "gpt-4-turbo-2024-04-09", finishReasons: ["stop"] }, usage: { inputTokens: 50, outputTokens: 25 }}GenAITelemetryAttributes type
The attributes used to describe telemetry in the context of Generative Artificial Intelligence (GenAI) Models requests and responses.
https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
Signature
type GenAITelemetryAttributes = Simplify<AttributesWithPrefix<BaseAttributes, "gen_ai"> & AttributesWithPrefix<OperationAttributes, "gen_ai.operation"> & AttributesWithPrefix<TokenAttributes, "gen_ai.token"> & AttributesWithPrefix<UsageAttributes, "gen_ai.usage"> & AttributesWithPrefix<RequestAttributes, "gen_ai.request"> & AttributesWithPrefix<ResponseAttributes, "gen_ai.response">>OperationAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.operation.
Signature
interface OperationAttributes { readonly name?: string & {} | WellKnownOperationName | null;}RequestAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.request.
Signature
interface RequestAttributes { readonly encodingFormats?: readonly Array<string> | null; readonly frequencyPenalty?: number | null; readonly maxTokens?: number | null; readonly model?: string | null; readonly presencePenalty?: number | null; readonly seed?: number | null; readonly stopSequences?: readonly Array<string> | null; readonly temperature?: number | null; readonly topK?: number | null; readonly topP?: number | null;}ResponseAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.response.
Signature
interface ResponseAttributes { readonly finishReasons?: readonly Array<string> | null; readonly id?: string | null; readonly model?: string | null;}SpanTransformer interface
A function that can transform OpenTelemetry spans based on AI operation data.
Span transformers receive the complete request/response context from AI operations and can add custom telemetry attributes, metrics, or other observability data.
Signature
interface SpanTransformer { (options: ProviderOptions & { readonly response: readonly Array<AllParts<any>>; }): void;}Example
import { Telemetry } from "@effect/ai"
const customTransformer: Telemetry.SpanTransformer = (options) => { // Add custom attributes based on the response const textParts = options.response.filter(part => part.type === "text") const totalTextLength = textParts.reduce((sum, part) => sum + (part.type === "text" ? part.text.length : 0), 0 )
// Add custom metrics console.log(`Generated ${totalTextLength} characters of text`)}TokenAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.token.
Signature
interface TokenAttributes { readonly type?: string | null;}UsageAttributes interface
Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.usage.
Signature
interface UsageAttributes { readonly inputTokens?: number | null; readonly outputTokens?: number | null;}WellKnownOperationName type
The gen_ai.operation.name attribute has the following list of well-known
values.
If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
Signature
type WellKnownOperationName = "chat" | "embeddings" | "text_completion"WellKnownSystem type
The gen_ai.system attribute has the following list of well-known values.
If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
Signature
type WellKnownSystem = "anthropic" | "aws.bedrock" | "az.ai.inference" | "az.ai.openai" | "cohere" | "deepseek" | "gemini" | "groq" | "ibm.watsonx.ai" | "mistral_ai" | "openai" | "perplexity" | "vertex_ai" | "xai"Utilities
addGenAIAnnotations
Applies GenAI telemetry attributes to an OpenTelemetry span.
This function adds standardized GenAI attributes to a span following OpenTelemetry semantic conventions. It supports both curried and direct application patterns.
Note: This function mutates the provided span in-place.
Signature
declare const addGenAIAnnotations: { (options: GenAITelemetryAttributeOptions): (span: Span) => void; (span: Span, options: GenAITelemetryAttributeOptions): void;}Example
import { Telemetry } from "@effect/ai"import { Effect } from "effect"
const directUsage = Effect.gen(function* () { const span = yield* Effect.currentSpan
Telemetry.addGenAIAnnotations(span, { system: "openai", request: { model: "gpt-4", temperature: 0.7 }, usage: { inputTokens: 100, outputTokens: 50 } })})addSpanAttributes
Creates a function to add attributes to a span with a given prefix and key transformation.
This utility function is used internally to create specialized functions for adding different types of telemetry attributes to OpenTelemetry spans.
Signature
declare function addSpanAttributes(keyPrefix: string, transformKey: (key: string) => string): <Attributes extends Record<string, any>>(span: Span, attributes: Attributes) => voidExample
import { Telemetry } from "@effect/ai"import { String, Tracer } from "effect"
const addCustomAttributes = Telemetry.addSpanAttributes( "custom.ai", String.camelToSnake)
// Usage with a spandeclare const span: Tracer.SpanaddCustomAttributes(span, { modelName: "gpt-4", maxTokens: 1000})// Results in attributes: "custom.ai.model_name" and "custom.ai.max_tokens"Utility Types
AttributesWithPrefix type
Utility type for prefixing attribute names with a namespace.
Transforms attribute keys by adding a prefix and formatting them according to OpenTelemetry conventions (camelCase to snake_case).
Signature
type AttributesWithPrefix<Attributes extends Record<string, any>, Prefix extends string> = { [Name in keyof Attributes]: Attributes[Name] }Example
import { Telemetry } from "@effect/ai"
type RequestAttrs = { modelName: string maxTokens: number}
type PrefixedAttrs = Telemetry.AttributesWithPrefix<RequestAttrs, "gen_ai.request">// Results in: {// "gen_ai.request.model_name": string// "gen_ai.request.max_tokens": number// }FormatAttributeName type
Utility type for converting camelCase names to snake_case format.
This type recursively transforms string literal types from camelCase to snake_case, which is the standard format for OpenTelemetry attributes.
Signature
type FormatAttributeName<T extends string | number | symbol> = T extends string ? T extends `${infer First}${infer Rest}` ? `${First extends Uppercase<First> ? "_" : ""}${Lowercase<First>}${FormatAttributeName<Rest>}` : T : neverExample
import { Telemetry } from "@effect/ai"
type Formatted1 = Telemetry.FormatAttributeName<"modelName"> // "model_name"type Formatted2 = Telemetry.FormatAttributeName<"maxTokens"> // "max_tokens"type Formatted3 = Telemetry.FormatAttributeName<"temperature"> // "temperature"