Perch Custom Services Roster
nestr intermediate 6 min read
Status: pre-production. Perch is pre-production (nestr-tools CLAUDE.md:40 @b8f0585). None of these four services has a Helm template; each exists only as source plus a raw manifest under
perch/k8s/(nestr-tools/perch @f9ec790, read 2026-10-25), and each was last changed 2026-06-03.
ELI5
Perch ships four little assistants on top of vanilla Prometheus: an accountant (cost-monitor), a coach with a clipboard (slo-tracker), a security guard at the deploy door (policy-enforcer), and a detective with a magnifying glass linking traces to logs (trace-correlator).
Technical Deep Dive
Source: nestr-tools/perch cost-monitor/main.go, slo-tracker/main.go:21-28,58, policy-enforcer/main.go:20-55,114-133, trace-correlator/main.go, k8s/{cost-monitor,slo-tracker,policy-enforcer,trace-correlator}/, helm/templates/ (no template for any of them), helm/values.yaml:33-36 @f9ec790; nestr-tools CLAUDE.md:86-101 (I-5) @b8f0585; read 2026-10-25. Endpoints and defaults re-verified against source; deployment status corrected. I-5 requires Perch to ship PEL-DIFF, PEL-REP and PEL-LOG panels before generic golden-signal dashboards, and the Helm chart’s only bundled dashboards are pellets-supply-chain.json and pellets-transparency-log.json; these four generic services sit outside that priority.
flowchart TB P[Prometheus] L[Loki] J[Jaeger] GH[GitHub PR] SL[Slack / PagerDuty]
subgraph Custom["Perch custom services (Go)"] CM[cost-monitor :8080] ST[slo-tracker :8080] PE[policy-enforcer :8080] TC[trace-correlator :8080] end
P --> CM P --> ST P --> PE ST -->|error budget| PE GH -->|/webhook/github| PE PE --> SL L --> TC J --> TC P --> TCcost-monitor (perch/cost-monitor/main.go)
- Polls Prometheus on
UpdateInterval(default 5 m). - Endpoints:
GET /api/v1/costs,GET /api/v1/capacity,GET /api/v1/recommendations. - Inputs: resource metrics (CPU, memory, storage),
CloudProvider,Regionfor unit pricing. - Outputs: per-service cost, capacity utilisation, rightsizing recommendations as JSON.
slo-tracker (perch/slo-tracker/main.go)
- Update interval default 60 s.
- Endpoints:
GET /api/v1/slo/status?service=X,GET /api/v1/error-budget?service=X&window=30d. - Re-emits its own SLO metrics into Prometheus so dashboards and alerts can subscribe; downstream of cost-monitor for spend-per-9 calculations.
policy-enforcer (perch/policy-enforcer/main.go)
- Three modes:
audit,warn,enforce. - Endpoints:
GET /api/v1/policy/check?service=X,GET /api/v1/policy/status,POST /webhook/github. - The GitHub webhook reads the slo-tracker’s error budget for the service named after the repository and answers the delivery with 403 when the budget is exhausted; it fails open when slo-tracker is unreachable (see Examples).
- Slack notification on enforcement is described in the service’s design; not verified in this revision.
trace-correlator (perch/trace-correlator/main.go)
- Bridges Jaeger ↔ Loki ↔ Prometheus by trace ID and request ID.
- Endpoints:
GET /api/v1/trace/logs?trace_id=X&service=Y,GET /api/v1/logs/trace?request_id=X,GET /api/v1/correlate?id=X&start_time=…&end_time=…. - Default time window: last hour when not specified — important to remember when correlating an old incident.
Operator Decision Table
| Question | Service to call |
|---|---|
| ”How much does service X cost this month?“ | cost-monitor /api/v1/costs |
| ”Is service X within its SLO?“ | slo-tracker /api/v1/slo/status |
| ”Can I merge this PR safely?“ | policy-enforcer /api/v1/policy/check |
| ”Show me logs for this trace ID” | trace-correlator /api/v1/trace/logs |
Key Terms
- Error budget →
1 - SLOminus consumed unreliability over a window; policy-enforcer gates on this. - Rightsizing → cost-monitor’s recommendation to scale resources up or down based on observed utilisation.
- Audit / warn / enforce → policy-enforcer modes; only
enforceblocks merges, the other two are observe-only.
Q&A
Q: Which service correlates a trace ID to log lines?
A: trace-correlator: GET /api/v1/trace/logs?trace_id=...&service=..., plus /api/v1/logs/trace?request_id=... and /api/v1/correlate.
Q: What signal does the policy-enforcer GitHub webhook check?
A: The touched service’s error budget, read from slo-tracker (-slo-tracker-url, default http://slo-tracker.perch-system.svc.cluster.local:8080) before allowing the deployment (policy-enforcer/main.go:114-133). Its default mode is warn.
Q: What is the SLO-tracker’s default update interval?
A: 60 seconds (-update-interval, slo-tracker/main.go:28).
Q: What happens if the slo-tracker is down when policy-enforcer is asked?
A: It fails open. CheckPolicy starts from Allowed: true and, when the error-budget fetch or parse fails, only records the reason (enforcer.go:113-136); the merge is not blocked. Whether a Slack message is sent on that path was not verified.
Q: Does cost-monitor write back to Prometheus? A: Recommendations are exposed only over its own JSON API; cost time-series themselves are computed on the fly from PromQL queries.
Q: Why split slo-tracker and policy-enforcer instead of one service? A: SLO computation is read-mostly and cacheable; policy enforcement carries a write surface (the webhook, and Slack by design). Separating them keeps blast radius small when the gating logic changes.
Examples
As coded (never observed running), a pull_request webhook with action opened or synchronize makes policy-enforcer map the repository name to a service, fetch error-budget?service=<repo>&window=30d from slo-tracker, and answer the webhook itself with 403 {allowed: false, reason, policy} when the budget is exhausted (main.go:114-150). It does not post a GitHub status check from this handler; a 403 to a webhook delivery blocks nothing on GitHub by itself.
neighbors on the map
- FNP Cost Optimization & Karpenter optimizing cloud infrastructure costs
- FNP Observability & Prometheus Metrics monitoring FNP systems
- Run Outcome Classification interpreting a History row's status pill
- Perch on Kubernetes: The Helm Chart as It Stands installing Perch in a fresh cluster