Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
329
plugins/inputs/nginx_plus_api/README.md
Normal file
329
plugins/inputs/nginx_plus_api/README.md
Normal file
|
@ -0,0 +1,329 @@
|
|||
# Nginx Plus API Input Plugin
|
||||
|
||||
This plugin gathers metrics from the commercial
|
||||
[Nginx Plus web server][nginx_plus] via the [REST API][api].
|
||||
|
||||
> [!NOTE]
|
||||
> Using this plugin requires a license.
|
||||
|
||||
For more information about differences between Nginx (F/OSS) and Nginx Plus, see
|
||||
the Nginx [documentation][diff_doc].
|
||||
|
||||
⭐ Telegraf v1.9.0
|
||||
🏷️ server, web
|
||||
💻 all
|
||||
|
||||
[nginx_plus]: https://www.f5.com/products/nginx/nginx-plus
|
||||
[api]: https://demo.nginx.com/swagger-ui/
|
||||
[diff_doc]: https://www.nginx.com/blog/whats-difference-nginx-foss-nginx-plus/
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Read Nginx Plus API advanced status information
|
||||
[[inputs.nginx_plus_api]]
|
||||
## An array of Nginx API URIs to gather stats.
|
||||
urls = ["http://localhost/api"]
|
||||
# Nginx API version, default: 3
|
||||
# api_version = 3
|
||||
|
||||
# HTTP response timeout (default: 5s)
|
||||
response_timeout = "5s"
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
||||
```
|
||||
|
||||
## Migration from Nginx Plus (Status) input plugin
|
||||
|
||||
| Nginx Plus | Nginx Plus API |
|
||||
|---------------------------------|--------------------------------------|
|
||||
| nginx_plus_processes | nginx_plus_api_processes |
|
||||
| nginx_plus_connections | nginx_plus_api_connections |
|
||||
| nginx_plus_ssl | nginx_plus_api_ssl |
|
||||
| nginx_plus_requests | nginx_plus_api_http_requests |
|
||||
| nginx_plus_zone | nginx_plus_api_http_server_zones |
|
||||
| nginx_plus_upstream | nginx_plus_api_http_upstreams |
|
||||
| nginx_plus_upstream_peer | nginx_plus_api_http_upstream_peers |
|
||||
| nginx_plus_cache | nginx_plus_api_http_caches |
|
||||
| nginx_plus_stream_upstream | nginx_plus_api_stream_upstreams |
|
||||
| nginx_plus_stream_upstream_peer | nginx_plus_api_stream_upstream_peers |
|
||||
| nginx.stream.zone | nginx_plus_api_stream_server_zones |
|
||||
|
||||
## Measurements by API version
|
||||
|
||||
| Measurement | API version (api_version) |
|
||||
|--------------------------------------|---------------------------|
|
||||
| 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 |
|
||||
| nginx_plus_api_http_upstream_peers | >= 3 |
|
||||
| nginx_plus_api_http_caches | >= 3 |
|
||||
| nginx_plus_api_stream_upstreams | >= 3 |
|
||||
| nginx_plus_api_stream_upstream_peers | >= 3 |
|
||||
| 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 |
|
||||
|
||||
## Metrics
|
||||
|
||||
- nginx_plus_api_processes
|
||||
- respawned
|
||||
- nginx_plus_api_connections
|
||||
- accepted
|
||||
- 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
|
||||
- session_reuses
|
||||
- nginx_plus_api_http_requests
|
||||
- total
|
||||
- current
|
||||
- nginx_plus_api_http_server_zones
|
||||
- processing
|
||||
- requests
|
||||
- responses_1xx
|
||||
- responses_2xx
|
||||
- responses_3xx
|
||||
- responses_4xx
|
||||
- responses_5xx
|
||||
- responses_total
|
||||
- received
|
||||
- sent
|
||||
- discarded
|
||||
- nginx_plus_api_http_upstreams
|
||||
- keepalive
|
||||
- zombies
|
||||
- nginx_plus_api_http_upstream_peers
|
||||
- requests
|
||||
- unavail
|
||||
- healthchecks_checks
|
||||
- header_time
|
||||
- state
|
||||
- response_time
|
||||
- active
|
||||
- healthchecks_last_passed
|
||||
- weight
|
||||
- responses_1xx
|
||||
- responses_2xx
|
||||
- responses_3xx
|
||||
- responses_4xx
|
||||
- responses_5xx
|
||||
- received
|
||||
- healthchecks_fails
|
||||
- healthchecks_unhealthy
|
||||
- backup
|
||||
- responses_total
|
||||
- sent
|
||||
- fails
|
||||
- downtime
|
||||
- nginx_plus_api_http_caches
|
||||
- size
|
||||
- max_size
|
||||
- cold
|
||||
- hit_responses
|
||||
- hit_bytes
|
||||
- stale_responses
|
||||
- stale_bytes
|
||||
- updating_responses
|
||||
- updating_bytes
|
||||
- revalidated_responses
|
||||
- revalidated_bytes
|
||||
- miss_responses
|
||||
- miss_bytes
|
||||
- miss_responses_written
|
||||
- miss_bytes_written
|
||||
- expired_responses
|
||||
- expired_bytes
|
||||
- expired_responses_written
|
||||
- expired_bytes_written
|
||||
- bypass_responses
|
||||
- bypass_bytes
|
||||
- bypass_responses_written
|
||||
- bypass_bytes_written
|
||||
- nginx_plus_api_stream_upstreams
|
||||
- zombies
|
||||
- nginx_plus_api_stream_upstream_peers
|
||||
- unavail
|
||||
- healthchecks_checks
|
||||
- healthchecks_fails
|
||||
- healthchecks_unhealthy
|
||||
- healthchecks_last_passed
|
||||
- response_time
|
||||
- state
|
||||
- active
|
||||
- weight
|
||||
- received
|
||||
- backup
|
||||
- sent
|
||||
- fails
|
||||
- downtime
|
||||
- nginx_plus_api_stream_server_zones
|
||||
- processing
|
||||
- connections
|
||||
- received
|
||||
- sent
|
||||
- nginx_plus_api_location_zones
|
||||
- requests
|
||||
- responses_1xx
|
||||
- responses_2xx
|
||||
- responses_3xx
|
||||
- responses_4xx
|
||||
- responses_5xx
|
||||
- responses_total
|
||||
- received
|
||||
- sent
|
||||
- discarded
|
||||
- nginx_plus_api_resolver_zones
|
||||
- name
|
||||
- srv
|
||||
- addr
|
||||
- noerror
|
||||
- formerr
|
||||
- servfail
|
||||
- nxdomain
|
||||
- notimp
|
||||
- refused
|
||||
- timedout
|
||||
- unknown
|
||||
- nginx_plus_api_http_limit_reqs
|
||||
- passed
|
||||
- delayed
|
||||
- rejected
|
||||
- delayed_dry_run
|
||||
- rejected_dry_run
|
||||
|
||||
### Tags
|
||||
|
||||
- nginx_plus_api_processes, nginx_plus_api_connections, nginx_plus_api_ssl, nginx_plus_api_http_requests
|
||||
- source
|
||||
- port
|
||||
|
||||
- nginx_plus_api_http_upstreams, nginx_plus_api_stream_upstreams
|
||||
- upstream
|
||||
- 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_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
|
||||
- upstream
|
||||
- source
|
||||
- port
|
||||
- upstream_address
|
||||
|
||||
- nginx_plus_api_http_caches
|
||||
- source
|
||||
- port
|
||||
|
||||
- nginx_plus_api_http_limit_reqs
|
||||
- source
|
||||
- port
|
||||
- limit
|
||||
|
||||
## Example Output
|
||||
|
||||
Using this configuration:
|
||||
|
||||
```toml
|
||||
[[inputs.nginx_plus_api]]
|
||||
## An array of Nginx Plus API URIs to gather stats.
|
||||
urls = ["http://localhost/api"]
|
||||
```
|
||||
|
||||
When run with:
|
||||
|
||||
```sh
|
||||
./telegraf -config telegraf.conf -input-filter nginx_plus_api -test
|
||||
```
|
||||
|
||||
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
|
||||
nginx_plus_api_http_server_zones,port=80,source=demo.nginx.com,zone=trac.nginx.org discarded=250i,processing=0i,received=2184618i,requests=12404i,responses_1xx=0i,responses_2xx=8579i,responses_3xx=2513i,responses_4xx=583i,responses_5xx=479i,responses_total=12154i,sent=139384159i 1570696322000000000
|
||||
nginx_plus_api_http_server_zones,port=80,source=demo.nginx.com,zone=lxr.nginx.org discarded=1i,processing=0i,received=1011701i,requests=4523i,responses_1xx=0i,responses_2xx=4332i,responses_3xx=28i,responses_4xx=39i,responses_5xx=123i,responses_total=4522i,sent=72631354i 1570696322000000000
|
||||
nginx_plus_api_http_upstreams,port=80,source=demo.nginx.com,upstream=trac-backend keepalive=0i,zombies=0i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=trac-backend,upstream_address=10.0.0.1:8080 active=0i,backup=false,downtime=0i,fails=0i,header_time=235i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=88581178i,requests=3180i,response_time=235i,responses_1xx=0i,responses_2xx=3168i,responses_3xx=5i,responses_4xx=6i,responses_5xx=0i,responses_total=3179i,sent=1321720i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=1,port=80,source=demo.nginx.com,upstream=trac-backend,upstream_address=10.0.0.1:8081 active=0i,backup=true,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,requests=0i,responses_1xx=0i,responses_2xx=0i,responses_3xx=0i,responses_4xx=0i,responses_5xx=0i,responses_total=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_upstreams,port=80,source=demo.nginx.com,upstream=hg-backend keepalive=0i,zombies=0i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=hg-backend,upstream_address=10.0.0.1:8088 active=0i,backup=false,downtime=0i,fails=0i,header_time=22i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=909402572i,requests=18514i,response_time=88i,responses_1xx=0i,responses_2xx=17799i,responses_3xx=531i,responses_4xx=179i,responses_5xx=0i,responses_total=18509i,sent=10608107i,state="up",unavail=0i,weight=5i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=1,port=80,source=demo.nginx.com,upstream=hg-backend,upstream_address=10.0.0.1:8089 active=0i,backup=true,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,requests=0i,responses_1xx=0i,responses_2xx=0i,responses_3xx=0i,responses_4xx=0i,responses_5xx=0i,responses_total=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_upstreams,port=80,source=demo.nginx.com,upstream=lxr-backend keepalive=0i,zombies=0i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=lxr-backend,upstream_address=unix:/tmp/cgi.sock active=0i,backup=false,downtime=0i,fails=123i,header_time=91i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=71782888i,requests=4354i,response_time=91i,responses_1xx=0i,responses_2xx=4230i,responses_3xx=0i,responses_4xx=0i,responses_5xx=0i,responses_total=4230i,sent=3088656i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=1,port=80,source=demo.nginx.com,upstream=lxr-backend,upstream_address=unix:/tmp/cgib.sock active=0i,backup=true,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,max_conns=42i,received=0i,requests=0i,responses_1xx=0i,responses_2xx=0i,responses_3xx=0i,responses_4xx=0i,responses_5xx=0i,responses_total=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_upstreams,port=80,source=demo.nginx.com,upstream=demo-backend keepalive=0i,zombies=0i 1570696322000000000
|
||||
nginx_plus_api_http_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=demo-backend,upstream_address=10.0.0.2:15431 active=0i,backup=false,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,requests=0i,responses_1xx=0i,responses_2xx=0i,responses_3xx=0i,responses_4xx=0i,responses_5xx=0i,responses_total=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696322000000000
|
||||
nginx_plus_api_http_caches,cache=http_cache,port=80,source=demo.nginx.com bypass_bytes=0i,bypass_bytes_written=0i,bypass_responses=0i,bypass_responses_written=0i,cold=false,expired_bytes=381518640i,expired_bytes_written=363449785i,expired_responses=42114i,expired_responses_written=39954i,hit_bytes=6321885979i,hit_responses=596730i,max_size=536870912i,miss_bytes=48512185i,miss_bytes_written=155600i,miss_responses=6052i,miss_responses_written=136i,revalidated_bytes=0i,revalidated_responses=0i,size=765952i,stale_bytes=0i,stale_responses=0i,updating_bytes=0i,updating_responses=0i 1570696323000000000
|
||||
nginx_plus_api_stream_server_zones,port=80,source=demo.nginx.com,zone=postgresql_loadbalancer connections=0i,processing=0i,received=0i,sent=0i 1570696323000000000
|
||||
nginx_plus_api_stream_server_zones,port=80,source=demo.nginx.com,zone=dns_loadbalancer connections=0i,processing=0i,received=0i,sent=0i 1570696323000000000
|
||||
nginx_plus_api_stream_upstreams,port=80,source=demo.nginx.com,upstream=postgresql_backends zombies=0i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=postgresql_backends,upstream_address=10.0.0.2:15432 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=1,port=80,source=demo.nginx.com,upstream=postgresql_backends,upstream_address=10.0.0.2:15433 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=2,port=80,source=demo.nginx.com,upstream=postgresql_backends,upstream_address=10.0.0.2:15434 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=3,port=80,source=demo.nginx.com,upstream=postgresql_backends,upstream_address=10.0.0.2:15435 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="down",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstreams,port=80,source=demo.nginx.com,upstream=dns_udp_backends zombies=0i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=0,port=80,source=demo.nginx.com,upstream=dns_udp_backends,upstream_address=10.0.0.5:53 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="up",unavail=0i,weight=2i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=1,port=80,source=demo.nginx.com,upstream=dns_udp_backends,upstream_address=10.0.0.2:53 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="up",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstream_peers,id=2,port=80,source=demo.nginx.com,upstream=dns_udp_backends,upstream_address=10.0.0.7:53 active=0i,backup=false,connections=0i,downtime=0i,fails=0i,healthchecks_checks=0i,healthchecks_fails=0i,healthchecks_unhealthy=0i,received=0i,sent=0i,state="down",unavail=0i,weight=1i 1570696323000000000
|
||||
nginx_plus_api_stream_upstreams,port=80,source=demo.nginx.com,upstream=unused_tcp_backends zombies=0i 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_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/#/)
|
||||
- [nginx_api_module documentation](http://nginx.org/en/docs/http/ngx_http_api_module.html)
|
116
plugins/inputs/nginx_plus_api/nginx_plus_api.go
Normal file
116
plugins/inputs/nginx_plus_api/nginx_plus_api.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package nginx_plus_api
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/plugins/common/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
const (
|
||||
// Default settings
|
||||
defaultAPIVersion = 3
|
||||
|
||||
// Paths
|
||||
processesPath = "processes"
|
||||
connectionsPath = "connections"
|
||||
slabsPath = "slabs"
|
||||
sslPath = "ssl"
|
||||
|
||||
httpRequestsPath = "http/requests"
|
||||
httpServerZonesPath = "http/server_zones"
|
||||
httpLocationZonesPath = "http/location_zones"
|
||||
httpUpstreamsPath = "http/upstreams"
|
||||
httpCachesPath = "http/caches"
|
||||
httpLimitReqsPath = "http/limit_reqs"
|
||||
resolverZonesPath = "resolvers"
|
||||
|
||||
streamServerZonesPath = "stream/server_zones"
|
||||
streamUpstreamsPath = "stream/upstreams"
|
||||
)
|
||||
|
||||
type NginxPlusAPI struct {
|
||||
Urls []string `toml:"urls"`
|
||||
APIVersion int64 `toml:"api_version"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
tls.ClientConfig
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func (*NginxPlusAPI) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) Gather(acc telegraf.Accumulator) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Create an HTTP client that is re-used for each
|
||||
// collection interval
|
||||
|
||||
if n.APIVersion == 0 {
|
||||
n.APIVersion = defaultAPIVersion
|
||||
}
|
||||
|
||||
if n.client == nil {
|
||||
client, err := n.createHTTPClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.client = client
|
||||
}
|
||||
|
||||
for _, u := range n.Urls {
|
||||
addr, err := url.Parse(u)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("unable to parse address %q: %w", u, err))
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(addr *url.URL) {
|
||||
defer wg.Done()
|
||||
n.gatherMetrics(addr, acc)
|
||||
}(addr)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) createHTTPClient() (*http.Client, error) {
|
||||
if n.ResponseTimeout < config.Duration(time.Second) {
|
||||
n.ResponseTimeout = config.Duration(time.Second * 5)
|
||||
}
|
||||
|
||||
tlsConfig, err := n.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
Timeout: time.Duration(n.ResponseTimeout),
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nginx_plus_api", func() telegraf.Input {
|
||||
return &NginxPlusAPI{}
|
||||
})
|
||||
}
|
669
plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go
Normal file
669
plugins/inputs/nginx_plus_api/nginx_plus_api_metrics.go
Normal file
|
@ -0,0 +1,669 @@
|
|||
package nginx_plus_api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
var (
|
||||
// errNotFound signals that the NGINX API routes does not exist.
|
||||
errNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
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))
|
||||
addError(acc, n.gatherHTTPUpstreamsMetrics(addr, acc))
|
||||
addError(acc, n.gatherHTTPCachesMetrics(addr, acc))
|
||||
addError(acc, n.gatherStreamServerZonesMetrics(addr, acc))
|
||||
addError(acc, n.gatherStreamUpstreamsMetrics(addr, acc))
|
||||
|
||||
if n.APIVersion >= 5 {
|
||||
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) {
|
||||
// This plugin has hardcoded API resource paths it checks that may not
|
||||
// be in the nginx.conf. Currently, this is to prevent logging of
|
||||
// paths that are not configured.
|
||||
//
|
||||
// The correct solution is to do a GET to /api to get the available paths
|
||||
// on the server rather than simply ignore.
|
||||
if !errors.Is(err, errNotFound) {
|
||||
acc.AddError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherURL(addr *url.URL, path string) ([]byte, error) {
|
||||
address := fmt.Sprintf("%s/%d/%s", addr.String(), n.APIVersion, path)
|
||||
resp, err := n.client.Get(address)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making HTTP request to %q: %w", address, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK:
|
||||
case http.StatusNotFound:
|
||||
// format as special error to catch and ignore as some nginx API
|
||||
// features are either optional, or only available in some versions
|
||||
return nil, errNotFound
|
||||
default:
|
||||
return nil, fmt.Errorf("%s returned HTTP status %s", address, resp.Status)
|
||||
}
|
||||
|
||||
contentType := strings.Split(resp.Header.Get("Content-Type"), ";")[0]
|
||||
switch contentType {
|
||||
case "application/json":
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%s returned unexpected content type %s", address, contentType)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherProcessesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, processesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var processes = &processes{}
|
||||
|
||||
if err := json.Unmarshal(body, processes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_processes",
|
||||
map[string]interface{}{
|
||||
"respawned": processes.Respawned,
|
||||
},
|
||||
getTags(addr),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherConnectionsMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, connectionsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var connections = &connections{}
|
||||
|
||||
if err := json.Unmarshal(body, connections); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_connections",
|
||||
map[string]interface{}{
|
||||
"accepted": connections.Accepted,
|
||||
"dropped": connections.Dropped,
|
||||
"active": connections.Active,
|
||||
"idle": connections.Idle,
|
||||
},
|
||||
getTags(addr),
|
||||
)
|
||||
|
||||
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 := make(map[string]string, len(tags)+1)
|
||||
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 := make(map[string]string, len(slabTags)+1)
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
var ssl = &ssl{}
|
||||
|
||||
if err := json.Unmarshal(body, ssl); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_ssl",
|
||||
map[string]interface{}{
|
||||
"handshakes": ssl.Handshakes,
|
||||
"handshakes_failed": ssl.HandshakesFailed,
|
||||
"session_reuses": ssl.SessionReuses,
|
||||
},
|
||||
getTags(addr),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherHTTPRequestsMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, httpRequestsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var httpRequests = &httpRequests{}
|
||||
|
||||
if err := json.Unmarshal(body, httpRequests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_http_requests",
|
||||
map[string]interface{}{
|
||||
"total": httpRequests.Total,
|
||||
"current": httpRequests.Current,
|
||||
},
|
||||
getTags(addr),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherHTTPServerZonesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, httpServerZonesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var httpServerZones httpServerZones
|
||||
|
||||
if err := json.Unmarshal(body, &httpServerZones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
for zoneName, zone := range httpServerZones {
|
||||
zoneTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
zoneTags[k] = v
|
||||
}
|
||||
zoneTags["zone"] = zoneName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_http_server_zones",
|
||||
func() map[string]interface{} {
|
||||
result := map[string]interface{}{
|
||||
"processing": zone.Processing,
|
||||
"requests": zone.Requests,
|
||||
"responses_1xx": zone.Responses.Responses1xx,
|
||||
"responses_2xx": zone.Responses.Responses2xx,
|
||||
"responses_3xx": zone.Responses.Responses3xx,
|
||||
"responses_4xx": zone.Responses.Responses4xx,
|
||||
"responses_5xx": zone.Responses.Responses5xx,
|
||||
"responses_total": zone.Responses.Total,
|
||||
"received": zone.Received,
|
||||
"sent": zone.Sent,
|
||||
}
|
||||
if zone.Discarded != nil {
|
||||
result["discarded"] = *zone.Discarded
|
||||
}
|
||||
return result
|
||||
}(),
|
||||
zoneTags,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Added in 5 API version
|
||||
func (n *NginxPlusAPI) gatherHTTPLocationZonesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, httpLocationZonesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var httpLocationZones httpLocationZones
|
||||
|
||||
if err := json.Unmarshal(body, &httpLocationZones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for zoneName, zone := range httpLocationZones {
|
||||
zoneTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
zoneTags[k] = v
|
||||
}
|
||||
zoneTags["zone"] = zoneName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_http_location_zones",
|
||||
func() map[string]interface{} {
|
||||
result := map[string]interface{}{
|
||||
"requests": zone.Requests,
|
||||
"responses_1xx": zone.Responses.Responses1xx,
|
||||
"responses_2xx": zone.Responses.Responses2xx,
|
||||
"responses_3xx": zone.Responses.Responses3xx,
|
||||
"responses_4xx": zone.Responses.Responses4xx,
|
||||
"responses_5xx": zone.Responses.Responses5xx,
|
||||
"responses_total": zone.Responses.Total,
|
||||
"received": zone.Received,
|
||||
"sent": zone.Sent,
|
||||
}
|
||||
if zone.Discarded != nil {
|
||||
result["discarded"] = *zone.Discarded
|
||||
}
|
||||
return result
|
||||
}(),
|
||||
zoneTags,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherHTTPUpstreamsMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, httpUpstreamsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var httpUpstreams httpUpstreams
|
||||
|
||||
if err := json.Unmarshal(body, &httpUpstreams); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for upstreamName, upstream := range httpUpstreams {
|
||||
upstreamTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
upstreamTags[k] = v
|
||||
}
|
||||
upstreamTags["upstream"] = upstreamName
|
||||
upstreamFields := map[string]interface{}{
|
||||
"keepalive": upstream.Keepalive,
|
||||
"zombies": upstream.Zombies,
|
||||
}
|
||||
if upstream.Queue != nil {
|
||||
upstreamFields["queue_size"] = upstream.Queue.Size
|
||||
upstreamFields["queue_max_size"] = upstream.Queue.MaxSize
|
||||
upstreamFields["queue_overflows"] = upstream.Queue.Overflows
|
||||
}
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_http_upstreams",
|
||||
upstreamFields,
|
||||
upstreamTags,
|
||||
)
|
||||
for _, peer := range upstream.Peers {
|
||||
peerFields := map[string]interface{}{
|
||||
"backup": peer.Backup,
|
||||
"weight": peer.Weight,
|
||||
"state": peer.State,
|
||||
"active": peer.Active,
|
||||
"requests": peer.Requests,
|
||||
"responses_1xx": peer.Responses.Responses1xx,
|
||||
"responses_2xx": peer.Responses.Responses2xx,
|
||||
"responses_3xx": peer.Responses.Responses3xx,
|
||||
"responses_4xx": peer.Responses.Responses4xx,
|
||||
"responses_5xx": peer.Responses.Responses5xx,
|
||||
"responses_total": peer.Responses.Total,
|
||||
"sent": peer.Sent,
|
||||
"received": peer.Received,
|
||||
"fails": peer.Fails,
|
||||
"unavail": peer.Unavail,
|
||||
"healthchecks_checks": peer.HealthChecks.Checks,
|
||||
"healthchecks_fails": peer.HealthChecks.Fails,
|
||||
"healthchecks_unhealthy": peer.HealthChecks.Unhealthy,
|
||||
"downtime": peer.Downtime,
|
||||
// "selected": peer.Selected.toInt64,
|
||||
// "downstart": peer.Downstart.toInt64,
|
||||
}
|
||||
if peer.HealthChecks.LastPassed != nil {
|
||||
peerFields["healthchecks_last_passed"] = *peer.HealthChecks.LastPassed
|
||||
}
|
||||
if peer.HeaderTime != nil {
|
||||
peerFields["header_time"] = *peer.HeaderTime
|
||||
}
|
||||
if peer.ResponseTime != nil {
|
||||
peerFields["response_time"] = *peer.ResponseTime
|
||||
}
|
||||
if peer.MaxConns != nil {
|
||||
peerFields["max_conns"] = *peer.MaxConns
|
||||
}
|
||||
peerTags := make(map[string]string, len(upstreamTags)+2)
|
||||
for k, v := range upstreamTags {
|
||||
peerTags[k] = v
|
||||
}
|
||||
peerTags["upstream_address"] = peer.Server
|
||||
if peer.ID != nil {
|
||||
peerTags["id"] = strconv.Itoa(*peer.ID)
|
||||
}
|
||||
acc.AddFields("nginx_plus_api_http_upstream_peers", peerFields, peerTags)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherHTTPCachesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, httpCachesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var httpCaches httpCaches
|
||||
|
||||
if err := json.Unmarshal(body, &httpCaches); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for cacheName, cache := range httpCaches {
|
||||
cacheTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
cacheTags[k] = v
|
||||
}
|
||||
cacheTags["cache"] = cacheName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_http_caches",
|
||||
map[string]interface{}{
|
||||
"size": cache.Size,
|
||||
"max_size": cache.MaxSize,
|
||||
"cold": cache.Cold,
|
||||
"hit_responses": cache.Hit.Responses,
|
||||
"hit_bytes": cache.Hit.Bytes,
|
||||
"stale_responses": cache.Stale.Responses,
|
||||
"stale_bytes": cache.Stale.Bytes,
|
||||
"updating_responses": cache.Updating.Responses,
|
||||
"updating_bytes": cache.Updating.Bytes,
|
||||
"revalidated_responses": cache.Revalidated.Responses,
|
||||
"revalidated_bytes": cache.Revalidated.Bytes,
|
||||
"miss_responses": cache.Miss.Responses,
|
||||
"miss_bytes": cache.Miss.Bytes,
|
||||
"miss_responses_written": cache.Miss.ResponsesWritten,
|
||||
"miss_bytes_written": cache.Miss.BytesWritten,
|
||||
"expired_responses": cache.Expired.Responses,
|
||||
"expired_bytes": cache.Expired.Bytes,
|
||||
"expired_responses_written": cache.Expired.ResponsesWritten,
|
||||
"expired_bytes_written": cache.Expired.BytesWritten,
|
||||
"bypass_responses": cache.Bypass.Responses,
|
||||
"bypass_bytes": cache.Bypass.Bytes,
|
||||
"bypass_responses_written": cache.Bypass.ResponsesWritten,
|
||||
"bypass_bytes_written": cache.Bypass.BytesWritten,
|
||||
},
|
||||
cacheTags,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherStreamServerZonesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, streamServerZonesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var streamServerZones streamServerZones
|
||||
|
||||
if err := json.Unmarshal(body, &streamServerZones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for zoneName, zone := range streamServerZones {
|
||||
zoneTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
zoneTags[k] = v
|
||||
}
|
||||
zoneTags["zone"] = zoneName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_stream_server_zones",
|
||||
map[string]interface{}{
|
||||
"processing": zone.Processing,
|
||||
"connections": zone.Connections,
|
||||
"received": zone.Received,
|
||||
"sent": zone.Sent,
|
||||
},
|
||||
zoneTags,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Added in 5 API version
|
||||
func (n *NginxPlusAPI) gatherResolverZonesMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, resolverZonesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var resolverZones resolverZones
|
||||
|
||||
if err := json.Unmarshal(body, &resolverZones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for zoneName, resolver := range resolverZones {
|
||||
zoneTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
zoneTags[k] = v
|
||||
}
|
||||
zoneTags["zone"] = zoneName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_resolver_zones",
|
||||
map[string]interface{}{
|
||||
"name": resolver.Requests.Name,
|
||||
"srv": resolver.Requests.Srv,
|
||||
"addr": resolver.Requests.Addr,
|
||||
|
||||
"noerror": resolver.Responses.Noerror,
|
||||
"formerr": resolver.Responses.Formerr,
|
||||
"servfail": resolver.Responses.Servfail,
|
||||
"nxdomain": resolver.Responses.Nxdomain,
|
||||
"notimp": resolver.Responses.Notimp,
|
||||
"refused": resolver.Responses.Refused,
|
||||
"timedout": resolver.Responses.Timedout,
|
||||
"unknown": resolver.Responses.Unknown,
|
||||
},
|
||||
zoneTags,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NginxPlusAPI) gatherStreamUpstreamsMetrics(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
body, err := n.gatherURL(addr, streamUpstreamsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var streamUpstreams streamUpstreams
|
||||
|
||||
if err := json.Unmarshal(body, &streamUpstreams); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := getTags(addr)
|
||||
|
||||
for upstreamName, upstream := range streamUpstreams {
|
||||
upstreamTags := make(map[string]string, len(tags)+1)
|
||||
for k, v := range tags {
|
||||
upstreamTags[k] = v
|
||||
}
|
||||
upstreamTags["upstream"] = upstreamName
|
||||
acc.AddFields(
|
||||
"nginx_plus_api_stream_upstreams",
|
||||
map[string]interface{}{
|
||||
"zombies": upstream.Zombies,
|
||||
},
|
||||
upstreamTags,
|
||||
)
|
||||
for _, peer := range upstream.Peers {
|
||||
peerFields := map[string]interface{}{
|
||||
"backup": peer.Backup,
|
||||
"weight": peer.Weight,
|
||||
"state": peer.State,
|
||||
"active": peer.Active,
|
||||
"connections": peer.Connections,
|
||||
"sent": peer.Sent,
|
||||
"received": peer.Received,
|
||||
"fails": peer.Fails,
|
||||
"unavail": peer.Unavail,
|
||||
"healthchecks_checks": peer.HealthChecks.Checks,
|
||||
"healthchecks_fails": peer.HealthChecks.Fails,
|
||||
"healthchecks_unhealthy": peer.HealthChecks.Unhealthy,
|
||||
"downtime": peer.Downtime,
|
||||
}
|
||||
if peer.HealthChecks.LastPassed != nil {
|
||||
peerFields["healthchecks_last_passed"] = *peer.HealthChecks.LastPassed
|
||||
}
|
||||
if peer.ConnectTime != nil {
|
||||
peerFields["connect_time"] = *peer.ConnectTime
|
||||
}
|
||||
if peer.FirstByteTime != nil {
|
||||
peerFields["first_byte_time"] = *peer.FirstByteTime
|
||||
}
|
||||
if peer.ResponseTime != nil {
|
||||
peerFields["response_time"] = *peer.ResponseTime
|
||||
}
|
||||
peerTags := make(map[string]string, len(upstreamTags)+2)
|
||||
for k, v := range upstreamTags {
|
||||
peerTags[k] = v
|
||||
}
|
||||
peerTags["upstream_address"] = peer.Server
|
||||
peerTags["id"] = strconv.Itoa(peer.ID)
|
||||
|
||||
acc.AddFields("nginx_plus_api_stream_upstream_peers", peerFields, peerTags)
|
||||
}
|
||||
}
|
||||
|
||||
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 := make(map[string]string, len(tags)+1)
|
||||
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)
|
||||
if err != nil {
|
||||
host = addr.Host
|
||||
if addr.Scheme == "http" {
|
||||
port = "80"
|
||||
} else if addr.Scheme == "https" {
|
||||
port = "443"
|
||||
} else {
|
||||
port = ""
|
||||
}
|
||||
}
|
||||
return map[string]string{"source": host, "port": port}
|
||||
}
|
1585
plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go
Normal file
1585
plugins/inputs/nginx_plus_api/nginx_plus_api_metrics_test.go
Normal file
File diff suppressed because it is too large
Load diff
180
plugins/inputs/nginx_plus_api/nginx_plus_api_types.go
Normal file
180
plugins/inputs/nginx_plus_api/nginx_plus_api_types.go
Normal file
|
@ -0,0 +1,180 @@
|
|||
package nginx_plus_api
|
||||
|
||||
type processes struct {
|
||||
Respawned int `json:"respawned"`
|
||||
}
|
||||
|
||||
type connections struct {
|
||||
Accepted int64 `json:"accepted"`
|
||||
Dropped int64 `json:"dropped"`
|
||||
Active int64 `json:"active"`
|
||||
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"`
|
||||
SessionReuses int64 `json:"session_reuses"`
|
||||
}
|
||||
|
||||
type resolverZones map[string]struct {
|
||||
Requests struct {
|
||||
Name int64 `json:"name"`
|
||||
Srv int64 `json:"srv"`
|
||||
Addr int64 `json:"addr"`
|
||||
} `json:"requests"`
|
||||
Responses struct {
|
||||
Noerror int64 `json:"noerror"`
|
||||
Formerr int64 `json:"formerr"`
|
||||
Servfail int64 `json:"servfail"`
|
||||
Nxdomain int64 `json:"nxdomain"`
|
||||
Notimp int64 `json:"notimp"`
|
||||
Refused int64 `json:"refused"`
|
||||
Timedout int64 `json:"timedout"`
|
||||
Unknown int64 `json:"unknown"`
|
||||
} `json:"responses"`
|
||||
}
|
||||
|
||||
type httpRequests struct {
|
||||
Total int64 `json:"total"`
|
||||
Current int64 `json:"current"`
|
||||
}
|
||||
|
||||
type responseStats struct {
|
||||
Responses1xx int64 `json:"1xx"`
|
||||
Responses2xx int64 `json:"2xx"`
|
||||
Responses3xx int64 `json:"3xx"`
|
||||
Responses4xx int64 `json:"4xx"`
|
||||
Responses5xx int64 `json:"5xx"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type httpServerZones map[string]struct {
|
||||
Processing int `json:"processing"`
|
||||
Requests int64 `json:"requests"`
|
||||
Responses responseStats `json:"responses"`
|
||||
Discarded *int64 `json:"discarded"` // added in version 6
|
||||
Received int64 `json:"received"`
|
||||
Sent int64 `json:"sent"`
|
||||
}
|
||||
|
||||
type httpLocationZones map[string]struct {
|
||||
Requests int64 `json:"requests"`
|
||||
Responses responseStats `json:"responses"`
|
||||
Discarded *int64 `json:"discarded"` // added in version 6
|
||||
Received int64 `json:"received"`
|
||||
Sent int64 `json:"sent"`
|
||||
}
|
||||
|
||||
type healthCheckStats struct {
|
||||
Checks int64 `json:"checks"`
|
||||
Fails int64 `json:"fails"`
|
||||
Unhealthy int64 `json:"unhealthy"`
|
||||
LastPassed *bool `json:"last_passed"`
|
||||
}
|
||||
|
||||
type httpUpstreams map[string]struct {
|
||||
Peers []struct {
|
||||
ID *int `json:"id"` // added in version 3
|
||||
Server string `json:"server"`
|
||||
Backup bool `json:"backup"`
|
||||
Weight int `json:"weight"`
|
||||
State string `json:"state"`
|
||||
Active int `json:"active"`
|
||||
Keepalive *int `json:"keepalive"` // removed in version 5
|
||||
MaxConns *int `json:"max_conns"` // added in version 3
|
||||
Requests int64 `json:"requests"`
|
||||
Responses responseStats `json:"responses"`
|
||||
Sent int64 `json:"sent"`
|
||||
Received int64 `json:"received"`
|
||||
Fails int64 `json:"fails"`
|
||||
Unavail int64 `json:"unavail"`
|
||||
HealthChecks healthCheckStats `json:"health_checks"`
|
||||
Downtime int64 `json:"downtime"`
|
||||
HeaderTime *int64 `json:"header_time"` // added in version 5
|
||||
ResponseTime *int64 `json:"response_time"` // added in version 5
|
||||
} `json:"peers"`
|
||||
Keepalive int `json:"keepalive"`
|
||||
Zombies int `json:"zombies"` // added in version 6
|
||||
Queue *struct { // added in version 6
|
||||
Size int `json:"size"`
|
||||
MaxSize int `json:"max_size"`
|
||||
Overflows int64 `json:"overflows"`
|
||||
} `json:"queue"`
|
||||
}
|
||||
|
||||
type streamServerZones map[string]struct {
|
||||
Processing int `json:"processing"`
|
||||
Connections int `json:"connections"`
|
||||
Sessions *responseStats `json:"sessions"`
|
||||
Discarded *int64 `json:"discarded"` // added in version 7
|
||||
Received int64 `json:"received"`
|
||||
Sent int64 `json:"sent"`
|
||||
}
|
||||
|
||||
type streamUpstreams map[string]struct {
|
||||
Peers []struct {
|
||||
ID int `json:"id"`
|
||||
Server string `json:"server"`
|
||||
Backup bool `json:"backup"`
|
||||
Weight int `json:"weight"`
|
||||
State string `json:"state"`
|
||||
Active int `json:"active"`
|
||||
Connections int64 `json:"connections"`
|
||||
ConnectTime *int `json:"connect_time"`
|
||||
FirstByteTime *int `json:"first_byte_time"`
|
||||
ResponseTime *int `json:"response_time"`
|
||||
Sent int64 `json:"sent"`
|
||||
Received int64 `json:"received"`
|
||||
Fails int64 `json:"fails"`
|
||||
Unavail int64 `json:"unavail"`
|
||||
HealthChecks healthCheckStats `json:"health_checks"`
|
||||
Downtime int64 `json:"downtime"`
|
||||
} `json:"peers"`
|
||||
Zombies int `json:"zombies"`
|
||||
}
|
||||
|
||||
type basicHitStats struct {
|
||||
Responses int64 `json:"responses"`
|
||||
Bytes int64 `json:"bytes"`
|
||||
}
|
||||
|
||||
type extendedHitStats struct {
|
||||
basicHitStats
|
||||
ResponsesWritten int64 `json:"responses_written"`
|
||||
BytesWritten int64 `json:"bytes_written"`
|
||||
}
|
||||
|
||||
type httpCaches map[string]struct { // added in version 2
|
||||
Size int64 `json:"size"`
|
||||
MaxSize int64 `json:"max_size"`
|
||||
Cold bool `json:"cold"`
|
||||
Hit basicHitStats `json:"hit"`
|
||||
Stale basicHitStats `json:"stale"`
|
||||
Updating basicHitStats `json:"updating"`
|
||||
Revalidated *basicHitStats `json:"revalidated"` // added in version 3
|
||||
Miss extendedHitStats `json:"miss"`
|
||||
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"`
|
||||
}
|
16
plugins/inputs/nginx_plus_api/sample.conf
Normal file
16
plugins/inputs/nginx_plus_api/sample.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Read Nginx Plus API advanced status information
|
||||
[[inputs.nginx_plus_api]]
|
||||
## An array of Nginx API URIs to gather stats.
|
||||
urls = ["http://localhost/api"]
|
||||
# Nginx API version, default: 3
|
||||
# api_version = 3
|
||||
|
||||
# HTTP response timeout (default: 5s)
|
||||
response_timeout = "5s"
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
Loading…
Add table
Add a link
Reference in a new issue