From 1aadb4426a6f604147c485e071ae69704951a919 Mon Sep 17 00:00:00 2001 From: Carl Bergquist Date: Thu, 6 Jun 2019 16:39:35 +0200 Subject: [PATCH] metrics: expose stats about roles as metrics (#17469) --- pkg/infra/metrics/metrics.go | 53 ++++++++++++++++++++++++- pkg/infra/usagestats/usage_stats.go | 6 +++ pkg/models/stats.go | 8 ++++ pkg/services/alerting/models.go | 3 +- pkg/services/sqlstore/stats.go | 60 +++++++++++++++-------------- 5 files changed, 98 insertions(+), 32 deletions(-) diff --git a/pkg/infra/metrics/metrics.go b/pkg/infra/metrics/metrics.go index bab2fb45127..bac82604475 100644 --- a/pkg/infra/metrics/metrics.go +++ b/pkg/infra/metrics/metrics.go @@ -43,8 +43,10 @@ var ( // Timers M_DataSource_ProxyReq_Timer prometheus.Summary M_Alerting_Execution_Time prometheus.Summary +) - // StatTotals +// StatTotals +var ( M_Alerting_Active_Alerts prometheus.Gauge M_StatTotal_Dashboards prometheus.Gauge M_StatTotal_Users prometheus.Gauge @@ -52,6 +54,13 @@ var ( M_StatTotal_Orgs prometheus.Gauge M_StatTotal_Playlists prometheus.Gauge + StatsTotalViewers prometheus.Gauge + StatsTotalEditors prometheus.Gauge + StatsTotalAdmins prometheus.Gauge + StatsTotalActiveViewers prometheus.Gauge + StatsTotalActiveEditors prometheus.Gauge + StatsTotalActiveAdmins prometheus.Gauge + // M_Grafana_Version is a gauge that contains build info about this binary // // Deprecated: use M_Grafana_Build_Version instead. @@ -274,6 +283,42 @@ func init() { Namespace: exporterName, }) + StatsTotalViewers = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_viewers", + Help: "total amount of viewers", + Namespace: exporterName, + }) + + StatsTotalEditors = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_editors", + Help: "total amount of editors", + Namespace: exporterName, + }) + + StatsTotalAdmins = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_admins", + Help: "total amount of admins", + Namespace: exporterName, + }) + + StatsTotalActiveViewers = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_active_viewers", + Help: "total amount of viewers", + Namespace: exporterName, + }) + + StatsTotalActiveEditors = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_active_editors", + Help: "total amount of active editors", + Namespace: exporterName, + }) + + StatsTotalActiveAdmins = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "stat_totals_active_admins", + Help: "total amount of active admins", + Namespace: exporterName, + }) + M_Grafana_Version = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: "info", Help: "Information about the Grafana. This metric is deprecated. please use `grafana_build_info`", @@ -339,6 +384,12 @@ func initMetricVars() { M_StatTotal_Orgs, M_StatTotal_Playlists, M_Grafana_Version, + StatsTotalViewers, + StatsTotalEditors, + StatsTotalAdmins, + StatsTotalActiveViewers, + StatsTotalActiveEditors, + StatsTotalActiveAdmins, grafanaBuildVersion) } diff --git a/pkg/infra/usagestats/usage_stats.go b/pkg/infra/usagestats/usage_stats.go index e5b9e8fd8cb..fe95ac5e6f2 100644 --- a/pkg/infra/usagestats/usage_stats.go +++ b/pkg/infra/usagestats/usage_stats.go @@ -166,6 +166,12 @@ func (uss *UsageStatsService) updateTotalStats() { metrics.M_StatActive_Users.Set(float64(statsQuery.Result.ActiveUsers)) metrics.M_StatTotal_Playlists.Set(float64(statsQuery.Result.Playlists)) metrics.M_StatTotal_Orgs.Set(float64(statsQuery.Result.Orgs)) + metrics.StatsTotalViewers.Set(float64(statsQuery.Result.Viewers)) + metrics.StatsTotalActiveViewers.Set(float64(statsQuery.Result.ActiveViewers)) + metrics.StatsTotalEditors.Set(float64(statsQuery.Result.Editors)) + metrics.StatsTotalActiveEditors.Set(float64(statsQuery.Result.ActiveEditors)) + metrics.StatsTotalAdmins.Set(float64(statsQuery.Result.Admins)) + metrics.StatsTotalActiveAdmins.Set(float64(statsQuery.Result.ActiveAdmins)) } func getEdition() string { diff --git a/pkg/models/stats.go b/pkg/models/stats.go index 994170786b0..2bd5337cc9c 100644 --- a/pkg/models/stats.go +++ b/pkg/models/stats.go @@ -16,6 +16,14 @@ type SystemStats struct { Folders int64 ProvisionedDashboards int64 AuthTokens int64 + + Admins int + Editors int + Viewers int + ActiveAdmins int + ActiveEditors int + ActiveViewers int + ActiveSessions int } type DataSourceStats struct { diff --git a/pkg/services/alerting/models.go b/pkg/services/alerting/models.go index e802ab5a7a1..b4bf56821ab 100644 --- a/pkg/services/alerting/models.go +++ b/pkg/services/alerting/models.go @@ -2,8 +2,7 @@ package alerting import "github.com/grafana/grafana/pkg/components/null" -// Job holds state about when the alert rule should -// be evaluated. +// Job holds state about when the alert rule should be evaluated. type Job struct { Offset int64 OffsetWait bool diff --git a/pkg/services/sqlstore/stats.go b/pkg/services/sqlstore/stats.go index a1191cb21c8..1e4537a0e16 100644 --- a/pkg/services/sqlstore/stats.go +++ b/pkg/services/sqlstore/stats.go @@ -75,7 +75,11 @@ func GetSystemStats(query *m.GetSystemStatsQuery) error { sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("dashboard_provisioning") + `) AS provisioned_dashboards,`) sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("dashboard_snapshot") + `) AS snapshots,`) sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("team") + `) AS teams,`) - sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("user_auth_token") + `) AS auth_tokens`) + sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("user_auth_token") + `) AS auth_tokens,`) + + sb.Write(roleCounterSQL("Viewer", "viewers")+`,`, activeUserDeadlineDate) + sb.Write(roleCounterSQL("Editor", "editors")+`,`, activeUserDeadlineDate) + sb.Write(roleCounterSQL("Admin", "admins")+``, activeUserDeadlineDate) var stats m.SystemStats _, err := x.SQL(sb.GetSqlString(), sb.params...).Get(&stats) @@ -88,33 +92,31 @@ func GetSystemStats(query *m.GetSystemStatsQuery) error { return err } +func roleCounterSQL(role, alias string) string { + return ` + ( + SELECT COUNT(*) + FROM ` + dialect.Quote("user") + ` as u + WHERE + (SELECT COUNT(*) + FROM org_user + WHERE org_user.user_id=u.id + AND org_user.role='` + role + `')>0 + ) as ` + alias + `, + ( + SELECT COUNT(*) + FROM ` + dialect.Quote("user") + ` as u + WHERE + (SELECT COUNT(*) + FROM org_user + WHERE org_user.user_id=u.id + AND org_user.role='` + role + `')>0 + AND u.last_seen_at>? + ) as active_` + alias +} + func GetAdminStats(query *m.GetAdminStatsQuery) error { activeEndDate := time.Now().Add(-activeUserTimeLimit) - roleCounter := func(role, alias string) string { - sql := - ` - ( - SELECT COUNT(*) - FROM ` + dialect.Quote("user") + ` as u - WHERE - (SELECT COUNT(*) - FROM org_user - WHERE org_user.user_id=u.id - AND org_user.role='` + role + `')>0 - ) as ` + alias + `, - ( - SELECT COUNT(*) - FROM ` + dialect.Quote("user") + ` as u - WHERE - (SELECT COUNT(*) - FROM org_user - WHERE org_user.user_id=u.id - AND org_user.role='` + role + `')>0 - AND u.last_seen_at>? - ) as active_` + alias - - return sql - } var rawSql = `SELECT ( @@ -156,9 +158,9 @@ func GetAdminStats(query *m.GetAdminStatsQuery) error { SELECT COUNT(*) FROM ` + dialect.Quote("user") + ` where last_seen_at > ? ) as active_users, - ` + roleCounter("Admin", "admins") + `, - ` + roleCounter("Editor", "editors") + `, - ` + roleCounter("Viewer", "viewers") + `, + ` + roleCounterSQL("Admin", "admins") + `, + ` + roleCounterSQL("Editor", "editors") + `, + ` + roleCounterSQL("Viewer", "viewers") + `, ( SELECT COUNT(*) FROM ` + dialect.Quote("user_auth_token") + ` where rotated_at > ?