feat(inputs.nginx_plus_api): Gather limit_reqs metrics (#10874)
This commit is contained in:
parent
8f789c5cd8
commit
c91eacda42
|
|
@ -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_stream_server_zones | >= 3 |
|
||||||
| nginx_plus_api_http_location_zones | >= 5 |
|
| nginx_plus_api_http_location_zones | >= 5 |
|
||||||
| nginx_plus_api_resolver_zones | >= 5 |
|
| nginx_plus_api_resolver_zones | >= 5 |
|
||||||
|
| nginx_plus_api_http_limit_reqs | >= 6 |
|
||||||
|
|
||||||
## Measurements & Fields
|
## Metrics
|
||||||
|
|
||||||
- nginx_plus_api_processes
|
- nginx_plus_api_processes
|
||||||
- respawned
|
- respawned
|
||||||
|
|
@ -194,8 +195,14 @@ between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff-doc].
|
||||||
- refused
|
- refused
|
||||||
- timedout
|
- timedout
|
||||||
- unknown
|
- 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
|
- nginx_plus_api_processes, nginx_plus_api_connections, nginx_plus_api_ssl, nginx_plus_api_http_requests
|
||||||
- source
|
- source
|
||||||
|
|
@ -228,6 +235,11 @@ between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff-doc].
|
||||||
- source
|
- source
|
||||||
- port
|
- port
|
||||||
|
|
||||||
|
- nginx_plus_api_http_limit_reqs
|
||||||
|
- source
|
||||||
|
- port
|
||||||
|
- limit
|
||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
Using this configuration:
|
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=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_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_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
|
### 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)
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ const (
|
||||||
httpLocationZonesPath = "http/location_zones"
|
httpLocationZonesPath = "http/location_zones"
|
||||||
httpUpstreamsPath = "http/upstreams"
|
httpUpstreamsPath = "http/upstreams"
|
||||||
httpCachesPath = "http/caches"
|
httpCachesPath = "http/caches"
|
||||||
|
httpLimitReqsPath = "http/limit_reqs"
|
||||||
resolverZonesPath = "resolvers"
|
resolverZonesPath = "resolvers"
|
||||||
|
|
||||||
streamServerZonesPath = "stream/server_zones"
|
streamServerZonesPath = "stream/server_zones"
|
||||||
streamUpstreamsPath = "stream/upstreams"
|
streamUpstreamsPath = "stream/upstreams"
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ func (n *NginxPlusAPI) gatherMetrics(addr *url.URL, acc telegraf.Accumulator) {
|
||||||
addError(acc, n.gatherHTTPLocationZonesMetrics(addr, acc))
|
addError(acc, n.gatherHTTPLocationZonesMetrics(addr, acc))
|
||||||
addError(acc, n.gatherResolverZonesMetrics(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) {
|
func addError(acc telegraf.Accumulator, err error) {
|
||||||
|
|
@ -613,6 +616,43 @@ func (n *NginxPlusAPI) gatherStreamUpstreamsMetrics(addr *url.URL, acc telegraf.
|
||||||
return nil
|
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 {
|
func getTags(addr *url.URL) map[string]string {
|
||||||
h := addr.Host
|
h := addr.Host
|
||||||
host, port, err := net.SplitHostPort(h)
|
host, port, err := net.SplitHostPort(h)
|
||||||
|
|
|
||||||
|
|
@ -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 = `
|
const httpLocationZonesPayload = `
|
||||||
{
|
{
|
||||||
"site1": {
|
"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) {
|
func TestGatherHttpLocationZonesMetrics(t *testing.T) {
|
||||||
ts, n := prepareEndpoint(t, httpLocationZonesPath, httpLocationZonesPayload)
|
ts, n := prepareEndpoint(t, httpLocationZonesPath, httpLocationZonesPayload)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
|
||||||
|
|
@ -170,3 +170,11 @@ type HTTPCaches map[string]struct { // added in version 2
|
||||||
Expired ExtendedHitStats `json:"expired"`
|
Expired ExtendedHitStats `json:"expired"`
|
||||||
Bypass ExtendedHitStats `json:"bypass"`
|
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"`
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue