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

Copy Markdown View Source

Trace context propagation for telemetry events.

Deprecated

Use Raxol.Core.Telemetry.TraceContext instead. It provides the same span/3, execute/3, and to_metadata/1 telemetry surface (with binary span names) plus causation tracking and header propagation. This module is retained for backward compatibility and will be removed in the next major release.

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)