diff --git a/command/agent/command.go b/command/agent/command.go index b1d3850b27c..53139eeea20 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -18,6 +18,7 @@ import ( metrics "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/lib" checkpoint "github.com/hashicorp/go-checkpoint" gsyslog "github.com/hashicorp/go-syslog" @@ -661,6 +662,12 @@ func (c *Command) setupTelemetry(config *Config) (*metrics.InmemSink, error) { fanout = append(fanout, sink) } + // Configure the prometheus sink + promSink, err := prometheus.NewPrometheusSink() + if err != nil { + fanout = append(fanout, promSink) + } + // Configure the datadog sink if telConfig.DataDogAddr != "" { sink, err := datadog.NewDogStatsdSink(telConfig.DataDogAddr, config.NodeName) diff --git a/command/agent/http.go b/command/agent/http.go index d37b24cdb8e..5bbc63d4b13 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -15,6 +15,8 @@ import ( "github.com/NYTimes/gziphandler" "github.com/hashicorp/nomad/helper/tlsutil" "github.com/hashicorp/nomad/nomad/structs" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/ugorji/go/codec" ) @@ -80,8 +82,15 @@ func NewHTTPServer(agent *Agent, config *Config) (*HTTPServer, error) { } srv.registerHandlers(config.EnableDebug) - // Start the server + // Handle requests with gzip compression go http.Serve(ln, gziphandler.GzipHandler(mux)) + + // Register Prometheus separately as this requires uncompressed responses + srv.registerPrometheusHandler() + + // Handle requests without gzip compression + go http.Serve(ln, mux) + return srv, nil } @@ -101,8 +110,15 @@ func newScadaHttp(agent *Agent, list net.Listener) *HTTPServer { } srv.registerHandlers(false) // Never allow debug for SCADA - // Start the server + // Handle requests with gzip compression go http.Serve(list, gziphandler.GzipHandler(mux)) + + // Register Prometheus separately as this requires uncompressed responses + srv.registerPrometheusHandler() + + // Handle requests without gzip compression + go http.Serve(list, mux) + return srv } @@ -131,6 +147,19 @@ func (s *HTTPServer) Shutdown() { } } +// Create a prometheus handler and register it separately, as other requests +// use gzip compression +func (s *HTTPServer) registerPrometheusHandler() { + handlerOptions := promhttp.HandlerOpts{ + ErrorLog: s.logger, + ErrorHandling: promhttp.ContinueOnError, + DisableCompression: true, + } + + handler := promhttp.HandlerFor(prometheus.DefaultGatherer, handlerOptions) + s.mux.Handle("/metrics", handler) +} + // registerHandlers is used to attach our handlers to the mux func (s *HTTPServer) registerHandlers(enableDebug bool) { s.mux.HandleFunc("/v1/jobs", s.wrap(s.JobsRequest)) diff --git a/command/agent/metrics_endpoint.go b/command/agent/metrics_endpoint.go index 9f3e1f57739..8f390236cdf 100644 --- a/command/agent/metrics_endpoint.go +++ b/command/agent/metrics_endpoint.go @@ -4,13 +4,10 @@ import ( "net/http" ) +// MetricsRequest returns metrics in JSON format func (s *HTTPServer) MetricsRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { if req.Method == "GET" { - return s.newMetricsRequest(resp, req) + return s.agent.InmemSink.DisplayMetrics(resp, req) } return nil, CodedError(405, ErrInvalidMethod) } - -func (s *HTTPServer) newMetricsRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { - return s.agent.InmemSink.DisplayMetrics(resp, req) -}