---
id: w8/m1/t002
title: Prometheus rollup queries — instance-seconds per service/tier + egress bytes
worker: worker8
status: done
estimate: 45m
depends_on: []
---

## Objective

Write the two Prometheus rollup queries the metering loop evaluates per hourly window: instance-seconds per service (from cAdvisor container-running series, attributed to the App's current tier) and egress bytes per service (from the Traefik series the existing `monthToDateBandwidth` companion already queries).

## Context

- `lego/backend/internal/metrics/source.go` already holds the Prometheus client (`BEX_PROM_URL`) used for resource-metrics history (cAdvisor) and request metrics (Traefik) — reuse it, don't add a second client.
- The `monthToDateBandwidth` implementation in `internal/metrics` contains the Traefik egress expression to adapt from month-to-date to a bounded hourly window.
- Instance-seconds: derive from cAdvisor running-container series for the App's pods (namespace/pod labels), summed over the window; multiply nothing — seconds are the unit. Tier comes from the App's current `tier` (lego/types/tiers) at rollup time.
- Queries must be window-bounded (`start`/`end` = the hour) so re-evaluation is deterministic.

## Steps

1. Locate the existing cAdvisor and Traefik expressions in `internal/metrics` and factor window-bounded variants for metering.
2. Implement `instance-seconds(service, window)` and `egress-bytes(service, window)` query functions in the new `internal/usage` package (or a `usage`-owned file that imports the metrics source).
3. Unit-test both against a fake Prometheus API with fixture responses (existing metrics tests show the pattern).

## Files

- `lego/backend/internal/usage/` (new feature package — one package per feature, per the m2.5 refactor)
- `lego/backend/internal/metrics/source.go` (reuse/export the client if needed)

## Acceptance criteria

- [ ] Fixture-backed unit tests return expected instance-seconds and egress bytes for a known window.
- [ ] Evaluating the same window twice returns identical results (deterministic, window-bounded).

## Out of scope

- The ticker/persistence loop (t003); build minutes (t004 — not Prometheus-sourced).
