package gateway import ( "errors" "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/tech/sendico/pkg/merrors" ) var ( metricsOnce sync.Once rpcLatency *prometheus.HistogramVec rpcStatus *prometheus.CounterVec ) func initMetrics() { metricsOnce.Do(func() { rpcLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "sendico", Subsystem: "mntx_gateway", Name: "rpc_latency_seconds", Help: "Latency distribution for Monetix gateway RPC handlers.", Buckets: prometheus.DefBuckets, }, []string{"method"}) rpcStatus = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "sendico", Subsystem: "mntx_gateway", Name: "rpc_requests_total", Help: "Total number of RPC invocations grouped by method and status.", }, []string{"method", "status"}) }) } func observeRPC(method string, err error, duration time.Duration) { if rpcLatency != nil { rpcLatency.WithLabelValues(method).Observe(duration.Seconds()) } if rpcStatus != nil { rpcStatus.WithLabelValues(method, statusLabel(err)).Inc() } } func statusLabel(err error) string { switch { case err == nil: return "ok" case errors.Is(err, merrors.ErrInvalidArg): return "invalid_argument" case errors.Is(err, merrors.ErrNoData): return "not_found" case errors.Is(err, merrors.ErrDataConflict): return "conflict" case errors.Is(err, merrors.ErrAccessDenied): return "denied" case errors.Is(err, merrors.ErrInternal): return "internal" default: return "error" } }