diff options
author | Valery Piashchynski <[email protected]> | 2021-06-07 23:19:18 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2021-06-07 23:19:18 +0300 |
commit | 54a0a61485831c1848d55f65e2fb21c057ac6729 (patch) | |
tree | eee1c293f46cd65ec628da3a1b557cd142f3eabd /plugins/http | |
parent | 0a48df5e5e44aaefa503669d7fb75490f1be103f (diff) |
- Add metrics exporter for the workers
- Add metrics for the request duration and request count
- Add tests
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'plugins/http')
-rw-r--r-- | plugins/http/metrics.go | 92 | ||||
-rw-r--r-- | plugins/http/plugin.go | 15 |
2 files changed, 104 insertions, 3 deletions
diff --git a/plugins/http/metrics.go b/plugins/http/metrics.go new file mode 100644 index 00000000..d7a9110b --- /dev/null +++ b/plugins/http/metrics.go @@ -0,0 +1,92 @@ +package http + +import ( + "strconv" + + "github.com/prometheus/client_golang/prometheus" + handler "github.com/spiral/roadrunner/v2/pkg/worker_handler" +) + +func (p *Plugin) MetricsCollector() []prometheus.Collector { + // p - implements Exporter interface (workers) + // other - request duration and count + return []prometheus.Collector{p, p.requestsExporter.requestDuration, p.requestsExporter.requestCounter} +} + +func (p *Plugin) metricsCallback(event interface{}) { + switch e := event.(type) { + case handler.ResponseEvent: + p.requestsExporter.requestCounter.With(prometheus.Labels{ + "status": strconv.Itoa(e.Response.Status), + }).Inc() + + p.requestsExporter.requestDuration.With(prometheus.Labels{ + "status": strconv.Itoa(e.Response.Status), + }).Observe(e.Elapsed().Seconds()) + case handler.ErrorEvent: + p.requestsExporter.requestCounter.With(prometheus.Labels{ + "status": "500", + }).Inc() + + p.requestsExporter.requestDuration.With(prometheus.Labels{ + "status": "500", + }).Observe(e.Elapsed().Seconds()) + } +} + +type workersExporter struct { + wm *prometheus.Desc + workersMemory uint64 +} + +func newWorkersExporter() *workersExporter { + return &workersExporter{ + wm: prometheus.NewDesc("rr_http_workers_memory_bytes", "Memory usage by HTTP workers.", nil, nil), + workersMemory: 0, + } +} + +func (p *Plugin) Describe(d chan<- *prometheus.Desc) { + // send description + d <- p.workersExporter.wm +} + +func (p *Plugin) Collect(ch chan<- prometheus.Metric) { + // get the copy of the processes + workers := p.Workers() + + // cumulative RSS memory in bytes + var cum uint64 + + // collect the memory + for i := 0; i < len(workers); i++ { + cum += workers[i].MemoryUsage + } + + // send the values to the prometheus + ch <- prometheus.MustNewConstMetric(p.workersExporter.wm, prometheus.GaugeValue, float64(cum)) +} + +type requestsExporter struct { + requestCounter *prometheus.CounterVec + requestDuration *prometheus.HistogramVec +} + +func newRequestsExporter() *requestsExporter { + return &requestsExporter{ + requestCounter: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "rr_http_request_total", + Help: "Total number of handled http requests after server restart.", + }, + []string{"status"}, + ), + requestDuration: prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "rr_http_request_duration_seconds", + Help: "HTTP request duration.", + }, + []string{"status"}, + ), + } +} diff --git a/plugins/http/plugin.go b/plugins/http/plugin.go index ba83344a..bec01ac3 100644 --- a/plugins/http/plugin.go +++ b/plugins/http/plugin.go @@ -62,6 +62,10 @@ type Plugin struct { // servers RR handler handler *handler.Handler + // metrics + workersExporter *workersExporter + requestsExporter *requestsExporter + // servers http *http.Server https *http.Server @@ -102,6 +106,11 @@ func (p *Plugin) Init(cfg config.Configurer, rrLogger logger.Logger, server serv p.cfg.Env = make(map[string]string) } + // initialize workersExporter + p.workersExporter = newWorkersExporter() + // initialize requests exporter + p.requestsExporter = newRequestsExporter() + p.cfg.Env[RrMode] = "http" p.server = server @@ -159,7 +168,7 @@ func (p *Plugin) serve(errCh chan error) { return } - p.handler.AddListener(p.logCallback) + p.handler.AddListener(p.logCallback, p.metricsCallback) if p.cfg.EnableHTTP() { if p.cfg.EnableH2C() { @@ -341,7 +350,7 @@ func (p *Plugin) Reset() error { } p.log.Info("HTTP handler listeners successfully re-added") - p.handler.AddListener(p.logCallback) + p.handler.AddListener(p.logCallback, p.metricsCallback) p.log.Info("HTTP plugin successfully restarted") return nil @@ -386,7 +395,7 @@ func (p *Plugin) Ready() status.Status { workers := p.workers() for i := 0; i < len(workers); i++ { // If state of the worker is ready (at least 1) - // we assume, that plugin'p worker pool is ready + // we assume, that plugin's worker pool is ready if workers[i].State().Value() == worker.StateReady { return status.Status{ Code: http.StatusOK, |