Module: Legion::LLM::Inference::Steps::Metering

Extended by:
Legion::Logging::Helper
Included in:
Executor
Defined in:
lib/legion/llm/inference/steps/metering.rb

Class Method Summary collapse

Class Method Details

.build_event(**opts) ⇒ Object



14
15
16
17
18
19
20
21
# File 'lib/legion/llm/inference/steps/metering.rb', line 14

def build_event(**opts)
  log.debug(
    "[metering][build_event] action=build request_id=#{opts[:request_id]} " \
    "conversation_id=#{opts[:conversation_id] || 'none'} provider=#{opts[:provider]} " \
    "instance=#{opts[:provider_instance] || 'default'} model=#{opts[:model_id]}"
  )
  identity_fields(opts).merge(token_fields(opts)).merge(timing_and_context(opts))
end

.flush_spoolObject



38
39
40
41
# File 'lib/legion/llm/inference/steps/metering.rb', line 38

def flush_spool
  log.debug('[metering][flush_spool] action=flush')
  Legion::LLM::Metering.flush_spool
end

.identity_fields(opts) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/legion/llm/inference/steps/metering.rb', line 43

def identity_fields(opts)
  {
    node_id:         opts[:node_id],
    worker_id:       opts[:worker_id],
    agent_id:        opts[:agent_id],
    task_id:         opts[:task_id],
    request_id:      opts[:request_id],
    conversation_id: opts[:conversation_id],
    correlation_id:  opts[:correlation_id],
    caller:          opts[:caller],
    identity:        opts[:identity],
    billing:         opts[:billing],
    request_type:    opts[:request_type],
    tier:            opts[:tier],
    provider:        opts[:provider],
    model_id:        opts[:model_id],
    offering_id:     opts[:offering_id]
  }.compact
end

.publish_event(event) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/legion/llm/inference/steps/metering.rb', line 82

def publish_event(event)
  log.debug(
    "[metering][publish_event] action=emit request_id=#{event[:request_id]} " \
    "conversation_id=#{event[:conversation_id] || 'none'}"
  )
  Legion::LLM::Metering.emit(event)
end

.publish_or_spool(event) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/legion/llm/inference/steps/metering.rb', line 23

def publish_or_spool(event)
  log.debug(
    "[metering][publish_or_spool] action=publish request_id=#{event[:request_id]} " \
    "provider=#{event[:provider]} model=#{event[:model_id]} total_tokens=#{event[:total_tokens]}"
  )
  result = publish_event(event)
  if result == :dropped
    log.warn(
      "[metering][publish_or_spool] action=dropped request_id=#{event[:request_id]} " \
      "provider=#{event[:provider]} model=#{event[:model_id]}"
    )
  end
  result
end

.timing_and_context(opts) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/legion/llm/inference/steps/metering.rb', line 71

def timing_and_context(opts)
  {
    latency_ms:        opts.fetch(:latency_ms, 0),
    wall_clock_ms:     opts.fetch(:wall_clock_ms, 0),
    cost_usd:          opts[:cost_usd],
    routing_reason:    opts[:routing_reason],
    offering_metadata: opts[:offering_metadata],
    recorded_at:       Time.now.utc.iso8601
  }.compact
end

.token_fields(opts) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/legion/llm/inference/steps/metering.rb', line 63

def token_fields(opts)
  input    = opts.fetch(:input_tokens, 0)
  output   = opts.fetch(:output_tokens, 0)
  thinking = opts.fetch(:thinking_tokens, 0)
  { input_tokens: input, output_tokens: output, thinking_tokens: thinking,
    total_tokens: input + output + thinking }
end