| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- package metrics
- import (
- "bytes"
- "encoding/json"
- "net/http"
- "runtime"
- "strings"
- "time"
- "github.com/grafana/grafana/pkg/bus"
- "github.com/grafana/grafana/pkg/models"
- "github.com/grafana/grafana/pkg/plugins"
- "github.com/grafana/grafana/pkg/setting"
- "github.com/prometheus/client_golang/prometheus"
- )
- const exporterName = "grafana"
- var (
- M_Instance_Start prometheus.Counter
- M_Page_Status *prometheus.CounterVec
- M_Api_Status *prometheus.CounterVec
- M_Proxy_Status *prometheus.CounterVec
- M_Http_Request_Total *prometheus.CounterVec
- M_Http_Request_Summary *prometheus.SummaryVec
- M_Api_User_SignUpStarted prometheus.Counter
- M_Api_User_SignUpCompleted prometheus.Counter
- M_Api_User_SignUpInvite prometheus.Counter
- M_Api_Dashboard_Save prometheus.Summary
- M_Api_Dashboard_Get prometheus.Summary
- M_Api_Dashboard_Search prometheus.Summary
- M_Api_Admin_User_Create prometheus.Counter
- M_Api_Login_Post prometheus.Counter
- M_Api_Login_OAuth prometheus.Counter
- M_Api_Org_Create prometheus.Counter
- M_Api_Dashboard_Snapshot_Create prometheus.Counter
- M_Api_Dashboard_Snapshot_External prometheus.Counter
- M_Api_Dashboard_Snapshot_Get prometheus.Counter
- M_Api_Dashboard_Insert prometheus.Counter
- M_Alerting_Result_State *prometheus.CounterVec
- M_Alerting_Notification_Sent *prometheus.CounterVec
- M_Aws_CloudWatch_GetMetricStatistics prometheus.Counter
- M_Aws_CloudWatch_ListMetrics prometheus.Counter
- M_Aws_CloudWatch_GetMetricData prometheus.Counter
- M_DB_DataSource_QueryById prometheus.Counter
- // Timers
- M_DataSource_ProxyReq_Timer prometheus.Summary
- M_Alerting_Execution_Time prometheus.Summary
- // StatTotals
- M_Alerting_Active_Alerts prometheus.Gauge
- M_StatTotal_Dashboards prometheus.Gauge
- M_StatTotal_Users prometheus.Gauge
- M_StatActive_Users prometheus.Gauge
- M_StatTotal_Orgs prometheus.Gauge
- M_StatTotal_Playlists prometheus.Gauge
- M_Grafana_Version *prometheus.GaugeVec
- )
- func newCounterVecStartingAtZero(opts prometheus.CounterOpts, labels []string, labelValues ...string) *prometheus.CounterVec {
- counter := prometheus.NewCounterVec(opts, labels)
- for _, label := range labelValues {
- counter.WithLabelValues(label).Add(0)
- }
- return counter
- }
- func newCounterStartingAtZero(opts prometheus.CounterOpts, labelValues ...string) prometheus.Counter {
- counter := prometheus.NewCounter(opts)
- counter.Add(0)
- return counter
- }
- func init() {
- M_Instance_Start = prometheus.NewCounter(prometheus.CounterOpts{
- Name: "instance_start_total",
- Help: "counter for started instances",
- Namespace: exporterName,
- })
- httpStatusCodes := []string{"200", "404", "500", "unknown"}
- M_Page_Status = newCounterVecStartingAtZero(
- prometheus.CounterOpts{
- Name: "page_response_status_total",
- Help: "page http response status",
- Namespace: exporterName,
- }, []string{"code"}, httpStatusCodes...)
- M_Api_Status = newCounterVecStartingAtZero(
- prometheus.CounterOpts{
- Name: "api_response_status_total",
- Help: "api http response status",
- Namespace: exporterName,
- }, []string{"code"}, httpStatusCodes...)
- M_Proxy_Status = newCounterVecStartingAtZero(
- prometheus.CounterOpts{
- Name: "proxy_response_status_total",
- Help: "proxy http response status",
- Namespace: exporterName,
- }, []string{"code"}, httpStatusCodes...)
- M_Http_Request_Total = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "http_request_total",
- Help: "http request counter",
- },
- []string{"handler", "statuscode", "method"},
- )
- M_Http_Request_Summary = prometheus.NewSummaryVec(
- prometheus.SummaryOpts{
- Name: "http_request_duration_milliseconds",
- Help: "http request summary",
- },
- []string{"handler", "statuscode", "method"},
- )
- M_Api_User_SignUpStarted = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_user_signup_started_total",
- Help: "amount of users who started the signup flow",
- Namespace: exporterName,
- })
- M_Api_User_SignUpCompleted = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_user_signup_completed_total",
- Help: "amount of users who completed the signup flow",
- Namespace: exporterName,
- })
- M_Api_User_SignUpInvite = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_user_signup_invite_total",
- Help: "amount of users who have been invited",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Save = prometheus.NewSummary(prometheus.SummaryOpts{
- Name: "api_dashboard_save_milliseconds",
- Help: "summary for dashboard save duration",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Get = prometheus.NewSummary(prometheus.SummaryOpts{
- Name: "api_dashboard_get_milliseconds",
- Help: "summary for dashboard get duration",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Search = prometheus.NewSummary(prometheus.SummaryOpts{
- Name: "api_dashboard_search_milliseconds",
- Help: "summary for dashboard search duration",
- Namespace: exporterName,
- })
- M_Api_Admin_User_Create = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_admin_user_created_total",
- Help: "api admin user created counter",
- Namespace: exporterName,
- })
- M_Api_Login_Post = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_login_post_total",
- Help: "api login post counter",
- Namespace: exporterName,
- })
- M_Api_Login_OAuth = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_login_oauth_total",
- Help: "api login oauth counter",
- Namespace: exporterName,
- })
- M_Api_Org_Create = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_org_create_total",
- Help: "api org created counter",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Snapshot_Create = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_dashboard_snapshot_create_total",
- Help: "dashboard snapshots created",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Snapshot_External = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_dashboard_snapshot_external_total",
- Help: "external dashboard snapshots created",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Snapshot_Get = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_dashboard_snapshot_get_total",
- Help: "loaded dashboards",
- Namespace: exporterName,
- })
- M_Api_Dashboard_Insert = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "api_models_dashboard_insert_total",
- Help: "dashboards inserted ",
- Namespace: exporterName,
- })
- M_Alerting_Result_State = prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "alerting_result_total",
- Help: "alert execution result counter",
- Namespace: exporterName,
- }, []string{"state"})
- M_Alerting_Notification_Sent = prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "alerting_notification_sent_total",
- Help: "counter for how many alert notifications been sent",
- Namespace: exporterName,
- }, []string{"type"})
- M_Aws_CloudWatch_GetMetricStatistics = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "aws_cloudwatch_get_metric_statistics_total",
- Help: "counter for getting metric statistics from aws",
- Namespace: exporterName,
- })
- M_Aws_CloudWatch_ListMetrics = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "aws_cloudwatch_list_metrics_total",
- Help: "counter for getting list of metrics from aws",
- Namespace: exporterName,
- })
- M_Aws_CloudWatch_GetMetricData = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "aws_cloudwatch_get_metric_data_total",
- Help: "counter for getting metric data time series from aws",
- Namespace: exporterName,
- })
- M_DB_DataSource_QueryById = newCounterStartingAtZero(prometheus.CounterOpts{
- Name: "db_datasource_query_by_id_total",
- Help: "counter for getting datasource by id",
- Namespace: exporterName,
- })
- M_DataSource_ProxyReq_Timer = prometheus.NewSummary(prometheus.SummaryOpts{
- Name: "api_dataproxy_request_all_milliseconds",
- Help: "summary for dataproxy request duration",
- Namespace: exporterName,
- })
- M_Alerting_Execution_Time = prometheus.NewSummary(prometheus.SummaryOpts{
- Name: "alerting_execution_time_milliseconds",
- Help: "summary of alert exeuction duration",
- Namespace: exporterName,
- })
- M_Alerting_Active_Alerts = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "alerting_active_alerts",
- Help: "amount of active alerts",
- Namespace: exporterName,
- })
- M_StatTotal_Dashboards = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "stat_totals_dashboard",
- Help: "total amount of dashboards",
- Namespace: exporterName,
- })
- M_StatTotal_Users = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "stat_total_users",
- Help: "total amount of users",
- Namespace: exporterName,
- })
- M_StatActive_Users = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "stat_active_users",
- Help: "number of active users",
- Namespace: exporterName,
- })
- M_StatTotal_Orgs = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "stat_total_orgs",
- Help: "total amount of orgs",
- Namespace: exporterName,
- })
- M_StatTotal_Playlists = prometheus.NewGauge(prometheus.GaugeOpts{
- Name: "stat_total_playlists",
- Help: "total amount of playlists",
- Namespace: exporterName,
- })
- M_Grafana_Version = prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Name: "info",
- Help: "Information about the Grafana",
- Namespace: exporterName,
- }, []string{"version"})
- }
- func initMetricVars() {
- prometheus.MustRegister(
- M_Instance_Start,
- M_Page_Status,
- M_Api_Status,
- M_Proxy_Status,
- M_Http_Request_Total,
- M_Http_Request_Summary,
- M_Api_User_SignUpStarted,
- M_Api_User_SignUpCompleted,
- M_Api_User_SignUpInvite,
- M_Api_Dashboard_Save,
- M_Api_Dashboard_Get,
- M_Api_Dashboard_Search,
- M_DataSource_ProxyReq_Timer,
- M_Alerting_Execution_Time,
- M_Api_Admin_User_Create,
- M_Api_Login_Post,
- M_Api_Login_OAuth,
- M_Api_Org_Create,
- M_Api_Dashboard_Snapshot_Create,
- M_Api_Dashboard_Snapshot_External,
- M_Api_Dashboard_Snapshot_Get,
- M_Api_Dashboard_Insert,
- M_Alerting_Result_State,
- M_Alerting_Notification_Sent,
- M_Aws_CloudWatch_GetMetricStatistics,
- M_Aws_CloudWatch_ListMetrics,
- M_Aws_CloudWatch_GetMetricData,
- M_DB_DataSource_QueryById,
- M_Alerting_Active_Alerts,
- M_StatTotal_Dashboards,
- M_StatTotal_Users,
- M_StatActive_Users,
- M_StatTotal_Orgs,
- M_StatTotal_Playlists,
- M_Grafana_Version)
- }
- func updateTotalStats() {
- statsQuery := models.GetSystemStatsQuery{}
- if err := bus.Dispatch(&statsQuery); err != nil {
- metricsLogger.Error("Failed to get system stats", "error", err)
- return
- }
- M_StatTotal_Dashboards.Set(float64(statsQuery.Result.Dashboards))
- M_StatTotal_Users.Set(float64(statsQuery.Result.Users))
- M_StatActive_Users.Set(float64(statsQuery.Result.ActiveUsers))
- M_StatTotal_Playlists.Set(float64(statsQuery.Result.Playlists))
- M_StatTotal_Orgs.Set(float64(statsQuery.Result.Orgs))
- }
- var usageStatsURL = "https://stats.grafana.org/grafana-usage-report"
- func getEdition() string {
- if setting.IsEnterprise {
- return "enterprise"
- } else {
- return "oss"
- }
- }
- func sendUsageStats(oauthProviders map[string]bool) {
- if !setting.ReportingEnabled {
- return
- }
- metricsLogger.Debug("Sending anonymous usage stats to stats.grafana.org")
- version := strings.Replace(setting.BuildVersion, ".", "_", -1)
- metrics := map[string]interface{}{}
- report := map[string]interface{}{
- "version": version,
- "metrics": metrics,
- "os": runtime.GOOS,
- "arch": runtime.GOARCH,
- "edition": getEdition(),
- }
- statsQuery := models.GetSystemStatsQuery{}
- if err := bus.Dispatch(&statsQuery); err != nil {
- metricsLogger.Error("Failed to get system stats", "error", err)
- return
- }
- metrics["stats.dashboards.count"] = statsQuery.Result.Dashboards
- metrics["stats.users.count"] = statsQuery.Result.Users
- metrics["stats.orgs.count"] = statsQuery.Result.Orgs
- metrics["stats.playlist.count"] = statsQuery.Result.Playlists
- metrics["stats.plugins.apps.count"] = len(plugins.Apps)
- metrics["stats.plugins.panels.count"] = len(plugins.Panels)
- metrics["stats.plugins.datasources.count"] = len(plugins.DataSources)
- metrics["stats.alerts.count"] = statsQuery.Result.Alerts
- metrics["stats.active_users.count"] = statsQuery.Result.ActiveUsers
- metrics["stats.datasources.count"] = statsQuery.Result.Datasources
- metrics["stats.stars.count"] = statsQuery.Result.Stars
- metrics["stats.folders.count"] = statsQuery.Result.Folders
- metrics["stats.dashboard_permissions.count"] = statsQuery.Result.DashboardPermissions
- metrics["stats.folder_permissions.count"] = statsQuery.Result.FolderPermissions
- metrics["stats.provisioned_dashboards.count"] = statsQuery.Result.ProvisionedDashboards
- metrics["stats.snapshots.count"] = statsQuery.Result.Snapshots
- metrics["stats.teams.count"] = statsQuery.Result.Teams
- dsStats := models.GetDataSourceStatsQuery{}
- if err := bus.Dispatch(&dsStats); err != nil {
- metricsLogger.Error("Failed to get datasource stats", "error", err)
- return
- }
- // send counters for each data source
- // but ignore any custom data sources
- // as sending that name could be sensitive information
- dsOtherCount := 0
- for _, dsStat := range dsStats.Result {
- if models.IsKnownDataSourcePlugin(dsStat.Type) {
- metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count
- } else {
- dsOtherCount += dsStat.Count
- }
- }
- metrics["stats.ds.other.count"] = dsOtherCount
- dsAccessStats := models.GetDataSourceAccessStatsQuery{}
- if err := bus.Dispatch(&dsAccessStats); err != nil {
- metricsLogger.Error("Failed to get datasource access stats", "error", err)
- return
- }
- // send access counters for each data source
- // but ignore any custom data sources
- // as sending that name could be sensitive information
- dsAccessOtherCount := make(map[string]int64)
- for _, dsAccessStat := range dsAccessStats.Result {
- if dsAccessStat.Access == "" {
- continue
- }
- access := strings.ToLower(dsAccessStat.Access)
- if models.IsKnownDataSourcePlugin(dsAccessStat.Type) {
- metrics["stats.ds_access."+dsAccessStat.Type+"."+access+".count"] = dsAccessStat.Count
- } else {
- old := dsAccessOtherCount[access]
- dsAccessOtherCount[access] = old + dsAccessStat.Count
- }
- }
- for access, count := range dsAccessOtherCount {
- metrics["stats.ds_access.other."+access+".count"] = count
- }
- anStats := models.GetAlertNotifierUsageStatsQuery{}
- if err := bus.Dispatch(&anStats); err != nil {
- metricsLogger.Error("Failed to get alert notification stats", "error", err)
- return
- }
- for _, stats := range anStats.Result {
- metrics["stats.alert_notifiers."+stats.Type+".count"] = stats.Count
- }
- authTypes := map[string]bool{}
- authTypes["anonymous"] = setting.AnonymousEnabled
- authTypes["basic_auth"] = setting.BasicAuthEnabled
- authTypes["ldap"] = setting.LdapEnabled
- authTypes["auth_proxy"] = setting.AuthProxyEnabled
- for provider, enabled := range oauthProviders {
- authTypes["oauth_"+provider] = enabled
- }
- for authType, enabled := range authTypes {
- enabledValue := 0
- if enabled {
- enabledValue = 1
- }
- metrics["stats.auth_enabled."+authType+".count"] = enabledValue
- }
- out, _ := json.MarshalIndent(report, "", " ")
- data := bytes.NewBuffer(out)
- client := http.Client{Timeout: 5 * time.Second}
- go client.Post(usageStatsURL, "application/json", data)
- }
|