From 267848063d5044cb7b719bb794906787bd0da577 Mon Sep 17 00:00:00 2001 From: Gabriel MABILLE Date: Fri, 10 Oct 2025 11:07:02 +0200 Subject: [PATCH] AuthZService: Add a metric to count folder app requests (#112258) --- pkg/services/authz/rbac.go | 4 +- pkg/services/authz/rbac/store/folder_store.go | 42 ++++++++++++++++++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/pkg/services/authz/rbac.go b/pkg/services/authz/rbac.go index 753d3934c62..b59d128422b 100644 --- a/pkg/services/authz/rbac.go +++ b/pkg/services/authz/rbac.go @@ -90,7 +90,7 @@ func ProvideAuthZClient( // When running in-proc we get a injection cycle between // authz client, resource client and apiserver so we need to use // package level function to get rest config - store.NewAPIFolderStore(tracer, restConfig.GetRestConfig), + store.NewAPIFolderStore(tracer, reg, restConfig.GetRestConfig), legacy.NewLegacySQLStores(sql), store.NewUnionPermissionStore( store.NewStaticPermissionStore(acService), @@ -224,7 +224,7 @@ func RegisterRBACAuthZService( if cfg.Folder.Host == "" { folderStore = store.NewSQLFolderStore(db, tracer) } else { - folderStore = store.NewAPIFolderStore(tracer, func(ctx context.Context) (*rest.Config, error) { + folderStore = store.NewAPIFolderStore(tracer, reg, func(ctx context.Context) (*rest.Config, error) { return &rest.Config{ Host: cfg.Folder.Host, WrapTransport: func(rt http.RoundTripper) http.RoundTripper { diff --git a/pkg/services/authz/rbac/store/folder_store.go b/pkg/services/authz/rbac/store/folder_store.go index a6d1736e4ec..c859925779c 100644 --- a/pkg/services/authz/rbac/store/folder_store.go +++ b/pkg/services/authz/rbac/store/folder_store.go @@ -3,7 +3,9 @@ package store import ( "context" "fmt" + "sync" + "github.com/prometheus/client_golang/prometheus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" @@ -11,13 +13,42 @@ import ( "k8s.io/client-go/tools/pager" "github.com/grafana/authlib/types" + folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" "github.com/grafana/grafana/pkg/apimachinery/utils" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/storage/legacysql" "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" ) +const ( + metricsNamespace = "iam" + metricsSubSystem = "authz_folder_store" +) + +var ( + registerOnce sync.Once + logger = log.New("authz_folder_store") + requestCount = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: metricsNamespace, + Subsystem: metricsSubSystem, + Name: "requests_total", + Help: "Total number of requests to the folder API server", + }, + []string{"status"}, + ) +) + +func registerMetrics(reg prometheus.Registerer) { + registerOnce.Do(func() { + if err := reg.Register(requestCount); err != nil { + logger.Warn("failed to register folder store metrics", "error", err) + } + }) +} + type FolderStore interface { ListFolders(ctx context.Context, ns types.NamespaceInfo) ([]Folder, error) } @@ -102,7 +133,8 @@ func (s *SQLFolderStore) ListFolders(ctx context.Context, ns types.NamespaceInfo var _ FolderStore = (*APIFolderStore)(nil) -func NewAPIFolderStore(tracer tracing.Tracer, configProvider func(ctx context.Context) (*rest.Config, error)) *APIFolderStore { +func NewAPIFolderStore(tracer tracing.Tracer, reg prometheus.Registerer, configProvider func(ctx context.Context) (*rest.Config, error)) *APIFolderStore { + registerMetrics(reg) return &APIFolderStore{tracer, configProvider} } @@ -121,7 +153,13 @@ func (s *APIFolderStore) ListFolders(ctx context.Context, ns types.NamespaceInfo } p := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { - return client.List(ctx, opts) + obj, err := client.List(ctx, opts) + if err != nil { + requestCount.WithLabelValues("error").Inc() + } else { + requestCount.WithLabelValues("success").Inc() + } + return obj, err }) const defaultPageSize = 500