From be144a5d96815850f10d81473dbb88fd0a84a897 Mon Sep 17 00:00:00 2001 From: glennlod <81913666+glennlod@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:18:13 +0200 Subject: [PATCH] feat(inputs.nginx_plus_api): Gather slab metrics (#10448) --- plugins/inputs/nginx_plus_api/README.md | 24 ++- .../inputs/nginx_plus_api/nginx_plus_api.go | 1 + .../nginx_plus_api/nginx_plus_api_metrics.go | 54 +++++ .../nginx_plus_api_metrics_test.go | 194 ++++++++++++++++++ .../nginx_plus_api/nginx_plus_api_types.go | 13 ++ 5 files changed, 285 insertions(+), 1 deletion(-) diff --git a/plugins/inputs/nginx_plus_api/README.md b/plugins/inputs/nginx_plus_api/README.md index 04a7a413be4c5..1ef0af51ee066 100644 --- a/plugins/inputs/nginx_plus_api/README.md +++ b/plugins/inputs/nginx_plus_api/README.md @@ -46,6 +46,8 @@ Nginx Plus is a commercial version of the open source web server Nginx. The use | nginx_plus_api_processes | >= 3 | | nginx_plus_api_connections | >= 3 | | nginx_plus_api_ssl | >= 3 | +| nginx_plus_api_slabs_pages | >= 3 | +| nginx_plus_api_slabs_slots | >= 3 | | nginx_plus_api_http_requests | >= 3 | | nginx_plus_api_http_server_zones | >= 3 | | nginx_plus_api_http_upstreams | >= 3 | @@ -66,6 +68,14 @@ Nginx Plus is a commercial version of the open source web server Nginx. The use - dropped - active - idle +- nginx_plus_api_slabs_pages + - used + - free +- nginx_plus_api_slabs_slots + - used + - free + - reqs + - fails - nginx_plus_api_ssl - handshakes - handshakes_failed @@ -192,10 +202,16 @@ Nginx Plus is a commercial version of the open source web server Nginx. The use - source - port -- nginx_plus_api_http_server_zones, nginx_plus_api_upstream_server_zones, nginx_plus_api_http_location_zones, nginx_plus_api_resolver_zones +- nginx_plus_api_http_server_zones, nginx_plus_api_upstream_server_zones, nginx_plus_api_http_location_zones, nginx_plus_api_resolver_zones, nginx_plus_api_slabs_pages + - source + - port + - zone + +- nginx_plus_api_slabs_slots - source - port - zone + - slot - nginx_plus_api_upstream_peers, nginx_plus_api_stream_upstream_peers - id @@ -229,6 +245,12 @@ It produces: ```text > nginx_plus_api_processes,port=80,source=demo.nginx.com respawned=0i 1570696321000000000 > nginx_plus_api_connections,port=80,source=demo.nginx.com accepted=68998606i,active=7i,dropped=0i,idle=57i 1570696322000000000 +> nginx_plus_api_slabs_pages,port=80,source=demo.nginx.com,zone=hg.nginx.org used=1i,free=503i 1570696322000000000 +> nginx_plus_api_slabs_pages,port=80,source=demo.nginx.com,zone=trac.nginx.org used=3i,free=500i 1570696322000000000 +> nginx_plus_api_slabs_slots,port=80,source=demo.nginx.com,zone=hg.nginx.org,slot=8 used=1i,free=503i,reqs=10i,fails=0i 1570696322000000000 +> nginx_plus_api_slabs_slots,port=80,source=demo.nginx.com,zone=hg.nginx.org,slot=16 used=3i,free=500i,reqs=1024i,fails=0i 1570696322000000000 +> nginx_plus_api_slabs_slots,port=80,source=demo.nginx.com,zone=trac.nginx.org,slot=8 used=1i,free=503i,reqs=10i,fails=0i 1570696322000000000 +> nginx_plus_api_slabs_slots,port=80,source=demo.nginx.com,zone=trac.nginx.org,slot=16 used=0i,free=1520i,reqs=0i,fails=1i 1570696322000000000 > nginx_plus_api_ssl,port=80,source=demo.nginx.com handshakes=9398978i,handshakes_failed=289353i,session_reuses=1004389i 1570696322000000000 > nginx_plus_api_http_requests,port=80,source=demo.nginx.com current=51i,total=264649353i 1570696322000000000 > nginx_plus_api_http_server_zones,port=80,source=demo.nginx.com,zone=hg.nginx.org discarded=5i,processing=0i,received=24123604i,requests=60138i,responses_1xx=0i,responses_2xx=59353i,responses_3xx=531i,responses_4xx=249i,responses_5xx=0i,responses_total=60133i,sent=830165221i 1570696322000000000 diff --git a/plugins/inputs/nginx_plus_api/nginx_plus_api.go b/plugins/inputs/nginx_plus_api/nginx_plus_api.go index ab3f196fa50c1..069f906e314f7 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api.go @@ -35,6 +35,7 @@ const ( // Paths processesPath = "processes" connectionsPath = "connections" + slabsPath = "slabs" sslPath = "ssl" httpRequestsPath = "http/requests" diff --git a/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go b/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go index 81f747d86d825..ab2699595e8d0 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go @@ -22,6 +22,7 @@ var ( func (n *NginxPlusAPI) gatherMetrics(addr *url.URL, acc telegraf.Accumulator) { addError(acc, n.gatherProcessesMetrics(addr, acc)) addError(acc, n.gatherConnectionsMetrics(addr, acc)) + addError(acc, n.gatherSlabsMetrics(addr, acc)) addError(acc, n.gatherSslMetrics(addr, acc)) addError(acc, n.gatherHTTPRequestsMetrics(addr, acc)) addError(acc, n.gatherHTTPServerZonesMetrics(addr, acc)) @@ -130,6 +131,59 @@ func (n *NginxPlusAPI) gatherConnectionsMetrics(addr *url.URL, acc telegraf.Accu return nil } +func (n *NginxPlusAPI) gatherSlabsMetrics(addr *url.URL, acc telegraf.Accumulator) error { + body, err := n.gatherURL(addr, slabsPath) + if err != nil { + return err + } + + var slabs Slabs + + if err := json.Unmarshal(body, &slabs); err != nil { + return err + } + + tags := getTags(addr) + + for zoneName, slab := range slabs { + slabTags := map[string]string{} + for k, v := range tags { + slabTags[k] = v + } + slabTags["zone"] = zoneName + + acc.AddFields( + "nginx_plus_api_slabs_pages", + map[string]interface{}{ + "used": slab.Pages.Used, + "free": slab.Pages.Free, + }, + slabTags, + ) + + for slotID, slot := range slab.Slots { + slotTags := map[string]string{} + for k, v := range slabTags { + slotTags[k] = v + } + slotTags["slot"] = slotID + + acc.AddFields( + "nginx_plus_api_slabs_slots", + map[string]interface{}{ + "used": slot.Used, + "free": slot.Free, + "reqs": slot.Reqs, + "fails": slot.Fails, + }, + slotTags, + ) + } + } + + return nil +} + func (n *NginxPlusAPI) gatherSslMetrics(addr *url.URL, acc telegraf.Accumulator) error { body, err := n.gatherURL(addr, sslPath) if err != nil { diff --git a/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go b/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go index 8f28772537288..a1c43c645a349 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go @@ -27,6 +27,135 @@ const connectionsPayload = ` } ` +const slabsPayload = ` +{ + "zone1":{ + "pages":{ + "used":7, + "free":56 + }, + "slots":{ + "8":{ + "used":1, + "free":503, + "reqs":1, + "fails":0 + }, + "16":{ + "used":1, + "free":253, + "reqs":1, + "fails":0 + }, + "32":{ + "used":3, + "free":124, + "reqs":3, + "fails":0 + }, + "64":{ + "used":3, + "free":61, + "reqs":3, + "fails":0 + }, + "128":{ + "used":6, + "free":26, + "reqs":6, + "fails":0 + }, + "256":{ + "used":0, + "free":0, + "reqs":0, + "fails":0 + }, + "512":{ + "used":2, + "free":6, + "reqs":2, + "fails":0 + }, + "1024":{ + "used":2, + "free":2, + "reqs":2, + "fails":0 + }, + "2048":{ + "used":0, + "free":0, + "reqs":0, + "fails":0 + } + } + }, + "zone2":{ + "pages":{ + "used":2218, + "free":252290 + }, + "slots":{ + "8":{ + "used":1, + "free":503, + "reqs":4, + "fails":0 + }, + "16":{ + "used":0, + "free":0, + "reqs":0, + "fails":0 + }, + "32":{ + "used":8, + "free":119, + "reqs":98, + "fails":0 + }, + "64":{ + "used":10899, + "free":45, + "reqs":124255, + "fails":0 + }, + "128":{ + "used":1, + "free":31, + "reqs":1, + "fails":0 + }, + "256":{ + "used":10901, + "free":11, + "reqs":124270, + "fails":0 + }, + "512":{ + "used":10893, + "free":3, + "reqs":124245, + "fails":0 + }, + "1024":{ + "used":0, + "free":0, + "reqs":0, + "fails":0 + }, + "2048":{ + "used":0, + "free":0, + "reqs":10, + "fails":0 + } + } + } +} +` + const sslPayload = ` { "handshakes": 79572, @@ -564,6 +693,71 @@ func TestGatherConnectionsMetrics(t *testing.T) { }) } +func TestGatherSlabsMetrics(t *testing.T) { + ts, n := prepareEndpoint(t, slabsPath, slabsPayload) + defer ts.Close() + + var acc testutil.Accumulator + addr, host, port := prepareAddr(t, ts) + + require.NoError(t, n.gatherSlabsMetrics(addr, &acc)) + + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_slabs_pages", + map[string]interface{}{ + "used": int64(7), + "free": int64(56), + }, + map[string]string{ + "source": host, + "port": port, + "zone": "zone1", + }) + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_slabs_pages", + map[string]interface{}{ + "used": int64(2218), + "free": int64(252290), + }, + map[string]string{ + "source": host, + "port": port, + "zone": "zone2", + }) + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_slabs_slots", + map[string]interface{}{ + "used": int64(1), + "free": int64(503), + "reqs": int64(1), + "fails": int64(0), + }, + map[string]string{ + "source": host, + "port": port, + "zone": "zone1", + "slot": "8", + }) + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_slabs_slots", + map[string]interface{}{ + "used": int64(10893), + "free": int64(3), + "reqs": int64(124245), + "fails": int64(0), + }, + map[string]string{ + "source": host, + "port": port, + "zone": "zone2", + "slot": "512", + }) +} + func TestGatherSslMetrics(t *testing.T) { ts, n := prepareEndpoint(t, sslPath, sslPayload) defer ts.Close() diff --git a/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go b/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go index 51ada5fd9f46f..654c3cb91ecad 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go @@ -11,6 +11,19 @@ type Connections struct { Idle int64 `json:"idle"` } +type Slabs map[string]struct { + Pages struct { + Used int64 `json:"used"` + Free int64 `json:"free"` + } `json:"pages"` + Slots map[string]struct { + Used int64 `json:"used"` + Free int64 `json:"free"` + Reqs int64 `json:"reqs"` + Fails int64 `json:"fails"` + } `json:"slots"` +} + type Ssl struct { // added in version 6 Handshakes int64 `json:"handshakes"` HandshakesFailed int64 `json:"handshakes_failed"`