// Package metrics implements the three Prometheus counters the reconciler // exposes, without pulling the prometheus/client_golang module. The /metrics // handler prints the standard text exposition format. package metrics import ( "fmt" "io" "net/http" "sync/atomic" ) // Registry holds the reconciler's counters. Use New() to construct and share // one instance across the scheduler and the HTTP handler. type Registry struct { dirtyRows atomic.Int64 reconciliationAttempts atomic.Int64 reconciliationFailures atomic.Int64 reconciliationNoopHits atomic.Int64 } func New() *Registry { return &Registry{} } // SetDirtyRows sets the current pending-row count. Called at the top of each // tick, before any attempts land. func (r *Registry) SetDirtyRows(n int64) { r.dirtyRows.Store(n) } func (r *Registry) IncAttempts() { r.reconciliationAttempts.Add(1) } func (r *Registry) IncFailures() { r.reconciliationFailures.Add(1) } func (r *Registry) IncIdempotentNoopHits() { r.reconciliationNoopHits.Add(1) } // Snapshot returns a point-in-time copy; useful for tests. type Snapshot struct { DirtyRows int64 ReconciliationAttempts int64 ReconciliationFailures int64 IdempotentNoopHits int64 } func (r *Registry) Snapshot() Snapshot { return Snapshot{ DirtyRows: r.dirtyRows.Load(), ReconciliationAttempts: r.reconciliationAttempts.Load(), ReconciliationFailures: r.reconciliationFailures.Load(), IdempotentNoopHits: r.reconciliationNoopHits.Load(), } } // Handler returns an http.HandlerFunc that writes the Prometheus text format. func (r *Registry) Handler() http.HandlerFunc { return func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8") r.write(w) } } func (r *Registry) write(w io.Writer) { s := r.Snapshot() fmt.Fprintln(w, "# HELP attest_reconciler_dirty_rows_total Current count of per_diem_rates rows missing an attestation reference (gauge-style, overwritten each tick).") fmt.Fprintln(w, "# TYPE attest_reconciler_dirty_rows_total gauge") fmt.Fprintf(w, "attest_reconciler_dirty_rows_total %d\n", s.DirtyRows) fmt.Fprintln(w, "# HELP attest_reconciler_reconciliation_attempts_total Total pending rows the reconciler attempted to re-sign.") fmt.Fprintln(w, "# TYPE attest_reconciler_reconciliation_attempts_total counter") fmt.Fprintf(w, "attest_reconciler_reconciliation_attempts_total %d\n", s.ReconciliationAttempts) fmt.Fprintln(w, "# HELP attest_reconciler_reconciliation_failures_total Total pending-row attempts that returned an error from the signer or transparency log.") fmt.Fprintln(w, "# TYPE attest_reconciler_reconciliation_failures_total counter") fmt.Fprintf(w, "attest_reconciler_reconciliation_failures_total %d\n", s.ReconciliationFailures) fmt.Fprintln(w, "# HELP attest_reconciler_idempotent_noop_total Rows the reconciler re-signed where the TLog already had the entry (safe no-op; proves the idempotency contract works).") fmt.Fprintln(w, "# TYPE attest_reconciler_idempotent_noop_total counter") fmt.Fprintf(w, "attest_reconciler_idempotent_noop_total %d\n", s.IdempotentNoopHits) }