Init dualwriter metrics (#89003)

* Pass prometheus registerer to the dual writer

* Fix tests

* Remove unused var

* Fix tests

* Uncomment test

* Remove leading line

* Fix tests. Reuse registerer if there's already one

* Lint

* Improve double registering logic

* Rebase main
This commit is contained in:
Leonor Oliveira
2024-06-14 10:01:49 +01:00
committed by GitHub
parent e3da5ed35d
commit fd44f2ee4f
28 changed files with 114 additions and 60 deletions

View File

@@ -4,6 +4,7 @@ import (
"net/http" "net/http"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
@@ -29,6 +30,7 @@ type APIGroupBuilder interface {
codecs serializer.CodecFactory, codecs serializer.CodecFactory,
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
desiredMode grafanarest.DualWriterMode, desiredMode grafanarest.DualWriterMode,
reg prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) ) (*genericapiserver.APIGroupInfo, error)
// Get OpenAPI definitions // Get OpenAPI definitions

View File

@@ -25,6 +25,7 @@ import (
"github.com/grafana/grafana/pkg/apiserver/endpoints/filters" "github.com/grafana/grafana/pkg/apiserver/endpoints/filters"
"github.com/grafana/grafana/pkg/services/apiserver/options" "github.com/grafana/grafana/pkg/services/apiserver/options"
"github.com/prometheus/client_golang/prometheus"
) )
// TODO: this is a temporary hack to make rest.Connecter work with resource level routes // TODO: this is a temporary hack to make rest.Connecter work with resource level routes
@@ -128,6 +129,7 @@ func InstallAPIs(
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
builders []APIGroupBuilder, builders []APIGroupBuilder,
storageOpts *options.StorageOptions, storageOpts *options.StorageOptions,
reg prometheus.Registerer,
) error { ) error {
// dual writing is only enabled when the storage type is not legacy. // dual writing is only enabled when the storage type is not legacy.
// this is needed to support setting a default RESTOptionsGetter for new APIs that don't // this is needed to support setting a default RESTOptionsGetter for new APIs that don't
@@ -136,7 +138,7 @@ func InstallAPIs(
for _, b := range builders { for _, b := range builders {
mode := b.GetDesiredDualWriterMode(dualWriteEnabled, storageOpts.DualWriterDesiredModes) mode := b.GetDesiredDualWriterMode(dualWriteEnabled, storageOpts.DualWriterDesiredModes)
g, err := b.GetAPIGroupInfo(scheme, codecs, optsGetter, mode) g, err := b.GetAPIGroupInfo(scheme, codecs, optsGetter, mode, reg)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/prometheus/client_golang/prometheus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
@@ -95,25 +96,28 @@ const (
Mode4 Mode4
) )
// TODO: make this function private as there should only be one public way of setting the dual writing mode
// NewDualWriter returns a new DualWriter. // NewDualWriter returns a new DualWriter.
func NewDualWriter(mode DualWriterMode, legacy LegacyStorage, storage Storage) DualWriter { func NewDualWriter(mode DualWriterMode, legacy LegacyStorage, storage Storage, reg prometheus.Registerer) DualWriter {
metrics := &dualWriterMetrics{}
metrics.init(reg)
switch mode { switch mode {
// It is not possible to initialize a mode 0 dual writer. Mode 0 represents // It is not possible to initialize a mode 0 dual writer. Mode 0 represents
// writing to legacy storage without `unifiedStorage` enabled. // writing to legacy storage without `unifiedStorage` enabled.
case Mode1: case Mode1:
// read and write only from legacy storage // read and write only from legacy storage
return newDualWriterMode1(legacy, storage) return newDualWriterMode1(legacy, storage, metrics)
case Mode2: case Mode2:
// write to both, read from storage but use legacy as backup // write to both, read from storage but use legacy as backup
return newDualWriterMode2(legacy, storage) return newDualWriterMode2(legacy, storage, metrics)
case Mode3: case Mode3:
// write to both, read from storage only // write to both, read from storage only
return newDualWriterMode3(legacy, storage) return newDualWriterMode3(legacy, storage, metrics)
case Mode4: case Mode4:
// read and write only from storage // read and write only from storage
return newDualWriterMode4(legacy, storage) return newDualWriterMode4(legacy, storage, metrics)
default: default:
return newDualWriterMode1(legacy, storage) return newDualWriterMode1(legacy, storage, metrics)
} }
} }
@@ -142,6 +146,7 @@ func SetDualWritingMode(
storage Storage, storage Storage,
entity string, entity string,
desiredMode DualWriterMode, desiredMode DualWriterMode,
reg prometheus.Registerer,
) (DualWriter, error) { ) (DualWriter, error) {
toMode := map[string]DualWriterMode{ toMode := map[string]DualWriterMode{
// It is not possible to initialize a mode 0 dual writer. Mode 0 represents // It is not possible to initialize a mode 0 dual writer. Mode 0 represents
@@ -200,5 +205,5 @@ func SetDualWritingMode(
// #TODO add support for other combinations of desired and current modes // #TODO add support for other combinations of desired and current modes
return NewDualWriter(currentMode, legacy, storage), nil return NewDualWriter(currentMode, legacy, storage, reg), nil
} }

View File

@@ -24,10 +24,8 @@ const mode1Str = "1"
// NewDualWriterMode1 returns a new DualWriter in mode 1. // NewDualWriterMode1 returns a new DualWriter in mode 1.
// Mode 1 represents writing to and reading from LegacyStorage. // Mode 1 represents writing to and reading from LegacyStorage.
func newDualWriterMode1(legacy LegacyStorage, storage Storage) *DualWriterMode1 { func newDualWriterMode1(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode1 {
metrics := &dualWriterMetrics{} return &DualWriterMode1{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode1"), dualWriterMetrics: dwm}
metrics.init()
return &DualWriterMode1{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode1"), dualWriterMetrics: metrics}
} }
// Mode returns the mode of the dual writer. // Mode returns the mode of the dual writer.

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
@@ -22,6 +23,8 @@ var failingObj = &example.Pod{TypeMeta: metav1.TypeMeta{Kind: "foo"}, ObjectMeta
var exampleList = &example.PodList{TypeMeta: metav1.TypeMeta{Kind: "foo"}, ListMeta: metav1.ListMeta{}, Items: []example.Pod{*exampleObj}} var exampleList = &example.PodList{TypeMeta: metav1.TypeMeta{Kind: "foo"}, ListMeta: metav1.ListMeta{}, Items: []example.Pod{*exampleObj}}
var anotherList = &example.PodList{Items: []example.Pod{*anotherObj}} var anotherList = &example.PodList{Items: []example.Pod{*anotherObj}}
var p = prometheus.NewRegistry()
func TestMode1_Create(t *testing.T) { func TestMode1_Create(t *testing.T) {
type testCase struct { type testCase struct {
input runtime.Object input runtime.Object
@@ -68,7 +71,7 @@ func TestMode1_Create(t *testing.T) {
tt.setupStorageFn(m) tt.setupStorageFn(m)
} }
dw := NewDualWriter(Mode1, ls, us) dw := NewDualWriter(Mode1, ls, us, p)
obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{}) obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{})
@@ -131,7 +134,8 @@ func TestMode1_Get(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode1, ls, us) p := prometheus.NewRegistry()
dw := NewDualWriter(Mode1, ls, us, p)
obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{})
@@ -182,7 +186,7 @@ func TestMode1_List(t *testing.T) {
tt.setupStorageFn(m) tt.setupStorageFn(m)
} }
dw := NewDualWriter(Mode1, ls, us) dw := NewDualWriter(Mode1, ls, us, p)
_, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) _, err := dw.List(context.Background(), &metainternalversion.ListOptions{})
@@ -237,7 +241,7 @@ func TestMode1_Delete(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode1, ls, us) dw := NewDualWriter(Mode1, ls, us, p)
obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{})
@@ -296,7 +300,7 @@ func TestMode1_DeleteCollection(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode1, ls, us) dw := NewDualWriter(Mode1, ls, us, p)
obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{})
@@ -372,7 +376,7 @@ func TestMode1_Update(t *testing.T) {
tt.setupGetFn(m, tt.input) tt.setupGetFn(m, tt.input)
} }
dw := NewDualWriter(Mode1, ls, us) dw := NewDualWriter(Mode1, ls, us, p)
obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{})

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/grafana/grafana/pkg/apimachinery/utils"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
@@ -13,8 +14,6 @@ import (
"k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/selection"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"github.com/grafana/grafana/pkg/apimachinery/utils"
) )
type DualWriterMode2 struct { type DualWriterMode2 struct {
@@ -28,10 +27,8 @@ const mode2Str = "2"
// NewDualWriterMode2 returns a new DualWriter in mode 2. // NewDualWriterMode2 returns a new DualWriter in mode 2.
// Mode 2 represents writing to LegacyStorage and Storage and reading from LegacyStorage. // Mode 2 represents writing to LegacyStorage and Storage and reading from LegacyStorage.
func newDualWriterMode2(legacy LegacyStorage, storage Storage) *DualWriterMode2 { func newDualWriterMode2(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode2 {
metrics := &dualWriterMetrics{} return &DualWriterMode2{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode2"), dualWriterMetrics: dwm}
metrics.init()
return &DualWriterMode2{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode2"), dualWriterMetrics: metrics}
} }
// Mode returns the mode of the dual writer. // Mode returns the mode of the dual writer.

View File

@@ -67,7 +67,7 @@ func TestMode2_Create(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, err := dw.Create(context.Background(), tt.input, createFn, &metav1.CreateOptions{}) obj, err := dw.Create(context.Background(), tt.input, createFn, &metav1.CreateOptions{})
@@ -143,7 +143,7 @@ func TestMode2_Get(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{})
@@ -196,7 +196,7 @@ func TestMode2_List(t *testing.T) {
tt.setupStorageFn(m) tt.setupStorageFn(m)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) obj, err := dw.List(context.Background(), &metainternalversion.ListOptions{})
@@ -289,7 +289,7 @@ func TestMode2_Delete(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, _, err := dw.Delete(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) obj, _, err := dw.Delete(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{})
@@ -361,7 +361,7 @@ func TestMode2_DeleteCollection(t *testing.T) {
tt.setupStorageFn(m) tt.setupStorageFn(m)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: tt.input}}, &metainternalversion.ListOptions{}) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: tt.input}}, &metainternalversion.ListOptions{})
@@ -469,7 +469,7 @@ func TestMode2_Update(t *testing.T) {
tt.setupStorageFn(m, tt.input) tt.setupStorageFn(m, tt.input)
} }
dw := NewDualWriter(Mode2, ls, us) dw := NewDualWriter(Mode2, ls, us, p)
obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{})

View File

@@ -20,10 +20,8 @@ type DualWriterMode3 struct {
// newDualWriterMode3 returns a new DualWriter in mode 3. // newDualWriterMode3 returns a new DualWriter in mode 3.
// Mode 3 represents writing to LegacyStorage and Storage and reading from Storage. // Mode 3 represents writing to LegacyStorage and Storage and reading from Storage.
func newDualWriterMode3(legacy LegacyStorage, storage Storage) *DualWriterMode3 { func newDualWriterMode3(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode3 {
metrics := &dualWriterMetrics{} return &DualWriterMode3{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode3"), dualWriterMetrics: dwm}
metrics.init()
return &DualWriterMode3{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode3"), dualWriterMetrics: metrics}
} }
// Mode returns the mode of the dual writer. // Mode returns the mode of the dual writer.

View File

@@ -19,10 +19,8 @@ type DualWriterMode4 struct {
// newDualWriterMode4 returns a new DualWriter in mode 4. // newDualWriterMode4 returns a new DualWriter in mode 4.
// Mode 4 represents writing and reading from Storage. // Mode 4 represents writing and reading from Storage.
func newDualWriterMode4(legacy LegacyStorage, storage Storage) *DualWriterMode4 { func newDualWriterMode4(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode4 {
metrics := &dualWriterMetrics{} return &DualWriterMode4{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode4"), dualWriterMetrics: dwm}
metrics.init()
return &DualWriterMode4{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode4"), dualWriterMetrics: metrics}
} }
// Mode returns the mode of the dual writer. // Mode returns the mode of the dual writer.

View File

@@ -7,6 +7,7 @@ import (
playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
"github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
) )
@@ -45,7 +46,8 @@ func TestSetDualWritingMode(t *testing.T) {
kvStore := kvstore.WithNamespace(kvstore.NewFakeKVStore(), 0, "storage.dualwriting."+tt.stackID) kvStore := kvstore.WithNamespace(kvstore.NewFakeKVStore(), 0, "storage.dualwriting."+tt.stackID)
dw, err := SetDualWritingMode(context.Background(), kvStore, ls, us, playlist.GROUPRESOURCE, tt.desiredMode) p := prometheus.NewRegistry()
dw, err := SetDualWritingMode(context.Background(), kvStore, ls, us, playlist.GROUPRESOURCE, tt.desiredMode, p)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.expectedMode, dw.Mode()) assert.Equal(t, tt.expectedMode, dw.Mode())

View File

@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"k8s.io/klog/v2"
) )
type dualWriterMetrics struct { type dualWriterMetrics struct {
@@ -37,10 +38,17 @@ var DualWriterOutcome = prometheus.NewHistogramVec(prometheus.HistogramOpts{
NativeHistogramBucketFactor: 1.1, NativeHistogramBucketFactor: 1.1,
}, []string{"mode", "name", "method"}) }, []string{"mode", "name", "method"})
func (m *dualWriterMetrics) init() { func (m *dualWriterMetrics) init(reg prometheus.Registerer) {
log := klog.NewKlogr()
m.legacy = DualWriterLegacyDuration m.legacy = DualWriterLegacyDuration
m.storage = DualWriterStorageDuration m.storage = DualWriterStorageDuration
m.outcome = DualWriterOutcome m.outcome = DualWriterOutcome
errLegacy := reg.Register(m.legacy)
errStorage := reg.Register(m.storage)
errOutcome := reg.Register(m.outcome)
if errLegacy != nil || errStorage != nil || errOutcome != nil {
log.Info("cloud migration metrics already registered")
}
} }
func (m *dualWriterMetrics) recordLegacyDuration(isError bool, mode string, name string, method string, startFrom time.Time) { func (m *dualWriterMetrics) recordLegacyDuration(isError bool, mode string, name string, method string, startFrom time.Time) {

View File

@@ -165,7 +165,7 @@ func (o *APIServerOptions) RunAPIServer(config *genericapiserver.RecommendedConf
// Install the API Group+version // Install the API Group+version
// #TODO figure out how to configure storage type in o.Options.StorageOptions // #TODO figure out how to configure storage type in o.Options.StorageOptions
err = builder.InstallAPIs(grafanaAPIServer.Scheme, grafanaAPIServer.Codecs, server, config.RESTOptionsGetter, o.builders, o.Options.StorageOptions) err = builder.InstallAPIs(grafanaAPIServer.Scheme, grafanaAPIServer.Codecs, server, config.RESTOptionsGetter, o.builders, o.Options.StorageOptions, o.Options.MetricsOptions.MetricsRegisterer)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -25,6 +25,7 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*DashboardsAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*DashboardsAPIBuilder)(nil)
@@ -49,6 +50,7 @@ func RegisterAPIService(cfg *setting.Cfg, features featuremgmt.FeatureToggles,
accessControl accesscontrol.AccessControl, accessControl accesscontrol.AccessControl,
provisioning provisioning.ProvisioningService, provisioning provisioning.ProvisioningService,
dashStore dashboards.Store, dashStore dashboards.Store,
reg prometheus.Registerer,
sql db.DB, sql db.DB,
) *DashboardsAPIBuilder { ) *DashboardsAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
@@ -115,6 +117,7 @@ func (b *DashboardsAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
desiredMode grafanarest.DualWriterMode, desiredMode grafanarest.DualWriterMode,
reg prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs)
@@ -145,7 +148,7 @@ func (b *DashboardsAPIBuilder) GetAPIGroupInfo(
if err := store.CompleteWithOptions(options); err != nil { if err := store.CompleteWithOptions(options); err != nil {
return nil, err return nil, err
} }
storage[resourceInfo.StoragePath()] = grafanarest.NewDualWriter(grafanarest.Mode1, legacyStore, store) storage[resourceInfo.StoragePath()] = grafanarest.NewDualWriter(grafanarest.Mode1, legacyStore, store, reg)
} }
// Summary // Summary

View File

@@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@@ -71,6 +72,7 @@ func RegisterAPIService(
cfg *setting.Cfg, cfg *setting.Cfg,
features featuremgmt.FeatureToggles, features featuremgmt.FeatureToggles,
sql db.DB, sql db.DB,
reg prometheus.Registerer,
) *SnapshotsAPIBuilder { ) *SnapshotsAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
return nil // skip registration unless opting into experimental apis return nil // skip registration unless opting into experimental apis
@@ -129,6 +131,7 @@ func (b *SnapshotsAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(dashboardsnapshot.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(dashboardsnapshot.GROUP, scheme, metav1.ParameterCodec, codecs)
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/prometheus/client_golang/prometheus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@@ -56,6 +57,7 @@ func RegisterAPIService(
contextProvider PluginContextWrapper, contextProvider PluginContextWrapper,
pluginStore pluginstore.Store, pluginStore pluginstore.Store,
accessControl accesscontrol.AccessControl, accessControl accesscontrol.AccessControl,
reg prometheus.Registerer,
) (*DataSourceAPIBuilder, error) { ) (*DataSourceAPIBuilder, error) {
// This requires devmode! // This requires devmode!
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
@@ -205,6 +207,7 @@ func (b *DataSourceAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
_ generic.RESTOptionsGetter, _ generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}

View File

@@ -25,6 +25,7 @@ import (
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/appcontext"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*TestingAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*TestingAPIBuilder)(nil)
@@ -41,7 +42,7 @@ func NewTestingAPIBuilder() *TestingAPIBuilder {
} }
} }
func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar) *TestingAPIBuilder { func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, reg prometheus.Registerer) *TestingAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
return nil // skip registration unless opting into experimental apis return nil // skip registration unless opting into experimental apis
} }
@@ -92,6 +93,7 @@ func (b *TestingAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
_ generic.RESTOptionsGetter, _ generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
b.codecs = codecs b.codecs = codecs
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(b.gv.Group, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(b.gv.Group, scheme, metav1.ParameterCodec, codecs)

View File

@@ -19,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*FeatureFlagAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*FeatureFlagAPIBuilder)(nil)
@@ -40,6 +41,7 @@ func RegisterAPIService(features *featuremgmt.FeatureManager,
accessControl accesscontrol.AccessControl, accessControl accesscontrol.AccessControl,
apiregistration builder.APIRegistrar, apiregistration builder.APIRegistrar,
cfg *setting.Cfg, cfg *setting.Cfg,
registerer prometheus.Registerer,
) *FeatureFlagAPIBuilder { ) *FeatureFlagAPIBuilder {
builder := NewFeatureFlagAPIBuilder(features, accessControl, cfg) builder := NewFeatureFlagAPIBuilder(features, accessControl, cfg)
apiregistration.RegisterAPI(builder) apiregistration.RegisterAPI(builder)
@@ -89,6 +91,7 @@ func (b *FeatureFlagAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
_ generic.RESTOptionsGetter, _ generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs)

View File

@@ -27,6 +27,7 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*FolderAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*FolderAPIBuilder)(nil)
@@ -47,6 +48,7 @@ func RegisterAPIService(cfg *setting.Cfg,
apiregistration builder.APIRegistrar, apiregistration builder.APIRegistrar,
folderSvc folder.Service, folderSvc folder.Service,
accessControl accesscontrol.AccessControl, accessControl accesscontrol.AccessControl,
registerer prometheus.Registerer,
) *FolderAPIBuilder { ) *FolderAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
return nil // skip registration unless opting into experimental apis return nil // skip registration unless opting into experimental apis
@@ -106,6 +108,7 @@ func (b *FolderAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
desiredMode grafanarest.DualWriterMode, desiredMode grafanarest.DualWriterMode,
reg prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs)
@@ -145,7 +148,7 @@ func (b *FolderAPIBuilder) GetAPIGroupInfo(
if err != nil { if err != nil {
return nil, err return nil, err
} }
storage[resourceInfo.StoragePath()] = grafanarest.NewDualWriter(grafanarest.Mode1, legacyStore, store) storage[resourceInfo.StoragePath()] = grafanarest.NewDualWriter(grafanarest.Mode1, legacyStore, store, reg)
} }
apiGroupInfo.VersionedResourcesStorageMap[v0alpha1.VERSION] = storage apiGroupInfo.VersionedResourcesStorageMap[v0alpha1.VERSION] = storage

View File

@@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/apiserver/builder" "github.com/grafana/grafana/pkg/apiserver/builder"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*PeakQAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*PeakQAPIBuilder)(nil)
@@ -28,7 +29,7 @@ func NewPeakQAPIBuilder() *PeakQAPIBuilder {
return &PeakQAPIBuilder{} return &PeakQAPIBuilder{}
} }
func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar) *PeakQAPIBuilder { func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, reg prometheus.Registerer) *PeakQAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
return nil // skip registration unless opting into experimental apis return nil // skip registration unless opting into experimental apis
} }
@@ -73,6 +74,7 @@ func (b *PeakQAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, codecs serializer.CodecFactory,
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, // dual write desired mode (not relevant) _ grafanarest.DualWriterMode, // dual write desired mode (not relevant)
_ prometheus.Registerer, // prometheus registerer
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(peakq.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(peakq.GROUP, scheme, metav1.ParameterCodec, codecs)

View File

@@ -23,6 +23,7 @@ import (
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils" gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
playlistsvc "github.com/grafana/grafana/pkg/services/playlist" playlistsvc "github.com/grafana/grafana/pkg/services/playlist"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*PlaylistAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*PlaylistAPIBuilder)(nil)
@@ -39,12 +40,14 @@ func RegisterAPIService(p playlistsvc.Service,
apiregistration builder.APIRegistrar, apiregistration builder.APIRegistrar,
cfg *setting.Cfg, cfg *setting.Cfg,
kvStore kvstore.KVStore, kvStore kvstore.KVStore,
registerer prometheus.Registerer,
) *PlaylistAPIBuilder { ) *PlaylistAPIBuilder {
builder := &PlaylistAPIBuilder{ builder := &PlaylistAPIBuilder{
service: p, service: p,
namespacer: request.GetNamespaceMapper(cfg), namespacer: request.GetNamespaceMapper(cfg),
gv: playlist.PlaylistResourceInfo.GroupVersion(), gv: playlist.PlaylistResourceInfo.GroupVersion(),
kvStore: kvstore.WithNamespace(kvStore, 0, "storage.dualwriting"), kvStore: kvstore.WithNamespace(kvStore, 0, "storage.dualwriting"),
// register: newMetrics(registerer),
} }
apiregistration.RegisterAPI(builder) apiregistration.RegisterAPI(builder)
return builder return builder
@@ -94,6 +97,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
desiredMode grafanarest.DualWriterMode, desiredMode grafanarest.DualWriterMode,
reg prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(playlist.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(playlist.GROUP, scheme, metav1.ParameterCodec, codecs)
storage := map[string]rest.Storage{} storage := map[string]rest.Storage{}
@@ -133,7 +137,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
return nil, err return nil, err
} }
dualWriter, err := grafanarest.SetDualWritingMode(context.Background(), b.kvStore, legacyStore, store, playlist.GROUPRESOURCE, desiredMode) dualWriter, err := grafanarest.SetDualWritingMode(context.Background(), b.kvStore, legacyStore, store, playlist.GROUPRESOURCE, desiredMode, reg)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -9,15 +9,15 @@ const (
metricsNamespace = "grafana" metricsNamespace = "grafana"
) )
type metrics struct { type queryMetrics struct {
dsRequests *prometheus.CounterVec dsRequests *prometheus.CounterVec
// older metric // older metric
expressionsQuerySummary *prometheus.SummaryVec expressionsQuerySummary *prometheus.SummaryVec
} }
func newMetrics(reg prometheus.Registerer) *metrics { func newQueryMetrics(reg prometheus.Registerer) *queryMetrics {
m := &metrics{ m := &queryMetrics{
dsRequests: prometheus.NewCounterVec(prometheus.CounterOpts{ dsRequests: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: metricsNamespace, Namespace: metricsNamespace,
Subsystem: metricsSubSystem, Subsystem: metricsSubSystem,

View File

@@ -42,7 +42,7 @@ type QueryAPIBuilder struct {
features featuremgmt.FeatureToggles features featuremgmt.FeatureToggles
tracer tracing.Tracer tracer tracing.Tracer
metrics *metrics metrics *queryMetrics
parser *queryParser parser *queryParser
client DataSourceClientSupplier client DataSourceClientSupplier
registry query.DataSourceApiServerRegistry registry query.DataSourceApiServerRegistry
@@ -81,7 +81,7 @@ func NewQueryAPIBuilder(features featuremgmt.FeatureToggles,
client: client, client: client,
registry: registry, registry: registry,
parser: newQueryParser(reader, legacy, tracer), parser: newQueryParser(reader, legacy, tracer),
metrics: newMetrics(registerer), metrics: newQueryMetrics(registerer),
tracer: tracer, tracer: tracer,
features: features, features: features,
queryTypes: queryTypes, queryTypes: queryTypes,
@@ -151,6 +151,7 @@ func (b *QueryAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, // pointer? codecs serializer.CodecFactory, // pointer?
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
gv := query.SchemeGroupVersion gv := query.SchemeGroupVersion
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(gv.Group, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(gv.Group, scheme, metav1.ParameterCodec, codecs)

View File

@@ -19,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/apiserver/builder" "github.com/grafana/grafana/pkg/apiserver/builder"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*ScopeAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*ScopeAPIBuilder)(nil)
@@ -30,7 +31,7 @@ func NewScopeAPIBuilder() *ScopeAPIBuilder {
return &ScopeAPIBuilder{} return &ScopeAPIBuilder{}
} }
func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar) *ScopeAPIBuilder { func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, reg prometheus.Registerer) *ScopeAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
return nil // skip registration unless opting into experimental apis return nil // skip registration unless opting into experimental apis
} }
@@ -121,6 +122,7 @@ func (b *ScopeAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, codecs serializer.CodecFactory,
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, // dual write desired mode (not relevant) _ grafanarest.DualWriterMode, // dual write desired mode (not relevant)
_ prometheus.Registerer, // prometheus registerer
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scope.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scope.GROUP, scheme, metav1.ParameterCodec, codecs)

View File

@@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/apiserver/builder" "github.com/grafana/grafana/pkg/apiserver/builder"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/prometheus/client_golang/prometheus"
) )
var _ builder.APIGroupBuilder = (*ServiceAPIBuilder)(nil) var _ builder.APIGroupBuilder = (*ServiceAPIBuilder)(nil)
@@ -26,7 +27,7 @@ func NewServiceAPIBuilder() *ServiceAPIBuilder {
return &ServiceAPIBuilder{} return &ServiceAPIBuilder{}
} }
func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar) *ServiceAPIBuilder { func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, registerer prometheus.Registerer) *ServiceAPIBuilder {
if !features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) { if !features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) {
return nil // skip registration unless opting into aggregator mode return nil // skip registration unless opting into aggregator mode
} }
@@ -79,6 +80,7 @@ func (b *ServiceAPIBuilder) GetAPIGroupInfo(
codecs serializer.CodecFactory, codecs serializer.CodecFactory,
optsGetter generic.RESTOptionsGetter, optsGetter generic.RESTOptionsGetter,
_ grafanarest.DualWriterMode, _ grafanarest.DualWriterMode,
_ prometheus.Registerer,
) (*genericapiserver.APIGroupInfo, error) { ) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(service.GROUP, scheme, metav1.ParameterCodec, codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(service.GROUP, scheme, metav1.ParameterCodec, codecs)

View File

@@ -24,6 +24,7 @@ import (
servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/service" "github.com/grafana/grafana/pkg/registry/apis/service"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@@ -172,7 +173,7 @@ func CreateAggregatorConfig(commandOptions *options.Options, sharedConfig generi
return NewConfig(aggregatorConfig, sharedInformerFactory, []builder.APIGroupBuilder{serviceAPIBuilder}, remoteServicesConfig), nil return NewConfig(aggregatorConfig, sharedInformerFactory, []builder.APIGroupBuilder{serviceAPIBuilder}, remoteServicesConfig), nil
} }
func CreateAggregatorServer(config *Config, delegateAPIServer genericapiserver.DelegationTarget) (*aggregatorapiserver.APIAggregator, error) { func CreateAggregatorServer(config *Config, delegateAPIServer genericapiserver.DelegationTarget, reg prometheus.Registerer) (*aggregatorapiserver.APIAggregator, error) {
aggregatorConfig := config.KubeAggregatorConfig aggregatorConfig := config.KubeAggregatorConfig
sharedInformerFactory := config.Informers sharedInformerFactory := config.Informers
remoteServicesConfig := config.RemoteServicesConfig remoteServicesConfig := config.RemoteServicesConfig
@@ -285,7 +286,13 @@ func CreateAggregatorServer(config *Config, delegateAPIServer genericapiserver.D
}) })
for _, b := range config.Builders { for _, b := range config.Builders {
serviceAPIGroupInfo, err := b.GetAPIGroupInfo(aggregatorscheme.Scheme, aggregatorscheme.Codecs, aggregatorConfig.GenericConfig.RESTOptionsGetter, grafanarest.Mode0) serviceAPIGroupInfo, err := b.GetAPIGroupInfo(
aggregatorscheme.Scheme,
aggregatorscheme.Codecs,
aggregatorConfig.GenericConfig.RESTOptionsGetter,
grafanarest.Mode0,
reg,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -7,6 +7,7 @@ import (
"path" "path"
"github.com/grafana/dskit/services" "github.com/grafana/dskit/services"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -24,6 +25,7 @@ import (
filestorage "github.com/grafana/grafana/pkg/apiserver/storage/file" filestorage "github.com/grafana/grafana/pkg/apiserver/storage/file"
"github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/appcontext"
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/modules" "github.com/grafana/grafana/pkg/modules"
@@ -109,6 +111,7 @@ type service struct {
builders []builder.APIGroupBuilder builders []builder.APIGroupBuilder
tracing *tracing.TracingService tracing *tracing.TracingService
metrics prometheus.Registerer
authorizer *authorizer.GrafanaAuthorizer authorizer *authorizer.GrafanaAuthorizer
} }
@@ -131,6 +134,7 @@ func ProvideService(
authorizer: authorizer.NewGrafanaAuthorizer(cfg, orgService), authorizer: authorizer.NewGrafanaAuthorizer(cfg, orgService),
tracing: tracing, tracing: tracing,
db: db, // For Unified storage db: db, // For Unified storage
metrics: metrics.ProvideRegisterer(),
} }
// This will be used when running as a dskit service // This will be used when running as a dskit service
@@ -314,7 +318,7 @@ func (s *service) start(ctx context.Context) error {
} }
// Install the API group+version // Install the API group+version
err = builder.InstallAPIs(Scheme, Codecs, server, serverConfig.RESTOptionsGetter, builders, o.StorageOptions) err = builder.InstallAPIs(Scheme, Codecs, server, serverConfig.RESTOptionsGetter, builders, o.StorageOptions, s.metrics)
if err != nil { if err != nil {
return err return err
} }
@@ -324,7 +328,7 @@ func (s *service) start(ctx context.Context) error {
var runningServer *genericapiserver.GenericAPIServer var runningServer *genericapiserver.GenericAPIServer
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) {
runningServer, err = s.startAggregator(transport, serverConfig, server) runningServer, err = s.startAggregator(transport, serverConfig, server, s.metrics)
if err != nil { if err != nil {
return err return err
} }
@@ -374,6 +378,7 @@ func (s *service) startAggregator(
transport *roundTripperFunc, transport *roundTripperFunc,
serverConfig *genericapiserver.RecommendedConfig, serverConfig *genericapiserver.RecommendedConfig,
server *genericapiserver.GenericAPIServer, server *genericapiserver.GenericAPIServer,
reg prometheus.Registerer,
) (*genericapiserver.GenericAPIServer, error) { ) (*genericapiserver.GenericAPIServer, error) {
namespaceMapper := request.GetNamespaceMapper(s.cfg) namespaceMapper := request.GetNamespaceMapper(s.cfg)
@@ -382,7 +387,7 @@ func (s *service) startAggregator(
return nil, err return nil, err
} }
aggregatorServer, err := aggregator.CreateAggregatorServer(aggregatorConfig, server) aggregatorServer, err := aggregator.CreateAggregatorServer(aggregatorConfig, server, reg)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -15,7 +15,7 @@ type MetricsOptions struct {
MetricsRegisterer prometheus.Registerer MetricsRegisterer prometheus.Registerer
} }
func NewMetrcicsOptions(logger log.Logger) *MetricsOptions { func NewMetricsOptions(logger log.Logger) *MetricsOptions {
return &MetricsOptions{ return &MetricsOptions{
logger: logger, logger: logger,
} }

View File

@@ -25,7 +25,7 @@ func New(logger log.Logger, codec runtime.Codec) *Options {
ExtraOptions: options.NewExtraOptions(), ExtraOptions: options.NewExtraOptions(),
RecommendedOptions: options.NewRecommendedOptions(codec), RecommendedOptions: options.NewRecommendedOptions(codec),
TracingOptions: NewTracingOptions(logger), TracingOptions: NewTracingOptions(logger),
MetricsOptions: NewMetrcicsOptions(logger), MetricsOptions: NewMetricsOptions(logger),
ServerRunOptions: genericoptions.NewServerRunOptions(), ServerRunOptions: genericoptions.NewServerRunOptions(),
StorageOptions: options.NewStorageOptions(), StorageOptions: options.NewStorageOptions(),
} }