diff --git a/pkg/registry/apis/secret/contracts/decrypt.go b/pkg/registry/apis/secret/contracts/decrypt.go index 32f9f7f6c1d..2c5403c790d 100644 --- a/pkg/registry/apis/secret/contracts/decrypt.go +++ b/pkg/registry/apis/secret/contracts/decrypt.go @@ -27,7 +27,7 @@ type DecryptAuthorizer interface { Authorize(ctx context.Context, secureValueName string, secureValueDecrypters []string) (identity string, allowed bool) } -// DecryptService is the inferface for the decrypt service. +// DecryptService is the interface for the decrypt service. type DecryptService interface { Decrypt(ctx context.Context, namespace string, names ...string) (map[string]DecryptResult, error) Close() error diff --git a/pkg/registry/apis/secret/service/metrics/metrics.go b/pkg/registry/apis/secret/service/metrics/metrics.go new file mode 100644 index 00000000000..b179ead20b7 --- /dev/null +++ b/pkg/registry/apis/secret/service/metrics/metrics.go @@ -0,0 +1,128 @@ +package metrics + +import ( + "sync" + + "github.com/prometheus/client_golang/prometheus" +) + +const ( + namespace = "grafana_secrets_manager" + subsystem = "service" +) + +// SecureValueServiceMetrics is a struct that contains all the metrics for SecureValue. +type SecureValueServiceMetrics struct { + SecureValueCreateDuration *prometheus.HistogramVec + SecureValueCreateCount *prometheus.CounterVec + SecureValueUpdateDuration *prometheus.HistogramVec + SecureValueUpdateCount *prometheus.CounterVec + SecureValueReadDuration *prometheus.HistogramVec + SecureValueReadCount *prometheus.CounterVec + SecureValueListDuration *prometheus.HistogramVec + SecureValueListCount *prometheus.CounterVec + SecureValueDeleteDuration *prometheus.HistogramVec + SecureValueDeleteCount *prometheus.CounterVec +} + +func newSecureValueServiceMetrics() *SecureValueServiceMetrics { + return &SecureValueServiceMetrics{ + SecureValueCreateDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_create_duration_seconds", + Help: "Duration of Secure Value create operations", + Buckets: prometheus.DefBuckets, + }, []string{"success"}), + SecureValueCreateCount: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_create_count", + Help: "Count of Secure Value create operations", + }, []string{"success"}), + SecureValueReadDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_read_duration_seconds", + Help: "Duration of Secure Value read operations", + Buckets: prometheus.DefBuckets, + }, []string{"success"}), + SecureValueReadCount: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_read_count", + Help: "Count of Secure Value read operations", + }, []string{"success"}), + SecureValueUpdateDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_update_duration_seconds", + Help: "Duration of Secure Value update operations", + Buckets: prometheus.DefBuckets, + }, []string{"success"}), + SecureValueUpdateCount: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_update_count", + Help: "Count of Secure Value update operations", + }, []string{"success"}), + SecureValueListDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_list_duration_seconds", + Help: "Duration of Secure Value list operations", + Buckets: prometheus.DefBuckets, + }, []string{"success"}), + SecureValueListCount: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_list_count", + Help: "Count of Secure Value list operations", + }, []string{"success"}), + SecureValueDeleteDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_delete_duration_seconds", + Help: "Duration of Secure Value delete operations", + Buckets: prometheus.DefBuckets, + }, []string{"success"}), + SecureValueDeleteCount: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "secure_value_delete_count", + Help: "Count of Secure Value delete operations", + }, []string{"success"}), + } +} + +var ( + initOnce sync.Once + metricsInstance *SecureValueServiceMetrics +) + +func NewSecureValueServiceMetrics(reg prometheus.Registerer) *SecureValueServiceMetrics { + initOnce.Do(func() { + m := newSecureValueServiceMetrics() + + if reg != nil { + reg.MustRegister( + m.SecureValueCreateDuration, + m.SecureValueCreateCount, + m.SecureValueReadDuration, + m.SecureValueReadCount, + m.SecureValueUpdateDuration, + m.SecureValueUpdateCount, + m.SecureValueListDuration, + m.SecureValueListCount, + m.SecureValueDeleteDuration, + m.SecureValueDeleteCount, + ) + } + metricsInstance = m + }) + return metricsInstance +} + +func NewTestMetrics() *SecureValueServiceMetrics { + return newSecureValueServiceMetrics() +} diff --git a/pkg/registry/apis/secret/service/secure_value.go b/pkg/registry/apis/secret/service/secure_value.go index f9bafad9467..fe32208562d 100644 --- a/pkg/registry/apis/secret/service/secure_value.go +++ b/pkg/registry/apis/secret/service/secure_value.go @@ -3,6 +3,8 @@ package service import ( "context" "fmt" + "strconv" + "time" claims "github.com/grafana/authlib/types" "go.opentelemetry.io/otel/attribute" @@ -12,9 +14,14 @@ import ( secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + "github.com/grafana/grafana/pkg/registry/apis/secret/service/metrics" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" + "github.com/prometheus/client_golang/prometheus" + "go.opentelemetry.io/otel/codes" ) +var _ contracts.SecureValueService = (*SecureValueService)(nil) + type SecureValueService struct { tracer trace.Tracer accessClient claims.AccessClient @@ -22,6 +29,7 @@ type SecureValueService struct { secureValueMetadataStorage contracts.SecureValueMetadataStorage keeperMetadataStorage contracts.KeeperMetadataStorage keeperService contracts.KeeperService + metrics *metrics.SecureValueServiceMetrics } func ProvideSecureValueService( @@ -31,6 +39,7 @@ func ProvideSecureValueService( secureValueMetadataStorage contracts.SecureValueMetadataStorage, keeperMetadataStorage contracts.KeeperMetadataStorage, keeperService contracts.KeeperService, + reg prometheus.Registerer, ) contracts.SecureValueService { return &SecureValueService{ tracer: tracer, @@ -39,27 +48,77 @@ func ProvideSecureValueService( secureValueMetadataStorage: secureValueMetadataStorage, keeperMetadataStorage: keeperMetadataStorage, keeperService: keeperService, + metrics: metrics.NewSecureValueServiceMetrics(reg), } } -func (s *SecureValueService) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) { +func (s *SecureValueService) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (_ *secretv1beta1.SecureValue, createErr error) { + start := time.Now() + name, namespace := sv.GetName(), sv.GetNamespace() ctx, span := s.tracer.Start(ctx, "SecureValueService.Create", trace.WithAttributes( - attribute.String("name", sv.GetName()), - attribute.String("namespace", sv.GetNamespace()), + attribute.String("name", name), + attribute.String("namespace", namespace), attribute.String("actor", actorUID), )) defer span.End() + + defer func() { + args := []any{ + "name", name, + "namespace", namespace, + "actorUID", actorUID, + } + + success := createErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueService.Create failed") + span.RecordError(createErr) + args = append(args, "error", createErr) + } + + logging.FromContext(ctx).Info("SecureValueService.Create finished", args...) + + s.metrics.SecureValueCreateDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueCreateCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + return s.createNewVersion(ctx, sv, actorUID) } -func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, bool, error) { +func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv1beta1.SecureValue, actorUID string) (_ *secretv1beta1.SecureValue, sync bool, updateErr error) { + start := time.Now() + name, namespace := newSecureValue.GetName(), newSecureValue.GetNamespace() + ctx, span := s.tracer.Start(ctx, "SecureValueService.Update", trace.WithAttributes( - attribute.String("name", newSecureValue.GetName()), - attribute.String("namespace", newSecureValue.GetNamespace()), + attribute.String("name", name), + attribute.String("namespace", namespace), attribute.String("actor", actorUID), )) defer span.End() + defer func() { + args := []any{ + "name", name, + "namespace", namespace, + "actorUID", actorUID, + "sync", sync, + } + + success := updateErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueService.Update failed") + span.RecordError(updateErr) + args = append(args, "error", updateErr) + } + + logging.FromContext(ctx).Info("SecureValueService.Update finished", args...) + + s.metrics.SecureValueUpdateDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueUpdateCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + if newSecureValue.Spec.Value == nil { currentVersion, err := s.secureValueMetadataStorage.Read(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name, contracts.ReadOpts{}) if err != nil { @@ -136,22 +195,66 @@ func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv1b return createdSv, nil } -func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (*secretv1beta1.SecureValue, error) { +func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (_ *secretv1beta1.SecureValue, readErr error) { + start := time.Now() + ctx, span := s.tracer.Start(ctx, "SecureValueService.Read", trace.WithAttributes( attribute.String("name", name), attribute.String("namespace", namespace.String()), )) + + defer func() { + args := []any{ + "name", name, + "namespace", namespace, + } + + success := readErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueService.Read failed") + span.RecordError(readErr) + args = append(args, "error", readErr) + } + + logging.FromContext(ctx).Info("SecureValueService.Read finished", args...) + + s.metrics.SecureValueReadDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueReadCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + defer span.End() return s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: false}) } -func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace) (*secretv1beta1.SecureValueList, error) { +func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace) (_ *secretv1beta1.SecureValueList, listErr error) { + start := time.Now() + ctx, span := s.tracer.Start(ctx, "SecureValueService.List", trace.WithAttributes( attribute.String("namespace", namespace.String()), )) defer span.End() + defer func() { + args := []any{ + "namespace", namespace, + } + + success := listErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueService.List failed") + span.RecordError(listErr) + args = append(args, "error", listErr) + } + + logging.FromContext(ctx).Info("SecureValueService.List finished", args...) + + s.metrics.SecureValueListDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueListCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + user, ok := claims.AuthInfoFrom(ctx) if !ok { return nil, fmt.Errorf("missing auth info in context") @@ -188,13 +291,35 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace }, nil } -func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (*secretv1beta1.SecureValue, error) { +func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (_ *secretv1beta1.SecureValue, deleteErr error) { + start := time.Now() + ctx, span := s.tracer.Start(ctx, "SecureValueService.Delete", trace.WithAttributes( attribute.String("name", name), attribute.String("namespace", namespace.String()), )) defer span.End() + defer func() { + args := []any{ + "name", name, + "namespace", namespace, + } + + success := deleteErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueService.Delete failed") + span.RecordError(deleteErr) + args = append(args, "error", deleteErr) + } + + logging.FromContext(ctx).Info("SecureValueService.Delete finished", args...) + + s.metrics.SecureValueDeleteDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueDeleteCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + // TODO: does this need to be for update? sv, err := s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: true}) if err != nil { diff --git a/pkg/registry/apis/secret/testutils/testutils.go b/pkg/registry/apis/secret/testutils/testutils.go index f2d24b05905..8b6765ba642 100644 --- a/pkg/registry/apis/secret/testutils/testutils.go +++ b/pkg/registry/apis/secret/testutils/testutils.go @@ -120,7 +120,7 @@ func Setup(t *testing.T, opts ...func(*SetupConfig)) Sut { keeperService = setupCfg.KeeperService } - secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, keeperMetadataStorage, keeperService) + secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, keeperMetadataStorage, keeperService, nil) decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer) diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index aeff3aa1924..3d055c451e5 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -780,7 +780,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) + secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService, registerer) secureValueValidator := validator3.ProvideSecureValueValidator() secureValueClient := secret.ProvideSecureValueClient(secureValueService, secureValueValidator, accessClient) decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer) @@ -1341,7 +1341,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) + secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService, registerer) secureValueValidator := validator3.ProvideSecureValueValidator() secureValueClient := secret.ProvideSecureValueClient(secureValueService, secureValueValidator, accessClient) decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer) diff --git a/pkg/storage/secret/metadata/decrypt_store_test.go b/pkg/storage/secret/metadata/decrypt_store_test.go index 03d0daace36..3c35a443794 100644 --- a/pkg/storage/secret/metadata/decrypt_store_test.go +++ b/pkg/storage/secret/metadata/decrypt_store_test.go @@ -292,8 +292,13 @@ func TestIntegrationDecrypt(t *testing.T) { require.NotEmpty(t, exposed) require.Equal(t, "value", exposed.DangerouslyExposeAndConsumeValue()) - require.Len(t, fakeLogger.InfoArgs, 1) - args := fakeLogger.InfoArgs[0] + require.Len(t, fakeLogger.InfoMsgs, 2) + require.Equal(t, fakeLogger.InfoMsgs[0], "SecureValueMetadataStorage.Read") + require.Equal(t, fakeLogger.InfoMsgs[1], "Secrets Audit Log") + + require.Len(t, fakeLogger.InfoArgs, 2) + // we only want to check the audit log args + args := fakeLogger.InfoArgs[1] require.Contains(t, args, "grafana_decrypter_identity") require.Contains(t, args, "decrypter_identity") for i, arg := range args { diff --git a/pkg/storage/secret/metadata/metrics/metrics.go b/pkg/storage/secret/metadata/metrics/metrics.go index aea3817f12c..f9baba1de64 100644 --- a/pkg/storage/secret/metadata/metrics/metrics.go +++ b/pkg/storage/secret/metadata/metrics/metrics.go @@ -25,12 +25,8 @@ type StorageMetrics struct { KeeperMetadataListCount prometheus.Counter KeeperMetadataGetKeeperConfigDuration prometheus.Histogram - SecureValueMetadataCreateDuration prometheus.Histogram - SecureValueMetadataCreateCount prometheus.Counter - SecureValueMetadataUpdateDuration prometheus.Histogram - SecureValueMetadataUpdateCount prometheus.Counter - SecureValueMetadataDeleteDuration prometheus.Histogram - SecureValueMetadataDeleteCount prometheus.Counter + SecureValueMetadataCreateDuration *prometheus.HistogramVec + SecureValueMetadataCreateCount *prometheus.CounterVec SecureValueMetadataGetDuration prometheus.Histogram SecureValueMetadataGetCount prometheus.Counter SecureValueMetadataListDuration prometheus.Histogram @@ -119,45 +115,19 @@ func newStorageMetrics() *StorageMetrics { }), // Secure value metrics - SecureValueMetadataCreateDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ + SecureValueMetadataCreateDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: namespace, Subsystem: subsystem, Name: "secure_value_metadata_create_duration_seconds", Help: "Duration of secure value metadata create operations", Buckets: prometheus.DefBuckets, - }), - SecureValueMetadataCreateCount: prometheus.NewCounter(prometheus.CounterOpts{ + }, []string{"successful"}), + SecureValueMetadataCreateCount: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Subsystem: subsystem, Name: "secure_value_metadata_create_count", Help: "Count of secure value metadata create operations", - }), - SecureValueMetadataUpdateDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "secure_value_metadata_update_duration_seconds", - Help: "Duration of secure value metadata update operations", - Buckets: prometheus.DefBuckets, - }), - SecureValueMetadataUpdateCount: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "secure_value_metadata_update_count", - Help: "Count of secure value metadata update operations", - }), - SecureValueMetadataDeleteDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "secure_value_metadata_delete_duration_seconds", - Help: "Duration of secure value metadata delete operations", - Buckets: prometheus.DefBuckets, - }), - SecureValueMetadataDeleteCount: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "secure_value_metadata_delete_count", - Help: "Count of secure value metadata delete operations", - }), + }, []string{"successful"}), SecureValueMetadataGetDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ Namespace: namespace, Subsystem: subsystem, @@ -241,10 +211,6 @@ func NewStorageMetrics(reg prometheus.Registerer) *StorageMetrics { m.KeeperMetadataGetKeeperConfigDuration, m.SecureValueMetadataCreateDuration, m.SecureValueMetadataCreateCount, - m.SecureValueMetadataUpdateDuration, - m.SecureValueMetadataUpdateCount, - m.SecureValueMetadataDeleteDuration, - m.SecureValueMetadataDeleteCount, m.SecureValueMetadataGetDuration, m.SecureValueMetadataGetCount, m.SecureValueMetadataListDuration, diff --git a/pkg/storage/secret/metadata/secure_value_store.go b/pkg/storage/secret/metadata/secure_value_store.go index 3e539b83b3e..46001baf3ae 100644 --- a/pkg/storage/secret/metadata/secure_value_store.go +++ b/pkg/storage/secret/metadata/secure_value_store.go @@ -3,18 +3,21 @@ package metadata import ( "context" "fmt" + "strconv" "time" "github.com/prometheus/client_golang/prometheus" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "github.com/grafana/grafana-app-sdk/logging" secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" "github.com/grafana/grafana/pkg/storage/secret/metadata/metrics" "github.com/grafana/grafana/pkg/storage/unified/sql" "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" + "go.opentelemetry.io/otel/codes" ) var _ contracts.SecureValueMetadataStorage = (*secureValueMetadataStorage)(nil) @@ -40,16 +43,39 @@ type secureValueMetadataStorage struct { tracer trace.Tracer } -func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) { +func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (_ *secretv1beta1.SecureValue, svmCreateErr error) { start := time.Now() + name := sv.GetName() + namespace := sv.GetNamespace() ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Create", trace.WithAttributes( - attribute.String("name", sv.GetName()), - attribute.String("namespace", sv.GetNamespace()), + attribute.String("name", name), + attribute.String("namespace", namespace), attribute.String("actorUID", actorUID), )) defer span.End() - // Set inside of the transaction callback + defer func() { + args := []any{ + "name", name, + "namespace", namespace, + "actorUID", actorUID, + } + + success := svmCreateErr == nil + args = append(args, "success", success) + if !success { + span.SetStatus(codes.Error, "SecureValueMetadataStorage.Create failed") + span.RecordError(svmCreateErr) + args = append(args, "error", svmCreateErr) + } + + logging.FromContext(ctx).Info("SecureValueMetadataStorage.Create", args...) + + s.metrics.SecureValueMetadataCreateDuration.WithLabelValues(strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) + s.metrics.SecureValueMetadataCreateCount.WithLabelValues(strconv.FormatBool(success)).Inc() + }() + + // Set inside the transaction callback var row *secureValueDB err := s.db.Transaction(ctx, func(ctx context.Context) error { @@ -145,9 +171,6 @@ func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv1bet return nil, fmt.Errorf("convert to kubernetes object: %w", err) } - s.metrics.SecureValueMetadataCreateDuration.Observe(time.Since(start).Seconds()) - s.metrics.SecureValueMetadataCreateCount.Inc() - return createdSecureValue, nil } @@ -230,7 +253,7 @@ func (s *secureValueMetadataStorage) readActiveVersion(ctx context.Context, name return secureValue, nil } -func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv1beta1.SecureValue, error) { +func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (_ *secretv1beta1.SecureValue, readErr error) { start := time.Now() ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Read", trace.WithAttributes( attribute.String("name", name), @@ -239,6 +262,13 @@ func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.N )) defer span.End() + defer func() { + logging.FromContext(ctx).Info("SecureValueMetadataStorage.Read", "namespace", namespace, "name", name, "success", readErr != nil, "error", readErr) + + s.metrics.SecureValueMetadataGetDuration.Observe(time.Since(start).Seconds()) + s.metrics.SecureValueMetadataGetCount.Inc() + }() + secureValue, err := s.readActiveVersion(ctx, namespace, name, opts) if err != nil { return nil, err @@ -249,9 +279,6 @@ func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.N return nil, fmt.Errorf("convert to kubernetes object: %w", err) } - s.metrics.SecureValueMetadataGetDuration.Observe(time.Since(start).Seconds()) - s.metrics.SecureValueMetadataGetCount.Inc() - return secureValueKub, nil }