diff --git a/pkg/infra/metrics/service.go b/pkg/infra/metrics/service.go index 13767508a484d..f62ad23f2a8ac 100644 --- a/pkg/infra/metrics/service.go +++ b/pkg/infra/metrics/service.go @@ -4,6 +4,7 @@ import ( "context" "errors" "regexp" + "sort" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" @@ -68,8 +69,10 @@ func ProvideRegisterer(cfg *setting.Cfg) prometheus.Registerer { func ProvideGatherer(cfg *setting.Cfg) prometheus.Gatherer { if cfg.IsFeatureToggleEnabled(featuremgmt.FlagGrafanaAPIServer) { - return newAddPrefixWrapper(legacyregistry.DefaultGatherer) + k8sGatherer := newAddPrefixWrapper(legacyregistry.DefaultGatherer) + return newMultiRegistry(k8sGatherer, prometheus.DefaultGatherer) } + return prometheus.DefaultGatherer } @@ -122,3 +125,40 @@ func (g *addPrefixWrapper) Gather() ([]*dto.MetricFamily, error) { return mf, nil } + +var _ prometheus.Gatherer = (*multiRegistry)(nil) + +type multiRegistry struct { + gatherers []prometheus.Gatherer +} + +func newMultiRegistry(gatherers ...prometheus.Gatherer) *multiRegistry { + return &multiRegistry{ + gatherers: gatherers, + } +} + +func (r *multiRegistry) Gather() (mfs []*dto.MetricFamily, err error) { + errs := prometheus.MultiError{} + + names := make(map[string]struct{}) + for _, g := range r.gatherers { + mf, err := g.Gather() + errs.Append(err) + + for i := 0; i < len(mf); i++ { + m := mf[i] + // prevent duplicate metric names + if _, exists := names[*m.Name]; !exists { + names[*m.Name] = struct{}{} + mfs = append(mfs, m) + } + } + } + + sort.Slice(mfs, func(i, j int) bool { + return *mfs[i].Name < *mfs[j].Name + }) + + return mfs, errs.MaybeUnwrap() +}