ykachala/meter

Token accounting, multi-provider cost calculation, and budget guardrails for PHP AI apps. Know what every LLM call costs and stop runaway spend before it happens.

Maintainers

Package info

github.com/ykachala/meter

pkg:composer/ykachala/meter

Statistics

Installs: 0

Dependents: 0

Suggesters: 3

Stars: 0

Open Issues: 0

dev-main 2026-06-01 23:38 UTC

This package is auto-updated.

Last update: 2026-06-02 09:06:52 UTC


README

Token accounting, multi-provider cost calculation, and budget guardrails for PHP AI apps. Measure what every LLM call costs, attribute it to a user/team/feature, and enforce spend caps before the request goes out.

PHP Version License

Why this exists (the 2026 gap)

AI features in production have one universal failure mode: a surprise invoice. A single buggy loop, a jailbroken agent, or a viral launch can burn thousands of dollars in tokens overnight.

The Python ecosystem solved this with LiteLLM (virtual keys, per-key budgets, cost tracking) and SaaS like Langfuse. PHP teams in 2026 have observability (Langfuse has a PHP-friendly tracing path) but no native, in-process metering layer that can also refuse a call when a budget is blown. Observability tells you what you spent yesterday; Ykachala Meter stops you spending it today.

What it does

  • Token estimation — pre-flight token counts per provider so you can budget before sending.
  • Cost calculation — a versioned, dated PriceBook for OpenAI, Anthropic, Google, Mistral, and custom models (input/output/cached-input/reasoning tiers).
  • Usage recording — every call recorded with model, tokens, cost, latency, and arbitrary tags (user_id, team, feature).
  • Budgets — hard and soft caps scoped to any tag (per user, per team, per day/month). Soft caps fire an event; hard caps throw before the request leaves.
  • Exporters — roll usage up to Prometheus, OpenTelemetry, or a plain SQL table.

Install

composer require ykachala/meter

Quick start

use Ykachala\Meter\Meter;
use Ykachala\Meter\PriceBook;
use Ykachala\Meter\Budget\Budget;

$meter = new Meter(
    prices: PriceBook::default(),            // dated, versioned price tables
    store:  new Psr16UsageStore($cache),
);

// 1. Enforce a budget BEFORE the call
$meter->budget(Budget::monthly('team:acme', usd: 500.00));

$estimate = $meter->estimate('claude-opus-4-8', $messages);
$meter->assertWithinBudget('team:acme', $estimate);   // throws BudgetExceeded if over

// 2. Record actual usage AFTER the call
$usage = $meter->record(
    model: 'claude-opus-4-8',
    inputTokens: $response->usage->input,
    outputTokens: $response->usage->output,
    tags: ['team' => 'acme', 'user' => $userId, 'feature' => 'support-bot'],
);

echo $usage->cost->format();      // "$0.0241"
echo $meter->spent('team:acme')->format();  // running total this period

Budgets

$meter->budget(Budget::daily('user:'.$userId, usd: 2.00, soft: 1.50));

$meter->on(BudgetSoftLimitReached::class, function ($e) {
    Notification::send($e->scope, new ApproachingLimit($e->spent, $e->limit));
});
// Hard limit throws BudgetExceeded — catch it and degrade gracefully (smaller model, queue, deny).

Wrap any client

Meter is a measurement layer, not a client. Wrap whatever you already use:

$response = $meter->wrap(
    fn () => $prism->text()->using('anthropic', 'claude-opus-4-8')->generate(),
    tags: ['feature' => 'summarizer'],
);
// usage auto-recorded from the response; budgets enforced around the closure

Architecture

src/
├── Meter.php             # facade: estimate / record / wrap / budget / spent
├── PriceBook.php         # dated price tables, per-model, per-tier
├── Money.php             # integer-cents money value object
├── Usage.php             # one recorded call (tokens, cost, latency, tags)
├── Budget/               # Budget definitions + enforcement + events
├── Store/                # PSR-16, SQL, in-memory usage stores
└── Export/               # Prometheus / OpenTelemetry / SQL exporters

Roadmap

  • Money + Usage value objects, integer-cents arithmetic
  • PriceBook with dated tables (input/output/cached/reasoning tiers)
  • Token estimators per provider family
  • Usage stores (in-memory, PSR-16, SQL)
  • Budget definitions + soft/hard enforcement + events
  • Prometheus & OpenTelemetry exporters

See CLAUDE.md for the full phase plan and conventions.

License

MIT