github.com/cilium/cilium@v1.16.2/operator/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 controllerRuntimeMetrics "sigs.k8s.io/controller-runtime/pkg/metrics" 17 18 "github.com/cilium/cilium/pkg/hive" 19 "github.com/cilium/cilium/pkg/metrics" 20 "github.com/cilium/cilium/pkg/metrics/metric" 21 ) 22 23 // goCustomCollectorsRX tracks enabled go runtime metrics. 24 var goCustomCollectorsRX = regexp.MustCompile(`^/sched/latencies:seconds`) 25 26 type params struct { 27 cell.In 28 29 Logger logrus.FieldLogger 30 Lifecycle cell.Lifecycle 31 Shutdowner hive.Shutdowner 32 33 Cfg Config 34 SharedCfg SharedConfig 35 36 Metrics []metric.WithMetadata `group:"hive-metrics"` 37 } 38 39 type metricsManager struct { 40 logger logrus.FieldLogger 41 shutdowner hive.Shutdowner 42 43 server http.Server 44 45 metrics []metric.WithMetadata 46 } 47 48 func (mm *metricsManager) Start(ctx cell.HookContext) error { 49 mux := http.NewServeMux() 50 mux.Handle("/metrics", promhttp.HandlerFor(Registry, promhttp.HandlerOpts{})) 51 mm.server.Handler = mux 52 53 go func() { 54 mm.logger.WithField("address", mm.server.Addr).Info("Starting metrics server") 55 if err := mm.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { 56 mm.logger.WithError(err).Error("Unable to start metrics server") 57 mm.shutdowner.Shutdown() 58 } 59 }() 60 61 return nil 62 } 63 64 func (mm *metricsManager) Stop(ctx cell.HookContext) error { 65 if err := mm.server.Shutdown(ctx); err != nil { 66 mm.logger.WithError(err).Error("Shutdown operator metrics server failed") 67 return err 68 } 69 return nil 70 } 71 72 func registerMetricsManager(p params) { 73 if !p.SharedCfg.EnableMetrics { 74 return 75 } 76 77 mm := &metricsManager{ 78 logger: p.Logger, 79 shutdowner: p.Shutdowner, 80 server: http.Server{Addr: p.Cfg.OperatorPrometheusServeAddr}, 81 metrics: p.Metrics, 82 } 83 84 if p.SharedCfg.EnableGatewayAPI { 85 // Use the same Registry as controller-runtime, so that we don't need 86 // to expose multiple metrics endpoints or servers. 87 // 88 // Ideally, we should use our own Registry instance, but the metrics 89 // registration is done by init() functions, which are executed before 90 // this function is called. 91 Registry = controllerRuntimeMetrics.Registry 92 } else { 93 Registry = prometheus.NewPedanticRegistry() 94 Registry.MustRegister(collectors.NewGoCollector( 95 collectors.WithGoCollectorRuntimeMetrics( 96 collectors.GoRuntimeMetricsRule{Matcher: goCustomCollectorsRX}, 97 ))) 98 } 99 100 Registry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{Namespace: metrics.CiliumOperatorNamespace})) 101 102 for _, metric := range mm.metrics { 103 Registry.MustRegister(metric.(prometheus.Collector)) 104 } 105 106 metrics.InitOperatorMetrics() 107 Registry.MustRegister(metrics.ErrorsWarnings) 108 metrics.FlushLoggingMetrics() 109 110 p.Lifecycle.Append(mm) 111 }