Skip to content

Add metrics from NGINX Plus API version 6 #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,30 @@ Name | Type | Description | Labels
`nginxplus_resolver_timedout` | Counter | Total number of timed out request | `resolver` |
`nginxplus_resolver_unknown` | Counter | Total requests completed with an unknown error | `resolver`|

#### [HTTP Requests Rate Limiting](https://nginx.org/en/docs/http/ngx_http_api_module.html#def_nginx_http_limit_req_zone)
Name | Type | Description | Labels
----|----|----|----|
`nginxplus_limit_request_passed` | Counter | Total number of requests that were neither limited nor accounted as limited | `zone` |
`nginxplus_limit_request_rejected` | Counter | Total number of requests that were that were rejected | `zone` |
`nginxplus_limit_request_delayed` | Counter | Total number of requests that were delayed | `zone` |
`nginxplus_limit_request_rejected_dry_run` | Counter | Total number of requests accounted as rejected in the dry run mode | `zone` |
`nginxplus_limit_request_delayed_dry_run` | Counter | Total number of requests accounted as delayed in the dry run mode | `zone` |

#### [HTTP Connections Limiting](https://nginx.org/en/docs/http/ngx_http_api_module.html#def_nginx_http_limit_conn_zone)
Name | Type | Description | Labels
----|----|----|----|
`nginxplus_limit_connection_passed` | Counter | Total number of connections that were neither limited nor accounted as limited | `zone` |
`nginxplus_limit_connection_rejected` | Counter | Total number of connections that were rejected | `zone` |
`nginxplus_limit_connection_rejected_dry_run` | Counter | Total number of connections accounted as rejected in the dry run mode | `zone` |


#### [Stream Connections Limiting](https://nginx.org/en/docs/http/ngx_http_api_module.html#def_nginx_stream_limit_conn_zone)
Name | Type | Description | Labels
----|----|----|----|
`nginxplus_stream_limit_connection_passed` | Counter | Total number of connections that were neither limited nor accounted as limited | `zone` |
`nginxplus_stream_limit_connection_rejected` | Counter | Total number of connections that were rejected | `zone` |
`nginxplus_stream_limit_connection_rejected_dry_run` | Counter | Total number of connections accounted as rejected in the dry run mode | `zone` |

Connect to the `/metrics` page of the running exporter to see the complete list of metrics along with their descriptions. Note: to see server zones related metrics you must configure [status zones](https://nginx.org/en/docs/http/ngx_http_status_module.html#status_zone) and to see upstream related metrics you must configure upstreams with a [shared memory zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone).

## Troubleshooting
Expand Down
61 changes: 61 additions & 0 deletions collector/nginx_plus.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type NginxPlusCollector struct {
streamUpstreamServerMetrics map[string]*prometheus.Desc
locationZoneMetrics map[string]*prometheus.Desc
resolverMetrics map[string]*prometheus.Desc
limitRequestMetrics map[string]*prometheus.Desc
limitConnectionMetrics map[string]*prometheus.Desc
streamLimitConnectionMetrics map[string]*prometheus.Desc
upMetric prometheus.Gauge
mutex sync.Mutex
variableLabelNames VariableLabelNames
Expand Down Expand Up @@ -340,6 +343,23 @@ func NewNginxPlusCollector(nginxClient *plusclient.NginxClient, namespace string
"timedout": newResolverMetric(namespace, "timedout", "Total number of timed out requests", constLabels),
"unknown": newResolverMetric(namespace, "unknown", "Total requests completed with an unknown error", constLabels),
},
limitRequestMetrics: map[string]*prometheus.Desc{
"passed": newLimitRequestMetric(namespace, "passed", "Total number of requests that were neither limited nor accounted as limited", constLabels),
"delayed": newLimitRequestMetric(namespace, "delayed", "Total number of requests that were delayed", constLabels),
"rejected": newLimitRequestMetric(namespace, "rejected", "Total number of requests that were that were rejected", constLabels),
"delayed_dry_run": newLimitRequestMetric(namespace, "delayed_dry_run", "Total number of requests accounted as delayed in the dry run mode", constLabels),
"rejected_dry_run": newLimitRequestMetric(namespace, "rejected_dry_run", "Total number of requests accounted as rejected in the dry run mode", constLabels),
},
limitConnectionMetrics: map[string]*prometheus.Desc{
"passed": newLimitConnectionMetric(namespace, "passed", "Total number of connections that were neither limited nor accounted as limited", constLabels),
"rejected": newLimitConnectionMetric(namespace, "rejected", "Total number of connections that were rejected", constLabels),
"rejected_dry_run": newLimitConnectionMetric(namespace, "rejected_dry_run", "Total number of connections accounted as rejected in the dry run mode", constLabels),
},
streamLimitConnectionMetrics: map[string]*prometheus.Desc{
"passed": newStreamLimitConnectionMetric(namespace, "passed", "Total number of connections that were neither limited nor accounted as limited", constLabels),
"rejected": newStreamLimitConnectionMetric(namespace, "rejected", "Total number of connections that were rejected", constLabels),
"rejected_dry_run": newStreamLimitConnectionMetric(namespace, "rejected_dry_run", "Total number of connections accounted as rejected in the dry run mode", constLabels),
},
upMetric: newUpMetric(namespace, constLabels),
}
}
Expand Down Expand Up @@ -379,6 +399,15 @@ func (c *NginxPlusCollector) Describe(ch chan<- *prometheus.Desc) {
for _, m := range c.resolverMetrics {
ch <- m
}
for _, m := range c.limitRequestMetrics {
ch <- m
}
for _, m := range c.limitConnectionMetrics {
ch <- m
}
for _, m := range c.streamLimitConnectionMetrics {
ch <- m
}
}

