init monlet repo with stage 0-2 (docs, contract, agent MVP)
This commit is contained in:
152
agent/internal/metrics/metrics.go
Normal file
152
agent/internal/metrics/metrics.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
type Metrics struct {
|
||||
Registry *prometheus.Registry
|
||||
|
||||
CheckRuns *prometheus.CounterVec
|
||||
CheckSkipped *prometheus.CounterVec
|
||||
CheckDuration *prometheus.HistogramVec
|
||||
CheckStatus *prometheus.GaugeVec
|
||||
CheckExitCode *prometheus.GaugeVec
|
||||
CheckLastRun *prometheus.GaugeVec
|
||||
CheckLastSuccess *prometheus.GaugeVec
|
||||
CheckInterval *prometheus.GaugeVec
|
||||
ChecksConfigured prometheus.Gauge
|
||||
SpoolDepth prometheus.Gauge
|
||||
SpoolBytes prometheus.Gauge
|
||||
SendAttempts *prometheus.CounterVec
|
||||
SendFailures *prometheus.CounterVec
|
||||
EventsAccepted prometheus.Counter
|
||||
EventsDedup prometheus.Counter
|
||||
LastHeartbeat prometheus.Gauge
|
||||
BuildInfo *prometheus.GaugeVec
|
||||
}
|
||||
|
||||
// StatusCode maps a CheckResultEvent status string to a numeric gauge value.
|
||||
func StatusCode(status string) float64 {
|
||||
switch status {
|
||||
case "ok":
|
||||
return 0
|
||||
case "warning":
|
||||
return 1
|
||||
case "critical":
|
||||
return 2
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
func New() *Metrics {
|
||||
reg := prometheus.NewRegistry()
|
||||
m := &Metrics{Registry: reg}
|
||||
m.CheckRuns = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_check_runs_total",
|
||||
Help: "Number of check runs by id and status.",
|
||||
}, []string{"check_id", "status"})
|
||||
m.CheckSkipped = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_check_skipped_total",
|
||||
Help: "Number of ticks skipped due to overlap.",
|
||||
}, []string{"check_id"})
|
||||
m.CheckDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "monlet_agent_check_duration_seconds",
|
||||
Help: "Check execution duration.",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"check_id"})
|
||||
m.SpoolDepth = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_spool_events",
|
||||
Help: "Current spool depth in events.",
|
||||
})
|
||||
m.SpoolBytes = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_spool_bytes",
|
||||
Help: "Current spool size in bytes.",
|
||||
})
|
||||
m.SendAttempts = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_send_attempts_total",
|
||||
Help: "Outbound send attempts by kind.",
|
||||
}, []string{"kind"})
|
||||
m.SendFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_send_failures_total",
|
||||
Help: "Outbound send failures by kind.",
|
||||
}, []string{"kind"})
|
||||
m.EventsAccepted = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_events_accepted_total",
|
||||
Help: "Events accepted by the server.",
|
||||
})
|
||||
m.EventsDedup = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "monlet_agent_events_deduplicated_total",
|
||||
Help: "Events the server reported as duplicates.",
|
||||
})
|
||||
m.CheckStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_check_status",
|
||||
Help: "Last observed status per check: 0=ok,1=warning,2=critical,3=unknown.",
|
||||
}, []string{"check_id"})
|
||||
m.CheckExitCode = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_check_exit_code",
|
||||
Help: "Last exit code per check.",
|
||||
}, []string{"check_id"})
|
||||
m.CheckLastRun = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_check_last_run_timestamp_seconds",
|
||||
Help: "Unix timestamp of the last completed run per check.",
|
||||
}, []string{"check_id"})
|
||||
m.CheckLastSuccess = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_check_last_success_timestamp_seconds",
|
||||
Help: "Unix timestamp of the last ok run per check.",
|
||||
}, []string{"check_id"})
|
||||
m.CheckInterval = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_check_interval_seconds",
|
||||
Help: "Configured interval per check.",
|
||||
}, []string{"check_id"})
|
||||
m.ChecksConfigured = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_checks_configured",
|
||||
Help: "Number of checks configured.",
|
||||
})
|
||||
m.LastHeartbeat = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_last_heartbeat_timestamp_seconds",
|
||||
Help: "Unix timestamp of the last successful heartbeat ack.",
|
||||
})
|
||||
m.BuildInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "monlet_agent_build_info",
|
||||
Help: "Constant 1 with build labels.",
|
||||
}, []string{"version", "mode"})
|
||||
reg.MustRegister(m.CheckRuns, m.CheckSkipped, m.CheckDuration,
|
||||
m.CheckStatus, m.CheckExitCode, m.CheckLastRun, m.CheckLastSuccess,
|
||||
m.CheckInterval, m.ChecksConfigured,
|
||||
m.SpoolDepth, m.SpoolBytes,
|
||||
m.SendAttempts, m.SendFailures,
|
||||
m.EventsAccepted, m.EventsDedup,
|
||||
m.LastHeartbeat, m.BuildInfo)
|
||||
return m
|
||||
}
|
||||
|
||||
// Serve blocks until ctx is done; the listener is closed on shutdown.
|
||||
func (m *Metrics) Serve(ctx context.Context, addr string) error {
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", promhttp.HandlerFor(m.Registry, promhttp.HandlerOpts{}))
|
||||
srv := &http.Server{Addr: addr, Handler: mux, ReadHeaderTimeout: 5 * time.Second}
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
go func() { errCh <- srv.ListenAndServe() }()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
shutCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
_ = srv.Shutdown(shutCtx)
|
||||
return nil
|
||||
case err := <-errCh:
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user