AITrace (AITrace v0.2.0)

Copy Markdown View Source

The unified observability layer for the AI Control Plane.

AITrace provides instrumentation for capturing the complete causal chain of an AI agent's reasoning process.

Quick Start

defmodule MyAgent do
  require AITrace

  def handle_message(message) do
    AITrace.trace "agent.handle_message" do
      AITrace.add_event("Message received", %{text: message})

      AITrace.span "reasoning_loop" do
        # Perform reasoning
        result = think_about(message)

        AITrace.with_attributes(%{tokens: result.token_count})
        result
      end
    end
  end
end

Core Concepts

  • Trace: The complete record of a transaction, identified by a trace_id
  • Span: A timed operation within a trace (can be nested)
  • Event: A point-in-time annotation within a span
  • Context: An immutable map carrying trace and span IDs through the call stack

Exporters

Configure exporters in your config:

config :aitrace,
  exporters: [
    {AITrace.Exporter.Console, verbose: true},
    {AITrace.Exporter.File, directory: "./traces"}
  ]

Summary

Functions

Adds an event to the current span.

Clears process-local context.

Exports a fully materialized trace through the configured exporter pipeline.

Exports a fully materialized trace through an explicit export profile or exporter list.

Gets the current context from the process dictionary.

Restores process-local context, deleting it when the previous context was nil.

Runs a span with an explicit parent context argument.

Runs a trace with an explicit context argument.

Sets the current context in the process dictionary.

Creates a span within a trace.

Starts a new trace.

Adds attributes to the current span.

Functions

add_event(name_or_context, name_or_attributes \\ %{})

@spec add_event(String.t(), map()) :: :ok
@spec add_event(AITrace.Context.t(), String.t()) :: :ok

Adds an event to the current span.

Examples

AITrace.add_event("cache_hit", %{key: "user_123"})
AITrace.add_event("validation_passed")

add_event(ctx, name, attributes)

@spec add_event(AITrace.Context.t(), String.t(), map()) :: :ok

clear_current_context()

@spec clear_current_context() :: :ok

Clears process-local context.

export(trace)

@spec export(AITrace.Trace.t()) :: :ok | {:error, term()}

Exports a fully materialized trace through the configured exporter pipeline.

This is the bridge-facing one-shot path for integrations that construct completed AITrace.Trace values directly.

export(trace, export_profile)

@spec export(AITrace.Trace.t(), AITrace.ExportProfile.t()) :: :ok | {:error, term()}
@spec export(AITrace.Trace.t(), [module() | {module(), keyword() | map()}]) ::
  :ok | {:error, term()}

Exports a fully materialized trace through an explicit export profile or exporter list.

Use this when a caller needs one-shot export behavior without relying on application-configured exporters.

Examples

trace = AITrace.Trace.new("trace-123")

AITrace.export(trace, [
  {AITrace.Exporter.Console, verbose: true}
])

get_current_context()

@spec get_current_context() :: AITrace.Context.t() | nil

Gets the current context from the process dictionary.

restore_current_context(ctx)

@spec restore_current_context(AITrace.Context.t() | nil) :: :ok

Restores process-local context, deleting it when the previous context was nil.

run_span(parent_ctx, name, fun)

@spec run_span(AITrace.Context.t(), String.t(), (AITrace.Context.t() -> result)) ::
  result
when result: var

Runs a span with an explicit parent context argument.

This path does not read or write process dictionary context.

run_trace(name, fun, opts \\ [])

@spec run_trace(String.t(), (AITrace.Context.t() -> result), keyword()) :: result
when result: var

Runs a trace with an explicit context argument.

This path does not write to the process dictionary. It is the preferred production API when context must cross task or process boundaries.

set_current_context(ctx)

@spec set_current_context(AITrace.Context.t()) :: :ok

Sets the current context in the process dictionary.

span(name, list)

(macro)

Creates a span within a trace.

The span macro creates a timed operation within the current trace. Use AITrace.get_current_context() to access the current context.

Examples

AITrace.trace "request" do
  AITrace.span "database_query" do
    query_database()
  end
end

Returns the result of the block.

trace(name, list)

(macro)

Starts a new trace.

The trace macro creates a new trace and stores the context in the process dictionary. Use AITrace.get_current_context() to retrieve it.

Examples

require AITrace

AITrace.trace "user_request" do
  process_request()
end

Returns the result of the block.

with_attributes(attributes)

@spec with_attributes(map()) :: :ok

with_attributes(ctx, attributes)

@spec with_attributes(AITrace.Context.t(), map()) :: :ok

Adds attributes to the current span.

Examples

AITrace.with_attributes(%{user_id: 42, region: "us-west"})