Class: Insika::Telemetry::Recorder

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/telemetry/recorder.rb

Overview

Translates the insika Event Stream into OTEL SPANS and METRICS — the already-existing observability spine becomes telemetry without touching the core (Events observe; Telemetry only consumes).

SPANS: one per TURN (insika.turn) with child spans per tool (insika.tool / insika.data_tool), correlated by task_id. Latency is the span duration; the agent/tenant/model/tokens/cost ride as ATTRIBUTES.

METRICS: the SAME events also feed counters and histograms, so volume/latency/tokens/cost are chartable WITHOUT span aggregation (which not every backend does, and none does cheaply at retention). Metric attributes are a deliberate LOW-CARDINALITY subset of the span attributes — never task_id or session_id. meter: nil -> spans only (the metrics SDK is optional).

pricing: nil -> no cost attribute/metric. Cost is an ESTIMATE from an operator-declared rates table (see Pricing) — the engine ships no prices.

PURE/testable: talks to a DUCK-TYPED tracer (start_span/set_attribute/ record_error/finish) and meter (create_counter/create_histogram -> add/ record) — the real OTEL adapters are injected in Telemetry.setup, fakes in

tests. Does NOT reference OpenTelemetry

(loads without the gem).

Robust: record NEVER raises (telemetry doesn't bring down a turn). Timestamps come from each event's meta.at (spans reconstructed with real time).

Defined Under Namespace

Classes: Instruments, OpenTool, Turn

Constant Summary collapse

MAX_OPEN =

Ceiling of open turns: a kill -9 without a terminal event would leave the turn hanging; when exceeded, the oldest is closed (defensive, bounded memory).

1_000

Instance Method Summary collapse

Constructor Details

#initialize(tracer:, meter: nil, pricing: nil) ⇒ Recorder

Returns a new instance of Recorder.



61
62
63
64
65
66
# File 'lib/insika/telemetry/recorder.rb', line 61

def initialize(tracer:, meter: nil, pricing: nil)
  @tracer = tracer
  @instruments = meter && Instruments.new(meter)
  @pricing = pricing
  @turns = {}
end

Instance Method Details

#record(event) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/insika/telemetry/recorder.rb', line 68

def record(event)
  meta = event.meta || {}
  data = event.data || {}
  case event.type
  when :task_started   then start_turn(meta, data)
  when :tool_call      then start_tool(meta, data)
  when :tool_result    then finish_tool(meta)
  when :data_tool_call then point_tool(meta, data)
  when :task_completed then finish_turn(meta, data, :ok)
  when :task_failed    then finish_turn(meta, data, :error)
  when :task_cancelled then finish_turn(meta, data, :cancelled)
  end
  nil
rescue StandardError
  nil # telemetry NEVER brings down the consumer/turn
end