Guard config CRUD metrics so it's safe for grafana-enterprise
Previous attempt to land this required this PR and a grafana-enterprise PR to land at the ~same time. This PR guards the use of `dsConfigHandlerRequestsDuration` with a nil check, and doesn't change any existing APIs, so we can land it without any timing issues with grafana-enterprise. Once this has landed, we'll make a follow-up PR for grafana-enterprise.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user