Files
sendico/api/fx/ingestor/internal/ingestor/metrics.go
Stephan D 62a6631b9a
All checks were successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
service backend
2025-11-07 18:35:26 +01:00

85 lines
2.6 KiB
Go

package ingestor
import (
"sync"
"time"
"github.com/tech/sendico/fx/ingestor/internal/config"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
type serviceMetrics struct {
pollDuration *prometheus.HistogramVec
pollTotal *prometheus.CounterVec
pairDuration *prometheus.HistogramVec
pairTotal *prometheus.CounterVec
pairLastUpdate *prometheus.GaugeVec
}
var (
metricsOnce sync.Once
globalMetricsRef *serviceMetrics
)
func getServiceMetrics() *serviceMetrics {
metricsOnce.Do(func() {
reg := prometheus.DefaultRegisterer
globalMetricsRef = &serviceMetrics{
pollDuration: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{
Name: "fx_ingestor_poll_duration_seconds",
Help: "Duration of a polling cycle.",
Buckets: prometheus.DefBuckets,
}, []string{"result"}),
pollTotal: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
Name: "fx_ingestor_poll_total",
Help: "Total polling cycles executed.",
}, []string{"result"}),
pairDuration: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{
Name: "fx_ingestor_pair_duration_seconds",
Help: "Duration of individual pair ingestion.",
Buckets: prometheus.DefBuckets,
}, []string{"source", "provider", "symbol", "result"}),
pairTotal: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
Name: "fx_ingestor_pair_total",
Help: "Total ingestion attempts per pair.",
}, []string{"source", "provider", "symbol", "result"}),
pairLastUpdate: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
Name: "fx_ingestor_pair_last_success_unix",
Help: "Unix timestamp of the last successful ingestion per pair.",
}, []string{"source", "provider", "symbol"}),
}
})
return globalMetricsRef
}
func (m *serviceMetrics) observePoll(duration time.Duration, err error) {
if m == nil {
return
}
result := labelForError(err)
m.pollDuration.WithLabelValues(result).Observe(duration.Seconds())
m.pollTotal.WithLabelValues(result).Inc()
}
func (m *serviceMetrics) observePair(pair config.Pair, duration time.Duration, err error) {
if m == nil {
return
}
result := labelForError(err)
labels := []string{pair.Source.String(), pair.Provider, pair.Symbol, result}
m.pairDuration.WithLabelValues(labels...).Observe(duration.Seconds())
m.pairTotal.WithLabelValues(labels...).Inc()
if err == nil {
m.pairLastUpdate.WithLabelValues(pair.Source.String(), pair.Provider, pair.Symbol).
Set(float64(time.Now().Unix()))
}
}
func labelForError(err error) string {
if err != nil {
return "error"
}
return "success"
}