Telemetry.ts
Telemetry.ts overview
Section titled “Telemetry.ts overview”Adds OpenTelemetry GenAI attributes to Effect AI spans.
This module models the gen_ai.* attributes used by language model and
embedding providers. It includes attribute types, helpers for writing
non-null attributes onto existing spans, and a CurrentSpanTransformer
service for adding custom span annotations from provider options and response
parts.
Since v4.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”- annotations
- models
- AllAttributes (type alias)
- BaseAttributes (interface)
- GenAITelemetryAttributes (type alias)
- OperationAttributes (interface)
- RequestAttributes (interface)
- ResponseAttributes (interface)
- SpanTransformer (interface)
- TokenAttributes (interface)
- UsageAttributes (interface)
- WellKnownOperationName (type alias)
- WellKnownSystem (type alias)
- options
- services
- utility types
annotations
Section titled “annotations”addGenAIAnnotations
Section titled “addGenAIAnnotations”Applies GenAI telemetry attributes to an OpenTelemetry span.
When to use
Use when you need to write GenAI request, response, token, or usage attributes onto an existing OpenTelemetry span.
Details
This function adds standardized GenAI attributes to a span following OpenTelemetry semantic conventions.
Gotchas
This function mutates the provided span in-place.
Example (Adding GenAI telemetry annotations)
import { Effect } from "effect"import { Telemetry } from "effect/unstable/ai"
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 } })})Signature
declare const addGenAIAnnotations: { (options: GenAITelemetryAttributeOptions): (span: Span) => void (span: Span, options: GenAITelemetryAttributeOptions): void}Since v4.0.0
addSpanAttributes
Section titled “addSpanAttributes”Creates a reusable span-attribute writer for a key prefix and key transformer.
Details
The returned function mutates the supplied span by adding each non-nullish
attribute as ${prefix}.${transformedKey}.
Example (Adding prefixed span attributes)
import { String } from "effect"import type { Tracer } from "effect"import { Telemetry } from "effect/unstable/ai"
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"Signature
declare const addSpanAttributes: ( keyPrefix: string, transformKey: (key: string) => string) => <Attributes extends Record<string, any>>(span: Span, attributes: Attributes) => voidSince v4.0.0
models
Section titled “models”AllAttributes (type alias)
Section titled “AllAttributes (type alias)”All telemetry attributes which are part of the GenAI specification.
Signature
type AllAttributes = BaseAttributes & OperationAttributes & TokenAttributes & UsageAttributes & RequestAttributes & ResponseAttributesSince v4.0.0
BaseAttributes (interface)
Section titled “BaseAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.
Signature
export interface BaseAttributes { /** * The Generative AI product as identified by the client or server * instrumentation. */ readonly system?: (string & {}) | WellKnownSystem | null | undefined}Since v4.0.0
GenAITelemetryAttributes (type alias)
Section titled “GenAITelemetryAttributes (type alias)”The attributes used to describe telemetry in the context of Generative Artificial Intelligence (GenAI) models requests and responses.
Details
These attributes follow the OpenTelemetry generative AI semantic conventions: https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
Signature
type GenAITelemetryAttributes = Struct.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">>Since v4.0.0
OperationAttributes (interface)
Section titled “OperationAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.operation.
Signature
export interface OperationAttributes { readonly name?: (string & {}) | WellKnownOperationName | null | undefined}Since v4.0.0
RequestAttributes (interface)
Section titled “RequestAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.request.
Signature
export interface RequestAttributes { /** * The name of the GenAI model a request is being made to. */ readonly model?: string | null | undefined /** * The temperature setting for the GenAI request. */ readonly temperature?: number | null | undefined /** * The temperature setting for the GenAI request. */ readonly topK?: number | null | undefined /** * The top_k sampling setting for the GenAI request. */ readonly topP?: number | null | undefined /** * The top_p sampling setting for the GenAI request. */ readonly maxTokens?: number | null | undefined /** * The encoding formats requested in an embeddings operation, if specified. */ readonly encodingFormats?: ReadonlyArray<string> | null | undefined /** * List of sequences that the model will use to stop generating further * tokens. */ readonly stopSequences?: ReadonlyArray<string> | null | undefined /** * The frequency penalty setting for the GenAI request. */ readonly frequencyPenalty?: number | null | undefined /** * The presence penalty setting for the GenAI request. */ readonly presencePenalty?: number | null | undefined /** * The seed setting for the GenAI request. Requests with same seed value * are more likely to return same result. */ readonly seed?: number | null | undefined}Since v4.0.0
ResponseAttributes (interface)
Section titled “ResponseAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.response.
Signature
export interface ResponseAttributes { /** * The unique identifier for the completion. */ readonly id?: string | null | undefined /** * The name of the model that generated the response. */ readonly model?: string | null | undefined /** * Array of reasons the model stopped generating tokens, corresponding to * each generation received. */ readonly finishReasons?: ReadonlyArray<string> | null | undefined}Since v4.0.0
SpanTransformer (interface)
Section titled “SpanTransformer (interface)”A function that can transform OpenTelemetry spans based on AI operation data.
Details
Span transformers receive the complete request/response context from AI operations and can add custom telemetry attributes, metrics, or other observability data.
Example (Transforming AI spans)
import type { Telemetry } from "effect/unstable/ai"
const customTransformer: Telemetry.SpanTransformer = ({ response, span }) => { // Add custom attributes based on the response const textParts = response.filter((part) => part.type === "text") const totalTextLength = textParts.reduce((sum, part) => sum + (part.type === "text" ? part.text.length : 0), 0) span.attribute("total_text_length", totalTextLength)}Signature
export interface SpanTransformer { ( options: ProviderOptions & { /** * Array of response parts generated by the AI model. */ readonly response: ReadonlyArray<Response.AllParts<any>> } ): void}Since v4.0.0
TokenAttributes (interface)
Section titled “TokenAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.token.
Signature
export interface TokenAttributes { readonly type?: string | null | undefined}Since v4.0.0
UsageAttributes (interface)
Section titled “UsageAttributes (interface)”Telemetry attributes which are part of the GenAI specification and are
namespaced by gen_ai.usage.
Signature
export interface UsageAttributes { readonly inputTokens?: number | null | undefined readonly outputTokens?: number | null | undefined}Since v4.0.0
WellKnownOperationName (type alias)
Section titled “WellKnownOperationName (type alias)”The gen_ai.operation.name attribute has the following list of well-known
values.
Details
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"Since v4.0.0
WellKnownSystem (type alias)
Section titled “WellKnownSystem (type alias)”The gen_ai.system attribute has the following list of well-known values.
Details
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"Since v4.0.0
options
Section titled “options”GenAITelemetryAttributeOptions (type alias)
Section titled “GenAITelemetryAttributeOptions (type alias)”Configuration options for GenAI telemetry attributes.
Details
Combines base attributes with optional grouped attributes for comprehensive telemetry coverage of AI operations.
Example (Configuring GenAI telemetry attributes)
import type { Telemetry } from "effect/unstable/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 }}Signature
type GenAITelemetryAttributeOptions = BaseAttributes & { /** * Operation-specific attributes (e.g., operation name). */ readonly operation?: OperationAttributes | undefined /** * Request-specific attributes (e.g., model parameters). */ readonly request?: RequestAttributes | undefined /** * Response-specific attributes (e.g., response metadata). */ readonly response?: ResponseAttributes | undefined /** * Token-specific attributes. */ readonly token?: TokenAttributes | undefined /** * Usage statistics attributes (e.g., token counts). */ readonly usage?: UsageAttributes | undefined}Since v4.0.0
services
Section titled “services”CurrentSpanTransformer (class)
Section titled “CurrentSpanTransformer (class)”Service tag for providing a SpanTransformer to large language model
operations.
When to use
Use to retrieve or provide the current SpanTransformer through context for
language model span annotation.
See
SpanTransformerfor the transformer contract provided by this service
Signature
declare class CurrentSpanTransformerSince v4.0.0
utility types
Section titled “utility types”AttributesWithPrefix (type alias)
Section titled “AttributesWithPrefix (type alias)”Utility type for prefixing attribute names with a namespace.
Details
Transforms attribute keys by adding a prefix and formatting them according to OpenTelemetry conventions (camelCase to snake_case).
Example (Prefixing telemetry attributes)
import type { Telemetry } from "effect/unstable/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// }Signature
type AttributesWithPrefix<Attributes, Prefix> = { [Name in keyof Attributes as `${Prefix}.${FormatAttributeName<Name>}`]: Attributes[Name]}Since v4.0.0
FormatAttributeName (type alias)
Section titled “FormatAttributeName (type alias)”Utility type for converting camelCase names to snake_case format.
Details
This type recursively transforms string literal types from camelCase to snake_case, which is the standard format for OpenTelemetry attributes.
Example (Formatting attribute names)
import type { Telemetry } from "effect/unstable/ai"
type Formatted1 = Telemetry.FormatAttributeName<"modelName"> // "model_name"type Formatted2 = Telemetry.FormatAttributeName<"maxTokens"> // "max_tokens"type Formatted3 = Telemetry.FormatAttributeName<"temperature"> // "temperature"Signature
type FormatAttributeName<T> = T extends string ? T extends `${infer First}${infer Rest}` ? `${First extends Uppercase<First> ? "_" : ""}${Lowercase<First>}${FormatAttributeName<Rest>}` : T : neverSince v4.0.0