From 89ebb97fcaa22488f5d56911e6703360899b56ae Mon Sep 17 00:00:00 2001 From: Carl Bergquist Date: Mon, 19 Oct 2020 16:58:16 +0200 Subject: [PATCH] Instrumentation: Adds environment_info metric (#28355) Signed-off-by: bergquist Co-authored-by: Arve Knudsen --- conf/defaults.ini | 6 +++ conf/sample.ini | 6 +++ docs/sources/administration/configuration.md | 13 +++++- pkg/infra/metrics/metrics.go | 20 +++++++++ pkg/server/server.go | 4 ++ pkg/setting/setting.go | 44 ++++++++++++++++---- 6 files changed, 84 insertions(+), 9 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 855f1b90072..750cc23a329 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -670,6 +670,12 @@ disable_total_stats = false basic_auth_username = basic_auth_password = +# Metrics environment info adds dimensions to the `grafana_environment_info` metric, which +# can expose more information about the Grafana instance. +[metrics.environment_info] +#exampleLabel1 = exampleValue1 +#exampleLabel2 = exampleValue2 + # Send internal Grafana metrics to graphite [metrics.graphite] # Enable by setting the address setting (ex localhost:2003) diff --git a/conf/sample.ini b/conf/sample.ini index 41c5e96a853..1ebd84a236f 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -664,6 +664,12 @@ ; basic_auth_username = ; basic_auth_password = +# Metrics environment info adds dimensions to the `grafana_environment_info` metric, which +# can expose more information about the Grafana instance. +[metrics.environment_info] +#exampleLabel1 = exampleValue1 +#exampleLabel2 = exampleValue2 + # Send internal metrics to Graphite [metrics.graphite] # Enable by setting the address setting (ex localhost:2003) diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index cf95a3eb508..e7bbdcb8827 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -399,7 +399,7 @@ The length of time that Grafana will wait for a successful TLS handshake with th ### expect_continue_timeout_seconds -The length of time that Grafana will wait for a datasource’s first response headers after fully writing the request headers, if the request has an “Expect: 100-continue” header. A value of `0` will result in the body being sent immediately. Default is `1` second. For more details check the [Transport.ExpectContinueTimeout](https://golang.org/pkg/net/http/#Transport.ExpectContinueTimeout) documentation. +The length of time that Grafana will wait for a datasource’s first response headers after fully writing the request headers, if the request has an “Expect: 100-continue” header. A value of `0` will result in the body being sent immediately. Default is `1` second. For more details check the [Transport.ExpectContinueTimeout](https://golang.org/pkg/net/http/#Transport.ExpectContinueTimeout) documentation. ### max_idle_connections @@ -625,7 +625,7 @@ Default is `false`. ### user_invite_max_lifetime_duration -The duration in time a user invitation remains valid before expiring. +The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is `24h` (24 hours). The minimum supported duration is `15m` (15 minutes). @@ -1075,6 +1075,15 @@ If both are set, then basic authentication is required to access the metrics end
+## [metrics.environment_info] + +Adds dimensions to the `grafana_environment_info` metric, which can expose more information about the Grafana instance. + +``` +; exampleLabel1 = exampleValue1 +; exampleLabel2 = exampleValue2 +``` + ## [metrics.graphite] Use these options if you want to send internal Grafana metrics to Graphite. diff --git a/pkg/infra/metrics/metrics.go b/pkg/infra/metrics/metrics.go index 31d2fcb4182..edaf70ceef5 100644 --- a/pkg/infra/metrics/metrics.go +++ b/pkg/infra/metrics/metrics.go @@ -513,6 +513,26 @@ func SetBuildInformation(version, revision, branch string) { grafanaBuildVersion.WithLabelValues(version, revision, branch, runtime.Version(), edition).Set(1) } +// SetEnvironmentInformation exposes environment values provided by the operators as an `_info` metric. +// If there are no environment metrics labels configured, this metric will not be exposed. +func SetEnvironmentInformation(labels map[string]string) error { + if len(labels) == 0 { + return nil + } + + grafanaEnvironmentInfo := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "environment_info", + Help: "A metric with a constant '1' value labeled by environment information about the running instance.", + Namespace: ExporterName, + ConstLabels: labels, + }) + + prometheus.MustRegister(grafanaEnvironmentInfo) + + grafanaEnvironmentInfo.Set(1) + return nil +} + func SetPluginBuildInformation(pluginID, pluginType, version string) { grafanaPluginBuildInfoDesc.WithLabelValues(pluginID, pluginType, version).Set(1) } diff --git a/pkg/server/server.go b/pkg/server/server.go index feeaabc961b..b272e100352 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -22,6 +22,7 @@ import ( _ "github.com/grafana/grafana/pkg/extensions" "github.com/grafana/grafana/pkg/infra/localcache" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/metrics" _ "github.com/grafana/grafana/pkg/infra/metrics" _ "github.com/grafana/grafana/pkg/infra/remotecache" _ "github.com/grafana/grafana/pkg/infra/serverlock" @@ -117,6 +118,9 @@ func (s *Server) init(cfg *Config) error { s.loadConfiguration() s.writePIDFile() + if err := metrics.SetEnvironmentInformation(s.cfg.MetricsGrafanaEnvironmentInfo); err != nil { + return err + } login.Init() social.NewOAuthService() diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index c6d1d6f5aa8..6dddd32cc94 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -17,6 +17,7 @@ import ( "time" "github.com/go-macaron/session" + "github.com/prometheus/common/model" ini "gopkg.in/ini.v1" "github.com/grafana/grafana/pkg/components/gtime" @@ -267,17 +268,20 @@ type Cfg struct { CookieSameSiteDisabled bool CookieSameSiteMode http.SameSite - TempDataLifetime time.Duration + TempDataLifetime time.Duration + PluginsEnableAlpha bool + PluginsAppsSkipVerifyTLS bool + PluginSettings PluginSettings + PluginsAllowUnsigned []string + DisableSanitizeHtml bool + EnterpriseLicensePath string + + // Metrics MetricsEndpointEnabled bool MetricsEndpointBasicAuthUsername string MetricsEndpointBasicAuthPassword string MetricsEndpointDisableTotalStats bool - PluginsEnableAlpha bool - PluginsAppsSkipVerifyTLS bool - PluginSettings PluginSettings - PluginsAllowUnsigned []string - DisableSanitizeHtml bool - EnterpriseLicensePath string + MetricsGrafanaEnvironmentInfo map[string]string // Dashboards DefaultHomeDashboardPath string @@ -411,6 +415,29 @@ func applyEnvVariableOverrides(file *ini.File) error { return nil } +func (cfg *Cfg) readGrafanaEnvironmentMetrics() error { + environmentMetricsSection := cfg.Raw.Section("metrics.environment_info") + keys := environmentMetricsSection.Keys() + cfg.MetricsGrafanaEnvironmentInfo = make(map[string]string, len(keys)) + + for _, key := range keys { + labelName := model.LabelName(key.Name()) + labelValue := model.LabelValue(key.Value()) + + if !labelName.IsValid() { + return fmt.Errorf("invalid label name in [metrics.environment_info] configuration. name %q", labelName) + } + + if !labelValue.IsValid() { + return fmt.Errorf("invalid label value in [metrics.environment_info] configuration. name %q value %q", labelName, labelValue) + } + + cfg.MetricsGrafanaEnvironmentInfo[string(labelName)] = string(labelValue) + } + + return nil +} + func (cfg *Cfg) readAnnotationSettings() { dashboardAnnotation := cfg.Raw.Section("annotations.dashboard") apiIAnnotation := cfg.Raw.Section("annotations.api") @@ -781,6 +808,9 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error { cfg.readSmtpSettings() cfg.readQuotaSettings() cfg.readAnnotationSettings() + if err := cfg.readGrafanaEnvironmentMetrics(); err != nil { + return err + } if VerifyEmailEnabled && !cfg.Smtp.Enabled { log.Warnf("require_email_validation is enabled but smtp is disabled")