// Collect fetches metrics from NGINX Plus and sends them to the provided channel.
Expand Down Expand Up @@ -683,6 +712,26 @@ func (c *NginxPlusCollector) Collect(ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(c.resolverMetrics["unknown"],
prometheus.CounterValue, float64(zone.Responses.Unknown), name)
}

for name, zone := range stats.HTTPLimitRequests {
ch <- prometheus.MustNewConstMetric(c.limitRequestMetrics["passed"], prometheus.CounterValue, float64(zone.Passed), name)
ch <- prometheus.MustNewConstMetric(c.limitRequestMetrics["rejected"], prometheus.CounterValue, float64(zone.Rejected), name)
ch <- prometheus.MustNewConstMetric(c.limitRequestMetrics["delayed"], prometheus.CounterValue, float64(zone.Delayed), name)
ch <- prometheus.MustNewConstMetric(c.limitRequestMetrics["rejected_dry_run"], prometheus.CounterValue, float64(zone.RejectedDryRun), name)
ch <- prometheus.MustNewConstMetric(c.limitRequestMetrics["delayed_dry_run"], prometheus.CounterValue, float64(zone.DelayedDryRun), name)
}

for name, zone := range stats.HTTPLimitConnections {
ch <- prometheus.MustNewConstMetric(c.limitConnectionMetrics["passed"], prometheus.CounterValue, float64(zone.Passed), name)
ch <- prometheus.MustNewConstMetric(c.limitConnectionMetrics["rejected"], prometheus.CounterValue, float64(zone.Rejected), name)
ch <- prometheus.MustNewConstMetric(c.limitConnectionMetrics["rejected_dry_run"], prometheus.CounterValue, float64(zone.RejectedDryRun), name)
}

for name, zone := range stats.StreamLimitConnections {
ch <- prometheus.MustNewConstMetric(c.streamLimitConnectionMetrics["passed"], prometheus.CounterValue, float64(zone.Passed), name)
ch <- prometheus.MustNewConstMetric(c.streamLimitConnectionMetrics["rejected"], prometheus.CounterValue, float64(zone.Rejected), name)
ch <- prometheus.MustNewConstMetric(c.streamLimitConnectionMetrics["rejected_dry_run"], prometheus.CounterValue, float64(zone.RejectedDryRun), name)
}
}

var upstreamServerStates = map[string]float64{
Expand Down Expand Up @@ -741,3 +790,15 @@ func newLocationZoneMetric(namespace string, metricName string, docString string
func newResolverMetric(namespace string, metricName string, docString string, constLabels prometheus.Labels) *prometheus.Desc {
return prometheus.NewDesc(prometheus.BuildFQName(namespace, "resolver", metricName), docString, []string{"resolver"}, constLabels)
}

func newLimitRequestMetric(namespace string, metricName string, docString string, constLabels prometheus.Labels) *prometheus.Desc {
return prometheus.NewDesc(prometheus.BuildFQName(namespace, "limit_request", metricName), docString, []string{"zone"}, constLabels)
}

func newLimitConnectionMetric(namespace string, metricName string, docString string, constLabels prometheus.Labels) *prometheus.Desc {
return prometheus.NewDesc(prometheus.BuildFQName(namespace, "limit_connection", metricName), docString, []string{"zone"}, constLabels)
}

func newStreamLimitConnectionMetric(namespace string, metricName string, docString string, constLabels prometheus.Labels) *prometheus.Desc {
return prometheus.NewDesc(prometheus.BuildFQName(namespace, "stream_limit_connection", metricName), docString, []string{"zone"}, constLabels)
}