summaryrefslogtreecommitdiff
path: root/plugins/http
diff options
context:
space:
mode:
authorValery Piashchynski <[email protected]>2021-06-07 23:19:18 +0300
committerValery Piashchynski <[email protected]>2021-06-07 23:19:18 +0300
commit54a0a61485831c1848d55f65e2fb21c057ac6729 (patch)
treeeee1c293f46cd65ec628da3a1b557cd142f3eabd /plugins/http
parent0a48df5e5e44aaefa503669d7fb75490f1be103f (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.go92
-rw-r--r--plugins/http/plugin.go15
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,