Skip to content

Span

class

Defined in src/logit/tracing/span.cr:67

Represents a traced operation with timing, attributes, and trace context.

Spans are the core building block of Logit's tracing system. Each instrumented method call creates a span that tracks: - Start and end times (for duration calculation) - Trace and span IDs (for distributed tracing) - Parent span ID (for call hierarchy) - Custom attributes (for structured data) - Exception information (if an error occurred)

Spans are stored in a fiber-local stack, allowing safe concurrent tracing across multiple fibers without interference.

Accessing the Current Span

Inside an instrumented method, you can access the current span to add custom attributes:

class OrderService
  @[Logit::Log]
  def process_order(order_id : Int32) : Bool
    # Add custom attributes to the current span
    if span = Logit::Span.current?
      span.attributes.set("order.priority", "high")
      span.attributes.set("order.items_count", 5_i64)
    end

    # ... process the order
    true
  end
end

Trace Context

Nested method calls automatically share the same trace ID and form a parent-child relationship through span IDs:

class PaymentService
  @[Logit::Log]
  def charge(amount : Float64) : Bool
    validate_amount(amount)  # Child span, same trace_id
    process_payment(amount)  # Child span, same trace_id
    true
  end

  @[Logit::Log]
  def validate_amount(amount : Float64) : Bool
    amount > 0
  end

  @[Logit::Log]
  def process_payment(amount : Float64) : Bool
    # ...
    true
  end
end

Constructors

.current

View source

Returns the current span for this fiber.

Raises an exception if no span is active. Prefer current? unless you're certain a span exists.


.new(name : String, span_id : String = Utils::IDGenerator.span_id, parent_span_id : Nil | String = nil)

View source

Creates a new span with the given name.

Automatically inherits the trace ID from the current span (if any), or generates a new trace ID for root spans. The parent span ID is set to the current span's ID.


Class Methods

.current?

View source

Returns the current span for this fiber, or nil if none is active.

Use this to safely access the current span without raising an exception.

if span = Logit::Span.current?
  span.attributes.set("custom.field", "value")
end

.pop(fiber_stack : Array(Span)) : Span | Nil

View source

Optimized version that takes the span stack directly to avoid repeated Fiber.current access. Used internally by the instrumentation macros.


.pop

View source

Pops the current span from the fiber-local span stack.

This is called automatically by the instrumentation macros. You typically don't need to call this directly.


.push(span : Span, fiber_stack : Array(Span)) : Nil

View source

Optimized version that takes the span stack directly to avoid repeated Fiber.current access. Used internally by the instrumentation macros.


.push(span : Span) : Nil

View source

Pushes a span onto the fiber-local span stack.

This is called automatically by the instrumentation macros. You typically don't need to call this directly.


Instance Methods

#add_event(name : String, **attributes) : Nil

View source

Adds a span event (intermediate log within a span).

This allows logging important events during long-running operations without creating separate spans. Events are attached to this span and included when the span is converted to an Event.

Usage

@[Logit::Log]
def process_large_file(path : String) : Result
  span = Logit::Span.current

  span.add_event("file.opened", path: path)

  results = process_chunks(path)

  span.add_event("file.processed",
    path: path,
    chunks: results.size
  )

  results
end

OpenTelemetry Compatibility

Span events map directly to OpenTelemetry Span Events, allowing for rich observability without creating separate spans for every operation.


#attributes

View source

Structured attributes attached to this span.


#end_time

View source

When this span ended (set when the span completes).


#events

View source

Span events that occurred during this span's lifetime.

These are intermediate logs attached to a span, similar to OpenTelemetry's Span Events. Use add_event to add events.


#exception

View source

Exception information if an error occurred during this span.


#name

View source

Name of this span (typically the method name).


#parent_span_id

View source

Span ID of the parent span, or nil if this is a root span.


#span_id

View source

Unique identifier for this span (64-bit hex string).


#start_time

View source

When this span started.


#to_event(trace_id : String, level : LogLevel, code_file : String, code_line : Int32, method_name : String, class_name : String) : Event

View source

Converts this span to an Event for logging.

Called automatically when a span completes. You typically don't need to call this directly.


#trace_id

View source

W3C trace ID (128-bit hex string) shared across all spans in a trace.