ServiceAccounts: Add Prometheus metrics service (#51831)

* ServiceAccounts: Add Prometheus metrics service

* add missing init in tests
This commit is contained in:
Jguer 2022-07-07 14:03:16 +00:00 committed by GitHub
parent 10cb84e401
commit db9f80a7a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import (
"github.com/grafana/grafana/pkg/services/searchV2"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
samanager "github.com/grafana/grafana/pkg/services/serviceaccounts/manager"
"github.com/grafana/grafana/pkg/services/store"
"github.com/grafana/grafana/pkg/services/store/sanitizer"
"github.com/grafana/grafana/pkg/services/thumbs"
@ -39,6 +40,7 @@ func ProvideBackgroundServiceRegistry(
pluginsUpdateChecker *updatechecker.PluginsService, metrics *metrics.InternalMetricsService,
secretsService *secretsManager.SecretsService, remoteCache *remotecache.RemoteCache,
thumbnailsService thumbs.Service, StorageService store.StorageService, searchService searchV2.SearchService, entityEventsService store.EntityEventsService,
saService *samanager.ServiceAccountsService,
// Need to make sure these are initialized, is there a better place to put them?
_ dashboardsnapshots.Service, _ *alerting.AlertNotificationService,
_ serviceaccounts.Service, _ *guardian.Provider,
@ -68,6 +70,7 @@ func ProvideBackgroundServiceRegistry(
thumbnailsService,
searchService,
entityEventsService,
saService,
)
}

View File

@ -2,10 +2,69 @@ package database
import (
"context"
"sync"
"time"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/prometheus/client_golang/prometheus"
)
const (
ExporterName = "grafana"
metricsCollectionInterval = time.Minute * 30
)
var (
// MStatTotalServiceAccounts is a metric gauge for total number of service accounts
MStatTotalServiceAccounts prometheus.Gauge
// MStatTotalServiceAccountTokens is a metric gauge for total number of service account tokens
MStatTotalServiceAccountTokens prometheus.Gauge
once sync.Once
Initialised bool = false
)
func InitMetrics() {
once.Do(func() {
MStatTotalServiceAccounts = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "stat_total_service_accounts",
Help: "total amount of service accounts",
Namespace: ExporterName,
})
MStatTotalServiceAccountTokens = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "stat_total_service_account_tokens",
Help: "total amount of service account tokens",
Namespace: ExporterName,
})
prometheus.MustRegister(
MStatTotalServiceAccounts,
MStatTotalServiceAccountTokens,
)
})
}
func (s *ServiceAccountsStoreImpl) RunMetricsCollection(ctx context.Context) error {
if _, err := s.GetUsageMetrics(ctx); err != nil {
s.log.Warn("Failed to get usage metrics", "error", err.Error())
}
updateStatsTicker := time.NewTicker(metricsCollectionInterval)
defer updateStatsTicker.Stop()
for {
select {
case <-updateStatsTicker.C:
if _, err := s.GetUsageMetrics(ctx); err != nil {
s.log.Warn("Failed to get usage metrics", "error", err.Error())
}
case <-ctx.Done():
return ctx.Err()
}
}
}
func (s *ServiceAccountsStoreImpl) GetUsageMetrics(ctx context.Context) (map[string]interface{}, error) {
stats := map[string]interface{}{}
@ -39,5 +98,8 @@ func (s *ServiceAccountsStoreImpl) GetUsageMetrics(ctx context.Context) (map[str
stats["stats.serviceaccounts.tokens.count"] = sqlStats.Tokens
stats["stats.serviceaccounts.in_teams.count"] = sqlStats.InTeams
MStatTotalServiceAccountTokens.Set(float64(sqlStats.Tokens))
MStatTotalServiceAccounts.Set(float64(sqlStats.ServiceAccounts))
return stats, nil
}

View File

@ -16,6 +16,7 @@ func TestStore_UsageStats(t *testing.T) {
saToCreate := tests.TestUser{Login: "servicetestwithTeam@admin", IsServiceAccount: true}
db, store := setupTestDatabase(t)
sa := tests.SetupUserServiceAccount(t, db, saToCreate)
InitMetrics()
keyName := t.Name()
key, err := apikeygen.New(sa.OrgID, keyName)

View File

@ -32,6 +32,7 @@ func ProvideServiceAccountsService(
routeRegister routing.RouteRegister,
usageStats usagestats.Service,
) (*ServiceAccountsService, error) {
database.InitMetrics()
s := &ServiceAccountsService{
store: database.NewServiceAccountsStore(store, kvStore),
log: log.New("serviceaccounts"),
@ -49,6 +50,11 @@ func ProvideServiceAccountsService(
return s, nil
}
func (sa *ServiceAccountsService) Run(ctx context.Context) error {
sa.log.Debug("Started Service Account Metrics collection service")
return sa.store.RunMetricsCollection(ctx)
}
func (sa *ServiceAccountsService) CreateServiceAccount(ctx context.Context, orgID int64, name string) (*serviceaccounts.ServiceAccountDTO, error) {
return sa.store.CreateServiceAccount(ctx, orgID, name)
}

View File

@ -31,4 +31,5 @@ type Store interface {
DeleteServiceAccountToken(ctx context.Context, orgID, serviceAccountID, tokenID int64) error
AddServiceAccountToken(ctx context.Context, serviceAccountID int64, cmd *AddServiceAccountTokenCommand) error
GetUsageMetrics(ctx context.Context) (map[string]interface{}, error)
RunMetricsCollection(ctx context.Context) error
}

View File

@ -133,6 +133,7 @@ type Calls struct {
}
type ServiceAccountsStoreMock struct {
serviceaccounts.Store
Calls Calls
}