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  }