diff --git a/pkg/registry/apis/datasource/legacy_store.go b/pkg/registry/apis/datasource/legacy_store.go index aea7ed1daa3..e0526dd2409 100644 --- a/pkg/registry/apis/datasource/legacy_store.go +++ b/pkg/registry/apis/datasource/legacy_store.go @@ -61,20 +61,24 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO } func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { - start := time.Now() - defer func() { - metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Get"), time.Since(start).Seconds()) - }() + if s.dsConfigHandlerRequestsDuration != nil { + start := time.Now() + defer func() { + metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Get"), time.Since(start).Seconds()) + }() + } return s.datasources.GetDataSource(ctx, name) } // Create implements rest.Creater. func (s *legacyStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { - start := time.Now() - defer func() { - metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) - }() + if s.dsConfigHandlerRequestsDuration != nil { + start := time.Now() + defer func() { + metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) + }() + } ds, ok := obj.(*v0alpha1.DataSource) if !ok { @@ -85,10 +89,12 @@ func (s *legacyStorage) Create(ctx context.Context, obj runtime.Object, createVa // Update implements rest.Updater. func (s *legacyStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { - start := time.Now() - defer func() { - metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) - }() + if s.dsConfigHandlerRequestsDuration != nil { + start := time.Now() + defer func() { + metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) + }() + } old, err := s.Get(ctx, name, &metav1.GetOptions{}) if err != nil { @@ -126,10 +132,12 @@ func (s *legacyStorage) Update(ctx context.Context, name string, objInfo rest.Up // Delete implements rest.GracefulDeleter. func (s *legacyStorage) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { - start := time.Now() - defer func() { - metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) - }() + if s.dsConfigHandlerRequestsDuration != nil { + start := time.Now() + defer func() { + metricutil.ObserveWithExemplar(ctx, s.dsConfigHandlerRequestsDuration.WithLabelValues("new", "Create"), time.Since(start).Seconds()) + }() + } err := s.datasources.DeleteDataSource(ctx, name) return nil, false, err diff --git a/pkg/registry/apis/datasource/register.go b/pkg/registry/apis/datasource/register.go index 92cf07053c7..4b6f27da5c0 100644 --- a/pkg/registry/apis/datasource/register.go +++ b/pkg/registry/apis/datasource/register.go @@ -3,6 +3,7 @@ package datasource import ( "context" "encoding/json" + "errors" "fmt" "maps" @@ -38,14 +39,14 @@ var ( // DataSourceAPIBuilder is used just so wire has something unique to return type DataSourceAPIBuilder struct { datasourceResourceInfo utils.ResourceInfo - - pluginJSON plugins.JSONData - client PluginClient // will only ever be called with the same plugin id! - datasources PluginDatasourceProvider - contextProvider PluginContextWrapper - accessControl accesscontrol.AccessControl - queryTypes *queryV0.QueryTypeDefinitionList - configCrudUseNewApis bool + pluginJSON plugins.JSONData + client PluginClient // will only ever be called with the same plugin id! + datasources PluginDatasourceProvider + contextProvider PluginContextWrapper + accessControl accesscontrol.AccessControl + queryTypes *queryV0.QueryTypeDefinitionList + configCrudUseNewApis bool + dataSourceCRUDMetric *prometheus.HistogramVec } func RegisterAPIService( @@ -66,6 +67,16 @@ func RegisterAPIService( var err error var builder *DataSourceAPIBuilder + dataSourceCRUDMetric := metricutil.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: "grafana", + Name: "ds_config_handler_requests_duration_seconds", + Help: "Duration of requests handled by datasource configuration handlers", + }, []string{"code_path", "handler"}) + regErr := reg.Register(dataSourceCRUDMetric) + if regErr != nil && !errors.As(regErr, &prometheus.AlreadyRegisteredError{}) { + return nil, regErr + } + pluginJSONs, err := getDatasourcePlugins(pluginSources) if err != nil { return nil, fmt.Errorf("error getting list of datasource plugins: %s", err) @@ -91,6 +102,7 @@ func RegisterAPIService( if err != nil { return nil, err } + builder.SetDataSourceCRUDMetrics(dataSourceCRUDMetric) apiRegistrar.RegisterAPI(builder) } @@ -161,6 +173,10 @@ func (b *DataSourceAPIBuilder) GetGroupVersion() schema.GroupVersion { return b.datasourceResourceInfo.GroupVersion() } +func (b *DataSourceAPIBuilder) SetDataSourceCRUDMetrics(datasourceCRUDMetric *prometheus.HistogramVec) { + b.dataSourceCRUDMetric = datasourceCRUDMetric +} + func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) { scheme.AddKnownTypes(gv, &datasourceV0.DataSource{}, @@ -218,13 +234,9 @@ func (b *DataSourceAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver if b.configCrudUseNewApis { legacyStore := &legacyStorage{ - datasources: b.datasources, - resourceInfo: &ds, - dsConfigHandlerRequestsDuration: metricutil.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "grafana", - Name: "ds_config_handler_requests_duration_seconds", - Help: "Duration of requests handled by datasource configuration handlers", - }, []string{"code_path", "handler"}), + datasources: b.datasources, + resourceInfo: &ds, + dsConfigHandlerRequestsDuration: b.dataSourceCRUDMetric, } unified, err := grafanaregistry.NewRegistryStore(opts.Scheme, ds, opts.OptsGetter) if err != nil {