diff --git a/plugins/inputs/nginx_plus_api/README.md b/plugins/inputs/nginx_plus_api/README.md index 1669f21e2..c05dc2523 100644 --- a/plugins/inputs/nginx_plus_api/README.md +++ b/plugins/inputs/nginx_plus_api/README.md @@ -62,8 +62,9 @@ between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff-doc]. | nginx_plus_api_stream_server_zones | >= 3 | | nginx_plus_api_http_location_zones | >= 5 | | nginx_plus_api_resolver_zones | >= 5 | +| nginx_plus_api_http_limit_reqs | >= 6 | -## Measurements & Fields +## Metrics - nginx_plus_api_processes - respawned @@ -194,8 +195,14 @@ between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff-doc]. - refused - timedout - unknown +- nginx_plus_api_http_limit_reqs + - passed + - delayed + - rejected + - delayed_dry_run + - rejected_dry_run -## Tags +### Tags - nginx_plus_api_processes, nginx_plus_api_connections, nginx_plus_api_ssl, nginx_plus_api_http_requests - source @@ -228,6 +235,11 @@ between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff-doc]. - source - port +- nginx_plus_api_http_limit_reqs + - source + - port + - limit + ## Example Output Using this configuration: @@ -287,8 +299,11 @@ It produces: > nginx_plus_api_http_location_zones,port=80,source=demo.nginx.com,zone=swagger discarded=0i,received=1622i,requests=8i,responses_1xx=0i,responses_2xx=7i,responses_3xx=0i,responses_4xx=1i,responses_5xx=0i,responses_total=8i,sent=638333i 1570696323000000000 > nginx_plus_api_http_location_zones,port=80,source=demo.nginx.com,zone=api-calls discarded=64i,received=337530181i,requests=1726513i,responses_1xx=0i,responses_2xx=1726428i,responses_3xx=0i,responses_4xx=21i,responses_5xx=0i,responses_total=1726449i,sent=1902577668i 1570696323000000000 > nginx_plus_api_resolver_zones,port=80,source=demo.nginx.com,zone=resolver1 addr=0i,formerr=0i,name=0i,noerror=0i,notimp=0i,nxdomain=0i,refused=0i,servfail=0i,srv=0i,timedout=0i,unknown=0i 1570696324000000000 +> nginx_plus_api_http_limit_reqs,port=80,source=demo.nginx.com,limit=limit_1 delayed=0i,delayed_dry_run=0i,passed=6i,rejected=9i,rejected_dry_run=0i 1570696322000000000 +> nginx_plus_api_http_limit_reqs,port=80,source=demo.nginx.com,limit=limit_2 delayed=13i,delayed_dry_run=3i,passed=6i,rejected=1i,rejected_dry_run=31i 1570696322000000000 ``` ### Reference material -[api documentation](http://demo.nginx.com/swagger-ui/#/) +- [api documentation](http://demo.nginx.com/swagger-ui/#/) +- [nginx_api_module documentation](http://nginx.org/en/docs/http/ngx_http_api_module.html) diff --git a/plugins/inputs/nginx_plus_api/nginx_plus_api.go b/plugins/inputs/nginx_plus_api/nginx_plus_api.go index 069f906e3..b50ef5cf3 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api.go @@ -43,8 +43,8 @@ const ( httpLocationZonesPath = "http/location_zones" httpUpstreamsPath = "http/upstreams" httpCachesPath = "http/caches" - - resolverZonesPath = "resolvers" + httpLimitReqsPath = "http/limit_reqs" + resolverZonesPath = "resolvers" streamServerZonesPath = "stream/server_zones" streamUpstreamsPath = "stream/upstreams" 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 ab2699595..fed57d7ab 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go @@ -35,6 +35,9 @@ func (n *NginxPlusAPI) gatherMetrics(addr *url.URL, acc telegraf.Accumulator) { addError(acc, n.gatherHTTPLocationZonesMetrics(addr, acc)) addError(acc, n.gatherResolverZonesMetrics(addr, acc)) } + if n.APIVersion >= 6 { + addError(acc, n.gatherHTTPLimitReqsMetrics(addr, acc)) + } } func addError(acc telegraf.Accumulator, err error) { @@ -613,6 +616,43 @@ func (n *NginxPlusAPI) gatherStreamUpstreamsMetrics(addr *url.URL, acc telegraf. return nil } +// Added in 6 API version +func (n *NginxPlusAPI) gatherHTTPLimitReqsMetrics(addr *url.URL, acc telegraf.Accumulator) error { + body, err := n.gatherURL(addr, httpLimitReqsPath) + if err != nil { + return err + } + + var httpLimitReqs HTTPLimitReqs + + if err := json.Unmarshal(body, &httpLimitReqs); err != nil { + return err + } + + tags := getTags(addr) + + for limitReqName, limit := range httpLimitReqs { + limitReqsTags := map[string]string{} + for k, v := range tags { + limitReqsTags[k] = v + } + limitReqsTags["limit"] = limitReqName + acc.AddFields( + "nginx_plus_api_http_limit_reqs", + map[string]interface{}{ + "passed": limit.Passed, + "delayed": limit.Delayed, + "rejected": limit.Rejected, + "delayed_dry_run": limit.DelayedDryRun, + "rejected_dry_run": limit.RejectedDryRun, + }, + limitReqsTags, + ) + } + + return nil +} + func getTags(addr *url.URL) map[string]string { h := addr.Host host, port, err := net.SplitHostPort(h) 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 a1c43c645..f5efa29c3 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 @@ -245,6 +245,25 @@ const httpServerZonesPayload = ` } ` +const httpLimitReqsPayload = ` +{ + "limit_1": { + "passed": 2, + "delayed": 9, + "rejected": 4, + "delayed_dry_run": 100, + "rejected_dry_run": 330 + }, + "limit_2": { + "passed": 451, + "delayed": 10, + "rejected": 0, + "delayed_dry_run": 10, + "rejected_dry_run": 32 + } +} +` + const httpLocationZonesPayload = ` { "site1": { @@ -857,6 +876,48 @@ func TestGatherHttpServerZonesMetrics(t *testing.T) { }) } +func TestGatherHttpLimitReqsMetrics(t *testing.T) { + ts, n := prepareEndpoint(t, httpLimitReqsPath, httpLimitReqsPayload) + defer ts.Close() + + var acc testutil.Accumulator + addr, host, port := prepareAddr(t, ts) + + require.NoError(t, n.gatherHTTPLimitReqsMetrics(addr, &acc)) + + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_http_limit_reqs", + map[string]interface{}{ + "passed": int64(2), + "delayed": int64(9), + "rejected": int64(4), + "delayed_dry_run": int64(100), + "rejected_dry_run": int64(330), + }, + map[string]string{ + "source": host, + "port": port, + "limit": "limit_1", + }) + + acc.AssertContainsTaggedFields( + t, + "nginx_plus_api_http_limit_reqs", + map[string]interface{}{ + "passed": int64(451), + "delayed": int64(10), + "rejected": int64(0), + "delayed_dry_run": int64(10), + "rejected_dry_run": int64(32), + }, + map[string]string{ + "source": host, + "port": port, + "limit": "limit_2", + }) +} + func TestGatherHttpLocationZonesMetrics(t *testing.T) { ts, n := prepareEndpoint(t, httpLocationZonesPath, httpLocationZonesPayload) 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 654c3cb91..a3aa36e5f 100644 --- a/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go +++ b/plugins/inputs/nginx_plus_api/nginx_plus_api_types.go @@ -170,3 +170,11 @@ type HTTPCaches map[string]struct { // added in version 2 Expired ExtendedHitStats `json:"expired"` Bypass ExtendedHitStats `json:"bypass"` } + +type HTTPLimitReqs map[string]struct { + Passed int64 `json:"passed"` + Delayed int64 `json:"delayed"` + Rejected int64 `json:"rejected"` + DelayedDryRun int64 `json:"delayed_dry_run"` + RejectedDryRun int64 `json:"rejected_dry_run"` +}