package ocaml-ai-sdk
- Quick start
- Span hierarchy
- Attribute selectivity
- Upstream parity gaps
- W3C Trace Context
- Types
- Settings
- Attribute Selection
- Optional Attribute Helpers
- Lwt Span Helpers
- Conditional Helpers
- Precompute Helpers
- Step Span Attribute Builders
- Integration Values
- Integration Notification
- Global Integration Registry
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=cb3b82428abcda76c02ec92f8103a4db28edf3f42795794a37135e9a3c40af96
sha512=11be8889ee25bee67b2be00553c42a4692bc73e5ce23985e8bb87f8a07e9d8f556b5a63b219fe5fe30366c8b0d4edae494afa80ccfbfcb112f1fa1e458de55bf
doc/ocaml-ai-sdk.ai_core/Ai_core/Telemetry/index.html
Module Ai_core.TelemetrySource
Telemetry configuration for AI SDK operations.
Mirrors the upstream AI SDK's TelemetrySettings. When enabled is false (the default), all instrumentation is skipped with zero overhead — Trace_core returns dummy spans and never serializes attribute data.
Quick start
(* 1. Install a trace collector in your application entrypoint *)
let () = Trace_core.setup_collector (my_otel_collector ())
(* 2. Pass telemetry settings to generate_text / stream_text *)
let telemetry =
Telemetry.create ~enabled:true ~function_id:"chat-completion"
~metadata:[ "user_id", `String "u-123" ]
()
let%lwt result = Generate_text.generate_text ~model ~messages ~telemetry ()Span hierarchy
ai.generateText (root — full operation) ├── ai.generateText.doGenerate (per-step LLM call) └── ai.toolCall (per tool execution) ai.streamText (root — full streaming operation) ├── ai.streamText.doStream (per-step streaming call) └── ai.toolCall (per tool execution)
Attribute selectivity
Attributes are classified as Input (prompts, tools), Output (responses, tool results), or Always (model info, usage). Input attributes are only recorded when record_inputs is true, Output when record_outputs is true. When enabled is false, no attributes are evaluated at all (zero serialization cost).
Upstream parity gaps
The following upstream attributes are not yet emitted:
ai.response.timestamp: ourGenerate_result.response_infodoes not carry timestamps.ai.response.idon stream step spans.ai.response.modelis emitted when the provider suppliesStream_result.raw_response.ai.usage.inputTokenDetails.*,ai.usage.outputTokenDetails.*: ourUsage.tonly hasinput_tokens,output_tokens,total_tokens. When the provider-level type gains detail fields (Anthropic already returns them in provider metadata), the span attributes can be extended without API changes.onStepStartintegration callback: upstream added this; we only haveon_step_finish.gen_ai.response.finish_reasons: upstream emits a string array (["stop"]).Trace_core.user_datahas no array variant, so we emit a plain string ("stop").ai.prompton root spans: upstream serializes full message content (gated byrecord_inputs). We emit placeholder strings ("<message>") to avoid serializing large payloads into span data. The full messages are available via integration callbacks.
W3C Trace Context
Parse the W3C Trace Context {traceparent} header to link backend spans to an incoming frontend trace. The header format (version 00) is a stable W3C Recommendation:
00-{32 hex trace_id}-{16 hex parent_id}-{2 hex flags}When passed to create via ~traceparent, the parsed IDs are emitted as ai.trace_context.trace_id, ai.trace_context.parent_id, and ai.trace_context.sampled attributes on every root span, so any trace collector can reconstruct the parent link.
If the user also installs the opentelemetry-trace bridge with ambient context, the parenting happens automatically at the Trace_core level — the attributes are still present as a belt-and-suspenders fallback.
type trace_context = {trace_id : string;(*32 lowercase hex chars
*)parent_id : string;(*16 lowercase hex chars
*)sampled : bool;
}Parsed W3C traceparent fields.
Parse a raw W3C {traceparent} header value. Returns None if the value is malformed, the wrong version, or contains all-zero trace/parent IDs (invalid per spec).
Types
Model info for callback events.
and integration = {on_start : (on_start_event -> unit Lwt.t) option;on_step_finish : (on_step_finish_event -> unit Lwt.t) option;on_tool_call_start : (on_tool_call_start_event -> unit Lwt.t) option;on_tool_call_finish : (on_tool_call_finish_event -> unit Lwt.t) option;on_finish : (on_finish_event -> unit Lwt.t) option;
}Lifecycle callbacks for telemetry events.
All callbacks are optional — implement only the ones you need. Errors in callbacks are caught and ignored (they must not break the generation pipeline). Callbacks are called in order: global integrations first, then per-call integrations (matching upstream).
and on_start_event = {model : model_info;messages : Ai_provider.Prompt.message list;tools : (string * Core_tool.t) list;function_id : string option;metadata : (string * Trace_core.user_data) list;
}and on_step_finish_event = {step_number : int;step : Generate_text_result.step;function_id : string option;metadata : (string * Trace_core.user_data) list;
}and on_tool_call_start_event = {step_number : int;model : model_info;tool_name : string;tool_call_id : string;args : Yojson.Basic.t;function_id : string option;metadata : (string * Trace_core.user_data) list;
}and on_tool_call_finish_event = {step_number : int;model : model_info;tool_name : string;tool_call_id : string;args : Yojson.Basic.t;result : tool_call_outcome;duration_ms : float;function_id : string option;metadata : (string * Trace_core.user_data) list;
}and on_finish_event = {steps : Generate_text_result.step list;total_usage : Ai_provider.Usage.t;finish_reason : Ai_provider.Finish_reason.t;function_id : string option;metadata : (string * Trace_core.user_data) list;
}Settings
Telemetry settings, enabling or disabling the logging of various pieces of information such as inputs or outputs or metadata
val create :
?enabled:bool ->
?record_inputs:bool ->
?record_outputs:bool ->
?function_id:string ->
?metadata:(string * Trace_core.user_data) list ->
?integrations:integration list ->
?traceparent:string ->
unit ->
tAttribute Selection
type attr = | Always of Trace_core.user_data| Input of unit -> Trace_core.user_data| Output of unit -> Trace_core.user_data
Attribute that may be conditionally recorded.
Always v: recorded whenever telemetry is enabledInput f: recorded only whenrecord_inputsistrue;fevaluated lazilyOutput f: recorded only whenrecord_outputsistrue;fevaluated lazily
Select attributes respecting telemetry settings. Returns [] immediately when enabled is false.
val assemble_operation_name :
operation_id:string ->
t ->
(string * Trace_core.user_data) listOperation Name Assembly
Builds the standard operation name attributes matching upstream: operation.name, resource.name, ai.operationId, ai.telemetry.functionId.
val base_attributes :
provider:string ->
model_id:string ->
settings_attrs:(string * Trace_core.user_data) list ->
headers:(string * string) list ->
t ->
(string * Trace_core.user_data) listBase Telemetry Attributes
Model info, call settings, user metadata, and request headers. Used on every span.
val settings_attributes :
?max_output_tokens:int ->
?temperature:float ->
?top_p:float ->
?top_k:int ->
?stop_sequences:string list ->
?seed:int ->
?frequency_penalty:float ->
?presence_penalty:float ->
?max_retries:int ->
unit ->
(string * Trace_core.user_data) listBuild settings attributes from call options. Only includes non-None values.
Optional Attribute Helpers
Build a single-element attribute list from an option value, or [] when None. Useful for building span data from optional call settings and response fields.
val opt_attr :
string ->
('a -> Trace_core.user_data) ->
'a option ->
(string * Trace_core.user_data) listLwt Span Helpers
An Lwt-aware ambient span provider (backed by Lwt.key) is installed at module load time. This makes Trace_core.current_span work across Lwt fibers, so nested with_span calls automatically form a parent-child hierarchy without explicit ~parent passing.
val with_span :
?parent:Trace_core.span ->
__FILE__:string ->
__LINE__:int ->
data:(unit -> (string * Trace_core.user_data) list) ->
string ->
(Trace_core.span -> 'a Lwt.t) ->
'a Lwt.twith_span ~__FILE__ ~__LINE__ ~data name f opens a span, sets it as the ambient current span (via Lwt.with_value), runs f span, and closes the span when the Lwt promise settles (via Lwt.on_termination).
When no Trace_core collector is installed, f receives a dummy span and no overhead is incurred.
Conditional Helpers
Convenience wrappers for use in generate_text and stream_text. When telemetry is None or enabled = false, these are zero-cost.
val maybe_span :
t option ->
string ->
__FILE__:string ->
__LINE__:int ->
data:(unit -> (string * Trace_core.user_data) list) ->
(Trace_core.span -> 'a Lwt.t) ->
'a Lwt.tConditionally wrap in a telemetry span. When telemetry is None or disabled, f is called with Trace_core.Collector.dummy_span.
Fire a telemetry notification when enabled; otherwise Lwt.return_unit.
Build a model_info from provider and model ID strings.
Serialize tool calls to a JSON string for telemetry attributes.
Precompute Helpers
One-shot telemetry setup shared by generate_text and stream_text. Extracts model info, settings, and base attributes. When telemetry is None or disabled, returns zero-cost defaults.
type precomputed = {model_info : model_info;function_id_ : string option;metadata_ : (string * Trace_core.user_data) list;base_data : (string * Trace_core.user_data) list;
}Precomputed telemetry values, extracted once per operation.
val precompute :
operation_id:string ->
model:(module Ai_provider.Language_model.S) ->
?max_output_tokens:int ->
?temperature:float ->
?top_p:float ->
?top_k:int ->
?stop_sequences:string list ->
?seed:int ->
?max_retries:int ->
?headers:(string * string) list ->
t option ->
precomputedStep Span Attribute Builders
Shared helpers that build span attributes for step spans (doGenerate / doStream) and tool call spans. These prevent attribute key drift between generate_text and stream_text.
val step_request_attrs :
operation_id:string ->
model_info:model_info ->
current_messages:Ai_provider.Prompt.message list ->
tools:(string * Core_tool.t) list ->
tool_choice:Ai_provider.Tool_choice.t option ->
?max_output_tokens:int ->
?temperature:float ->
?top_p:float ->
?top_k:int ->
?stop_sequences:string list ->
t ->
(string * Trace_core.user_data) listBuild request-side attributes for a step span.
val step_response_attrs :
text:string ->
reasoning:string ->
tool_calls:Generate_text_result.tool_call list ->
finish_reason:Ai_provider.Finish_reason.t ->
usage:Ai_provider.Usage.t ->
?response_id:string ->
?response_model:string ->
t ->
(string * Trace_core.user_data) listBuild response-side attributes for a step span.
val final_response_attrs :
text:string ->
reasoning:string ->
finish_reason:Ai_provider.Finish_reason.t ->
usage:Ai_provider.Usage.t ->
t ->
(string * Trace_core.user_data) listBuild final response attributes for the root span.
val tool_call_span_data :
model_info:model_info ->
tool_name:string ->
tool_call_id:string ->
args:Yojson.Basic.t ->
t ->
(string * Trace_core.user_data) listBuild initial span data for a tool call span.
val tool_call_result_attrs :
result:Yojson.Basic.t ->
t ->
(string * Trace_core.user_data) listBuild result attributes to add to a tool call span after execution.
Integration Values
An empty integration with no callbacks. Useful as a starting point for building partial integrations:
{ Telemetry.no_integration with
on_finish = Some (fun event -> ...);
}Integration Notification
Notify all integrations (per-call + global) of an event. Errors are caught and logged to stderr.
Global Integration Registry
Register an integration that receives events from all AI SDK operations. Useful for application-wide logging or metrics.
Remove all global integrations. Primarily for testing.
- Quick start
- Span hierarchy
- Attribute selectivity
- Upstream parity gaps
- W3C Trace Context
- Types
- Settings
- Attribute Selection
- Optional Attribute Helpers
- Lwt Span Helpers
- Conditional Helpers
- Precompute Helpers
- Step Span Attribute Builders
- Integration Values
- Integration Notification
- Global Integration Registry