github.com/cilium/cilium@v1.16.2/clustermesh-apiserver/metrics/metrics.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package metrics 5 6 import ( 7 "errors" 8 "net/http" 9 "regexp" 10 11 "github.com/cilium/hive/cell" 12 "github.com/prometheus/client_golang/prometheus" 13 "github.com/prometheus/client_golang/prometheus/collectors" 14 "github.com/prometheus/client_golang/prometheus/promhttp" 15 "github.com/sirupsen/logrus" 16 "github.com/spf13/pflag" 17 18 "github.com/cilium/cilium/pkg/metrics" 19 "github.com/cilium/cilium/pkg/metrics/metric" 20 "github.com/cilium/cilium/pkg/option" 21 ) 22 23 var Cell = cell.Module( 24 "metrics", 25 "Metrics", 26 27 cell.Config(MetricsConfig{}), 28 cell.Invoke(registerMetricsManager), 29 ) 30 31 type MetricsConfig struct { 32 // PrometheusServeAddr IP:Port on which to serve prometheus metrics (pass ":Port" to bind on all interfaces, "" is off) 33 PrometheusServeAddr string 34 } 35 36 func (def MetricsConfig) Flags(flags *pflag.FlagSet) { 37 flags.String(option.PrometheusServeAddr, def.PrometheusServeAddr, "Address to serve Prometheus metrics") 38 } 39 40 type metricsManager struct { 41 logger logrus.FieldLogger 42 registry *prometheus.Registry 43 server http.Server 44 45 metrics []metric.WithMetadata 46 } 47 48 type params struct { 49 cell.In 50 Logger logrus.FieldLogger 51 52 MetricsConfig 53 Metrics []metric.WithMetadata `group:"hive-metrics"` 54 } 55 56 func registerMetricsManager(lc cell.Lifecycle, params params) error { 57 manager := metricsManager{ 58 logger: params.Logger, 59 registry: prometheus.NewPedanticRegistry(), 60 server: http.Server{Addr: params.PrometheusServeAddr}, 61 metrics: params.Metrics, 62 } 63 64 if params.PrometheusServeAddr != "" { 65 lc.Append(&manager) 66 } else { 67 manager.logger.Info("Prometheus metrics are disabled") 68 } 69 70 return nil 71 } 72 73 func (mm *metricsManager) Start(cell.HookContext) error { 74 mm.logger.Info("Registering metrics") 75 76 mm.registry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) 77 mm.registry.MustRegister(collectors.NewGoCollector( 78 collectors.WithGoCollectorRuntimeMetrics( 79 collectors.GoRuntimeMetricsRule{Matcher: regexp.MustCompile(`^/sched/latencies:seconds`)}, 80 ), 81 )) 82 // Constructing the legacy metrics and register them at the metrics global variable. 83 // This is a hack until we can unify this metrics manager with the metrics.Registry. 84 metrics.NewLegacyMetrics() 85 mm.registry.MustRegister( 86 metrics.VersionMetric, 87 metrics.KVStoreOperationsDuration, 88 metrics.KVStoreEventsQueueDuration, 89 metrics.KVStoreQuorumErrors, 90 metrics.APILimiterProcessingDuration, 91 metrics.APILimiterWaitDuration, 92 metrics.APILimiterRequestsInFlight, 93 metrics.APILimiterRateLimit, 94 metrics.APILimiterProcessedRequests, 95 ) 96 97 for _, metric := range mm.metrics { 98 mm.registry.MustRegister(metric.(prometheus.Collector)) 99 } 100 101 mux := http.NewServeMux() 102 mux.Handle("/metrics", promhttp.HandlerFor(mm.registry, promhttp.HandlerOpts{})) 103 mm.server.Handler = mux 104 105 go func() { 106 mm.logger.WithField("address", mm.server.Addr).Info("Starting metrics server") 107 if err := mm.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { 108 mm.logger.WithError(err).Fatal("Unable to start metrics server") 109 } 110 }() 111 112 return nil 113 } 114 115 func (mm *metricsManager) Stop(ctx cell.HookContext) error { 116 mm.logger.Info("Stopping metrics server") 117 118 if err := mm.server.Shutdown(ctx); err != nil { 119 mm.logger.WithError(err).Error("Shutdown metrics server failed") 120 return err 121 } 122 123 return nil 124 }