Raxol.Core.Telemetry.Context (Raxol Core v2.4.0)

Copy Markdown View Source

Trace context propagation for telemetry events.

Provides request correlation across components using trace_id and span_id. Following OpenTelemetry-compatible patterns for distributed tracing.

Design

Trace context is stored in the process dictionary and automatically propagated to child processes. This allows correlating all telemetry events within a single request/operation.

Usage

# Start a new trace (e.g., at request entry point)
Context.start_trace()

# Start a child span within a trace
Context.start_span(:render)

# Get current context for telemetry metadata
metadata = Context.to_metadata()
:telemetry.execute([:raxol, :render, :stop], measurements, metadata)

# End current span
Context.end_span()

# Wrap a function with span instrumentation
Context.with_span(:database_query, fn ->
  # ... work ...
end)

Context Structure

%{
  trace_id: "abc123def456",      # Unique per request/trace
  span_id: "span789",            # Unique per operation within trace
  parent_span_id: "span456",     # Parent span (for nesting)
  baggage: %{}                   # Additional context to propagate
}

Summary

Functions

Captures current context for propagation to another process.

Clears the current trace context.

Ends the current span and returns to the parent span.

Executes a telemetry event with trace context automatically injected.

Gets the current trace context.

Gets a baggage value.

Sets a baggage value that will be propagated with the trace.

Restores captured context in a new process.

Wraps a function with telemetry span instrumentation.

Gets the current span_id, or nil if no trace is active.

Starts a new span within the current trace.

Starts a new trace with a unique trace_id.

Converts current context to telemetry metadata map.

Gets the current trace_id, or nil if no trace is active.

Executes a function within a new span.

Types

span_id()

@type span_id() :: String.t()

t()

@type t() :: %{
  trace_id: trace_id(),
  span_id: span_id(),
  parent_span_id: span_id() | nil,
  baggage: map()
}

trace_id()

@type trace_id() :: String.t()

Functions

capture()

@spec capture() :: t() | nil

Captures current context for propagation to another process.

Examples

# In parent process
captured = Context.capture()

# In spawned process
Task.async(fn ->
  Context.restore(captured)
  # ... work with trace context ...
end)

clear()

@spec clear() :: :ok

Clears the current trace context.

Call this when a request/operation completes.

end_span()

@spec end_span() :: t() | nil

Ends the current span and returns to the parent span.

execute(event, measurements, metadata \\ %{})

@spec execute([atom()], map(), map()) :: :ok

Executes a telemetry event with trace context automatically injected.

Examples

Context.execute([:raxol, :render, :stop], %{duration: 1234}, %{component: :button})

get()

@spec get() :: t() | nil

Gets the current trace context.

Returns nil if no trace is active.

get_baggage(key, default \\ nil)

@spec get_baggage(atom(), any()) :: any()

Gets a baggage value.

put_baggage(key, value)

@spec put_baggage(atom(), any()) :: :ok

Sets a baggage value that will be propagated with the trace.

Baggage is additional context that travels with the trace.

Examples

Context.put_baggage(:user_id, "user123")
Context.put_baggage(:request_path, "/api/users")

restore(captured)

@spec restore(map() | nil) :: :ok

Restores captured context in a new process.

span(event_prefix, metadata, fun)

@spec span([atom()], map(), (-> result)) :: result when result: any()

Wraps a function with telemetry span instrumentation.

Emits start/stop/exception events with trace context.

Examples

result = Context.span([:raxol, :render], %{component: :button}, fn ->
  render_component()
end)

span_id()

@spec span_id() :: span_id() | nil

Gets the current span_id, or nil if no trace is active.

start_span(name)

@spec start_span(atom()) :: t()

Starts a new span within the current trace.

Spans can be nested - calling start_span while a span is active creates a child span.

Examples

Context.start_span(:render)
# ... do rendering ...
Context.end_span()

start_trace(opts \\ [])

@spec start_trace(keyword()) :: t()

Starts a new trace with a unique trace_id.

Call this at the entry point of a request or operation. Returns the trace context.

Examples

context = Context.start_trace()
# => %{trace_id: "abc123...", span_id: "def456...", ...}

# With custom trace_id (e.g., from incoming request header)
context = Context.start_trace(trace_id: "incoming-trace-id")

to_metadata(extra \\ %{})

@spec to_metadata(map()) :: map()

Converts current context to telemetry metadata map.

Use this to add trace context to telemetry events:

Examples

metadata = Context.to_metadata()
:telemetry.execute([:raxol, :render], measurements, metadata)

# With additional metadata
metadata = Context.to_metadata(%{component: :button})

trace_id()

@spec trace_id() :: trace_id() | nil

Gets the current trace_id, or nil if no trace is active.

with_span(name, fun)

@spec with_span(atom(), (-> result)) :: result when result: any()

Executes a function within a new span.

Automatically starts a span, executes the function, and ends the span. The span timing is captured for telemetry.

Examples

result = Context.with_span(:database_query, fn ->
  Repo.all(User)
end)