package telemetry import ( "fmt" "net/http" "sync/atomic" "aigw/internal/billing" ) type Metrics struct { requests atomic.Uint64 failed atomic.Uint64 inFlight atomic.Int64 attempts atomic.Uint64 droppedUsage atomic.Uint64 settlementBacklog atomic.Int64 settlementSpool atomic.Int64 stripeRefundBacklog atomic.Int64 stripeUncollected atomic.Int64 stripeMismatches atomic.Int64 stripeWebhooks atomic.Int64 unmeteredSuccesses atomic.Int64 ready atomic.Int64 } func (m *Metrics) SetSettlementQueue(backlog int64, spool int) { m.settlementBacklog.Store(backlog) m.settlementSpool.Store(int64(spool)) } func (m *Metrics) SetReady(ready bool) { if ready { m.ready.Store(1) } else { m.ready.Store(0) } } func (m *Metrics) SetStripeOperations(status billing.OperationalStatus) { m.stripeRefundBacklog.Store(status.RefundBacklog) m.stripeUncollected.Store(status.UncollectedMicros) m.stripeMismatches.Store(status.ReconciliationMismatches) m.stripeWebhooks.Store(status.UnprocessedWebhooks) m.unmeteredSuccesses.Store(status.UnmeteredSuccesses) } func (m *Metrics) RequestStarted() { m.requests.Add(1) m.inFlight.Add(1) } func (m *Metrics) RequestFinished(success bool) { m.inFlight.Add(-1) if !success { m.failed.Add(1) } } func (m *Metrics) UpstreamAttempt() { m.attempts.Add(1) } func (m *Metrics) UsageDropped() { m.droppedUsage.Add(1) } func (m *Metrics) ServeHTTP(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/plain; version=0.0.4") fmt.Fprintf(w, "# TYPE aigw_requests_total counter\naigw_requests_total %d\n", m.requests.Load()) fmt.Fprintf(w, "# TYPE aigw_requests_failed_total counter\naigw_requests_failed_total %d\n", m.failed.Load()) fmt.Fprintf(w, "# TYPE aigw_requests_in_flight gauge\naigw_requests_in_flight %d\n", m.inFlight.Load()) fmt.Fprintf(w, "# TYPE aigw_upstream_attempts_total counter\naigw_upstream_attempts_total %d\n", m.attempts.Load()) fmt.Fprintf(w, "# TYPE aigw_usage_events_dropped_total counter\naigw_usage_events_dropped_total %d\n", m.droppedUsage.Load()) fmt.Fprintf(w, "# TYPE aigw_billing_settlement_backlog gauge\naigw_billing_settlement_backlog %d\n", m.settlementBacklog.Load()) fmt.Fprintf(w, "# TYPE aigw_billing_settlement_spool_records gauge\naigw_billing_settlement_spool_records %d\n", m.settlementSpool.Load()) fmt.Fprintf(w, "# TYPE aigw_stripe_refund_backlog gauge\naigw_stripe_refund_backlog %d\n", m.stripeRefundBacklog.Load()) fmt.Fprintf(w, "# TYPE aigw_billing_uncollected_micros gauge\naigw_billing_uncollected_micros %d\n", m.stripeUncollected.Load()) fmt.Fprintf(w, "# TYPE aigw_stripe_reconciliation_mismatches gauge\naigw_stripe_reconciliation_mismatches %d\n", m.stripeMismatches.Load()) fmt.Fprintf(w, "# TYPE aigw_stripe_webhook_backlog gauge\naigw_stripe_webhook_backlog %d\n", m.stripeWebhooks.Load()) fmt.Fprintf(w, "# TYPE aigw_billing_unmetered_successes gauge\naigw_billing_unmetered_successes %d\n", m.unmeteredSuccesses.Load()) fmt.Fprintf(w, "# TYPE aigw_ready gauge\naigw_ready %d\n", m.ready.Load()) }