From fd98fb144937a7d83d391d10b55910715ddb4da0 Mon Sep 17 00:00:00 2001 From: Pierre Souchay Date: Fri, 6 Apr 2018 08:55:49 +0200 Subject: [PATCH] Added support exposing metrics in Prometheus format --- agent/agent_endpoint.go | 12 ++++++++++++ agent/config/builder.go | 1 + agent/config/config.go | 1 + agent/config/runtime.go | 5 +++++ agent/config/runtime_test.go | 4 ++++ command/agent/agent.go | 15 +++++++++++++++ 6 files changed, 38 insertions(+) diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index 0e2b4b4803..5d8970fabd 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -19,6 +19,8 @@ import ( "github.com/hashicorp/logutils" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" ) type Self struct { @@ -86,7 +88,17 @@ func (s *HTTPServer) AgentMetrics(resp http.ResponseWriter, req *http.Request) ( if rule != nil && !rule.AgentRead(s.agent.config.NodeName) { return nil, acl.ErrPermissionDenied } + if format := req.URL.Query().Get("format"); format == "prometheus" { + handlerOptions := promhttp.HandlerOpts{ + ErrorLog: s.agent.logger, + ErrorHandling: promhttp.ContinueOnError, + DisableCompression: true, + } + handler := promhttp.HandlerFor(prometheus.DefaultGatherer, handlerOptions) + handler.ServeHTTP(resp, req) + return nil, nil + } return s.agent.MemSink.DisplayMetrics(resp, req) } diff --git a/agent/config/builder.go b/agent/config/builder.go index e9cb19394c..7659180116 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -626,6 +626,7 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { TelemetryDisableHostname: b.boolVal(c.Telemetry.DisableHostname), TelemetryDogstatsdAddr: b.stringVal(c.Telemetry.DogstatsdAddr), TelemetryDogstatsdTags: c.Telemetry.DogstatsdTags, + TelemetryPrometheusDisable: b.boolVal(c.Telemetry.PrometheusDisable), TelemetryFilterDefault: b.boolVal(c.Telemetry.FilterDefault), TelemetryAllowedPrefixes: telemetryAllowedPrefixes, TelemetryBlockedPrefixes: telemetryBlockedPrefixes, diff --git a/agent/config/config.go b/agent/config/config.go index 2a14abc6b8..a481bbf4c9 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -394,6 +394,7 @@ type Telemetry struct { FilterDefault *bool `json:"filter_default,omitempty" hcl:"filter_default" mapstructure:"filter_default"` PrefixFilter []string `json:"prefix_filter,omitempty" hcl:"prefix_filter" mapstructure:"prefix_filter"` MetricsPrefix *string `json:"metrics_prefix,omitempty" hcl:"metrics_prefix" mapstructure:"metrics_prefix"` + PrometheusDisable *bool `json:"prometheus_disable,omitempty" hcl:"prometheus_disable" mapstructure:"prometheus_disable"` StatsdAddr *string `json:"statsd_address,omitempty" hcl:"statsd_address" mapstructure:"statsd_address"` StatsiteAddr *string `json:"statsite_address,omitempty" hcl:"statsite_address" mapstructure:"statsite_address"` EnableDeprecatedNames *bool `json:"enable_deprecated_names" hcl:"enable_deprecated_names" mapstructure:"enable_deprecated_names"` diff --git a/agent/config/runtime.go b/agent/config/runtime.go index f43fac24f1..e1aa1b2ebf 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -425,6 +425,11 @@ type RuntimeConfig struct { // hcl: telemetry { dogstatsd_tags = []string } TelemetryDogstatsdTags []string + // TelemetryPrometheusDisable enables prometheus Support for metrics + // + // hcl: telemetry { prometheus_disable = (true|false) } + TelemetryPrometheusDisable bool + // TelemetryFilterDefault is the default for whether to allow a metric that's not // covered by the filter. // diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index da62e0339c..e923a14f68 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2589,6 +2589,7 @@ func TestFullConfig(t *testing.T) { "prefix_filter": [ "+oJotS8XJ","-cazlEhGn" ], "enable_deprecated_names": true, "metrics_prefix": "ftO6DySn", + "prometheus_disable": true, "statsd_address": "drce87cy", "statsite_address": "HpFwKB8R" }, @@ -3026,6 +3027,7 @@ func TestFullConfig(t *testing.T) { prefix_filter = [ "+oJotS8XJ","-cazlEhGn" ] enable_deprecated_names = true metrics_prefix = "ftO6DySn" + prometheus_disable = true statsd_address = "drce87cy" statsite_address = "HpFwKB8R" } @@ -3588,6 +3590,7 @@ func TestFullConfig(t *testing.T) { TelemetryAllowedPrefixes: []string{"oJotS8XJ", "consul.consul"}, TelemetryBlockedPrefixes: []string{"cazlEhGn"}, TelemetryMetricsPrefix: "ftO6DySn", + TelemetryPrometheusDisable: true, TelemetryStatsdAddr: "drce87cy", TelemetryStatsiteAddr: "HpFwKB8R", TLSCipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, @@ -4140,6 +4143,7 @@ func TestSanitize(t *testing.T) { "TelemetryDogstatsdTags": [], "TelemetryFilterDefault": false, "TelemetryMetricsPrefix": "", + "TelemetryPrometheusDisable": false, "TelemetryStatsdAddr": "", "TelemetryStatsiteAddr": "", "TranslateWANAddrs": false, diff --git a/command/agent/agent.go b/command/agent/agent.go index 40bfbef20c..9e7867c675 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -15,6 +15,7 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-metrics/circonus" "github.com/armon/go-metrics/datadog" + "github.com/armon/go-metrics/prometheus" "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/command/flags" @@ -208,6 +209,17 @@ func dogstatdSink(config *config.RuntimeConfig, hostname string) (metrics.Metric return sink, nil } +func prometheusSink(config *config.RuntimeConfig, hostname string) (metrics.MetricSink, error) { + if config.TelemetryPrometheusDisable { + return nil, nil + } + sink, err := prometheus.NewPrometheusSink() + if err != nil { + return nil, err + } + return sink, nil +} + func circonusSink(config *config.RuntimeConfig, hostname string) (metrics.MetricSink, error) { if config.TelemetryCirconusAPIToken == "" && config.TelemetryCirconusSubmissionURL == "" { return nil, nil @@ -284,6 +296,9 @@ func startupTelemetry(conf *config.RuntimeConfig) (*metrics.InmemSink, error) { if err := addSink("circonus", circonusSink); err != nil { return nil, err } + if err := addSink("prometheus", prometheusSink); err != nil { + return nil, err + } if len(sinks) > 0 { sinks = append(sinks, memSink)