diff --git a/pkg/services/supportbundles/supportbundlesimpl/service.go b/pkg/services/supportbundles/supportbundlesimpl/service.go index 7f3b4b44bf1..00bd192712e 100644 --- a/pkg/services/supportbundles/supportbundlesimpl/service.go +++ b/pkg/services/supportbundles/supportbundlesimpl/service.go @@ -68,6 +68,8 @@ func ProvideService(cfg *setting.Cfg, serverAdminOnly: section.Key("server_admin_only").MustBool(true), } + usageStats.RegisterMetricsFunc(s.getUsageStats) + if !features.IsEnabled(featuremgmt.FlagSupportBundles) || !s.enabled { return s, nil } @@ -167,3 +169,15 @@ func (s *Service) cleanup(ctx context.Context) { } } } + +func (s *Service) getUsageStats(ctx context.Context) (map[string]interface{}, error) { + m := map[string]interface{}{} + + count, err := s.store.StatsCount(ctx) + if err != nil { + s.log.Warn("unable to get support bundle counter", "error", err) + } + + m["stats.bundles.count"] = count + return m, nil +} diff --git a/pkg/services/supportbundles/supportbundlesimpl/store.go b/pkg/services/supportbundles/supportbundlesimpl/store.go index 921ee551b30..a7bc17fa742 100644 --- a/pkg/services/supportbundles/supportbundlesimpl/store.go +++ b/pkg/services/supportbundles/supportbundlesimpl/store.go @@ -4,13 +4,17 @@ import ( "context" "encoding/json" "errors" + "fmt" "sort" + "strconv" "strings" + "sync" "time" "github.com/google/uuid" "github.com/grafana/grafana/pkg/infra/kvstore" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/supportbundles" "github.com/grafana/grafana/pkg/services/user" ) @@ -19,17 +23,27 @@ const ( defaultBundleExpiration = 72 * time.Hour // 72h ) +const key = "count" + func newStore(kv kvstore.KVStore) *store { - return &store{kv: kvstore.WithNamespace(kv, 0, "supportbundle")} + return &store{ + kv: kvstore.WithNamespace(kv, 0, "supportbundle"), + statKV: kvstore.WithNamespace(kv, 0, "supportbundlestats"), + log: log.New("supportbundle.store"), + } } type store struct { - kv *kvstore.NamespacedKVStore + kv *kvstore.NamespacedKVStore + log log.Logger + mu sync.Mutex + statKV *kvstore.NamespacedKVStore } type bundleStore interface { Create(ctx context.Context, usr *user.SignedInUser) (*supportbundles.Bundle, error) Get(ctx context.Context, uid string) (*supportbundles.Bundle, error) + StatsCount(ctx context.Context) (int64, error) List() ([]supportbundles.Bundle, error) Remove(ctx context.Context, uid string) error Update(ctx context.Context, uid string, state supportbundles.State, tarBytes []byte) error @@ -49,6 +63,25 @@ func (s *store) Create(ctx context.Context, usr *user.SignedInUser) (*supportbun ExpiresAt: time.Now().Add(defaultBundleExpiration).Unix(), } + s.mu.Lock() + + bundlesCreatedString, _, err := s.statKV.Get(ctx, key) + if err != nil { + s.log.Warn("An error has occurred upon retrieving value at statKV", "key", key) + } + + bundlesCreated, err := strconv.ParseInt(bundlesCreatedString, 10, 64) + if err != nil { + s.log.Warn("No value was found at statKV", "key", key) + } + + bundlesCreated = bundlesCreated + 1 + + if err := s.statKV.Set(ctx, key, fmt.Sprint(bundlesCreated)); err != nil { + s.log.Warn("An error has occurred upon setting a value at statKV", "key", key) + } + s.mu.Unlock() + if err := s.set(ctx, &bundle); err != nil { return nil, err } @@ -121,3 +154,14 @@ func (s *store) List() ([]supportbundles.Bundle, error) { return res, nil } + +func (s *store) StatsCount(ctx context.Context) (int64, error) { + countString, exists, err := s.statKV.Get(ctx, key) + if err != nil { + return 0, err + } + if !exists { + return 0, nil + } + return strconv.ParseInt(countString, 10, 64) +}