0.0
The project is in a healthy, maintained state
Captures LLM token usage metrics per task for cost attribution and intelligent routing
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

Runtime

 Project Readme

lex-metering

LLM cost metering for LegionIO. Records token usage, latency, and routing metrics per task for cost attribution, budget forecasting, and intelligent model routing.

Ruby >= 3.4 | License: MIT | Author: @Esity

Installation

Included with the LegionIO framework. No separate installation needed.

# Gemfile
gem 'lex-metering'

Architecture

Legion::Extensions::Metering
├── Runners/
│   ├── Metering         # record, worker_costs, team_costs, routing_stats, cleanup_old_records
│   ├── CostOptimizer    # analyze_costs (LLM-powered model rightsizing)
│   └── Rollup           # rollup_hour, purge_raw_records
├── Actors/
│   ├── Cleanup          # Daily (86400s) — prunes records older than 90 days
│   ├── CostOptimizer    # Weekly (604800s) — generates model rightsizing recommendations
│   └── Rollup           # Hourly (3600s) — aggregates raw records into hourly summaries
├── Helpers/
│   └── Economics        # payroll_summary, worker_report, budget_forecast
└── Data/Migrations/
    ├── 001              # metering_records table
    ├── 002              # trace columns (cost_usd, status, event_type, extension, runner_function)
    └── 003              # indexes (worker_id, task_id, provider, recorded_at)

Usage

Recording Metrics

Legion::Extensions::Metering::Runners::Metering.record(
  worker_id:      'worker-abc',
  task_id:        42,
  provider:       'anthropic',
  model_id:       'claude-sonnet-4-6',
  input_tokens:   1000,
  output_tokens:  500,
  thinking_tokens: 200,
  latency_ms:     1200,
  wall_clock_ms:  1500,
  cpu_time_ms:    80,
  cost_usd:       0.0051,
  routing_reason: 'cost_optimization',
  extension:      'lex-developer',
  runner_function: 'generate_code',
  status:         'success',
  event_type:     'llm_completion'
)

Querying Costs

# Per-worker costs (daily/weekly/monthly)
Legion::Extensions::Metering::Runners::Metering.worker_costs(
  worker_id: 'worker-abc',
  period:    'weekly'
)
# => { worker_id:, period:, total_tokens:, input_tokens:, output_tokens:,
#      thinking_tokens:, total_calls:, avg_latency_ms:, by_provider:, by_model: }

# Per-team costs
Legion::Extensions::Metering::Runners::Metering.team_costs(
  team: 'engineering',
  period: 'monthly'
)
# => { team:, period:, worker_count:, total_tokens:, total_calls:, by_worker: }

Routing Statistics

Legion::Extensions::Metering::Runners::Metering.routing_stats(worker_id: 'worker-abc')
# => { by_routing_reason: [...], by_provider: [...], by_model: [...],
#      avg_latency_by_provider: [{ provider: 'anthropic', avg_latency: 820.0 }] }

Hourly Rollup

Raw records are aggregated hourly into metering_hourly_rollup for efficient reporting:

# Manually trigger (normally runs via actor)
Legion::Extensions::Metering::Runners::Rollup.rollup_hour
# => { rolled_up: 15, hour: "2026-05-17T10:00:00Z", raw_records: 340 }

# Purge rolled-up raw records (default: 7 days retention)
Legion::Extensions::Metering::Runners::Rollup.purge_raw_records(retention_days: 7)
# => { purged: 2400, retention_days: 7, cutoff: "2026-05-10T11:00:00Z" }

Cost Optimization

Weekly LLM-powered analysis identifies model rightsizing opportunities:

Legion::Extensions::Metering::Runners::CostOptimizer.analyze_costs(window_days: 7, top_n: 10)
# => { status: 'analyzed', window_days: 7, cost_drivers: [...],
#      recommendations: [{ extension: 'lex-developer', current_model: 'claude-opus-4-6',
#                          suggested_model: 'claude-sonnet-4-6', rationale: '...',
#                          estimated_savings_pct: 80 }] }

Built-in rate table (per 1M tokens):

Provider Model Rate
Anthropic claude-opus-4-6 $15.00
Anthropic claude-sonnet-4-6 $3.00
Anthropic claude-haiku-4-5 $0.25
OpenAI gpt-4o $5.00
OpenAI gpt-4o-mini $0.15
OpenAI gpt-4.1 $2.00
Bedrock default $3.00
Azure AI default $3.00

Economics Helper

Labor economics reporting for digital worker cost attribution:

include Legion::Extensions::Metering::Helpers::Economics

payroll_summary(period: :weekly)
# => { workers: [{ worker_id:, task_count:, cost:, autonomy: }], total_cost:, avg_productivity: }

worker_report(worker_id: 'worker-abc', period: :daily)
# => { worker_id:, salary:, overtime:, productivity:, avg_latency:, autonomy_level: }

budget_forecast(days: 30)
# => { projected_cost: 4.50, daily_average: 0.15, days: 30, trend: :active }

Database Schema

metering_records

Column Type Description
id Integer (PK) Auto-increment primary key
worker_id String(36) Digital worker ID
task_id Integer Legion task ID
provider String(100) LLM provider name
model_id String(255) Model identifier
input_tokens Integer Prompt tokens
output_tokens Integer Completion tokens
thinking_tokens Integer Reasoning tokens
total_tokens Integer Sum of all token types
input_context_bytes Integer Raw context size in bytes
latency_ms Integer LLM API round-trip time
wall_clock_ms Integer Total wall-clock time
cpu_time_ms Integer CPU time consumed
external_api_calls Integer Non-LLM external API calls
routing_reason String(255) Model/provider selection rationale
cost_usd Float Estimated cost in USD
status String(50) Pipeline status at time of record
event_type String(100) Event type for audit correlation
extension String(255) Calling extension name
runner_function String(255) Calling runner function
recorded_at DateTime Timestamp (indexed)

Indexes: worker_id, task_id, provider, recorded_at, status, event_type, extension

metering_hourly_rollup

Aggregated hourly summaries grouped by worker/provider/model. One row per unique combination per hour, upserted on each rollup cycle.

Record Retention

Actor Interval Retention Description
Cleanup Daily 90 days Prunes raw metering_records older than cutoff
Rollup Hourly Aggregates into metering_hourly_rollup
Purge On-demand 7 days Removes rolled-up raw records via purge_raw_records
# Manual cleanup
Legion::Extensions::Metering::Runners::Metering.cleanup_old_records(retention_days: 90)
# => { purged: 1234, retention_days: 90, cutoff: 2026-02-16 00:00:00 UTC }

Integration Points

System Interface Description
MCP legion.routing_stats Tool for querying routing statistics
REST API GET /api/metering Returns routing stats and recent records
CLI legion worker costs Worker cost attribution from terminal
lex-llm-gateway Shared table Gateway publishes metering events over AMQP
legion-data Migrations 021, 046 Archive table and hourly rollup DDL

Development

bundle install
bundle exec rspec
bundle exec rubocop

Related