Skip to content

Commit

Permalink
add cache metrics for NGINX plus (#540)
Browse files Browse the repository at this point in the history
Signed-off-by: Mohammad Shehar Yaar Tausif <[email protected]>
  • Loading branch information
sheharyaar authored Nov 13, 2023
1 parent 0edad8e commit d57f771
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 2 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,32 @@ Name | Type | Description | Labels
`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` |

#### [Cache](https://nginx.org/en/docs/http/ngx_http_api_module.html#http_caches_http_cache_zone_name)

Name | Type | Description | Labels
----|----|----|----
`nginxplus_cache_size` | Gauge | Total size of the cache | `cache`
`nginxplus_cache_max_size` | Gauge | Maximum size of the cache | `cache`
`nginxplus_cache_cold` | Gauge | Is the cache considered cold | `cache`
`nginxplus_cache_hit_responses` | Counter | Total number of cache hits | `cache`
`nginxplus_cache_hit_bytes` | Counter | Total number of bytes returned from cache hits | `cache`
`nginxplus_cache_stale_responses` | Counter | Total number of stale cache hits | `cache`
`nginxplus_cache_stale_bytes` | Counter | Total number of bytes returned from stale cache hits | `cache`
`nginxplus_cache_updating_responses` | Counter | Total number of cache hits while cache is updating | `cache`
`nginxplus_cache_updating_bytes` | Counter | Total number of bytes returned from cache while cache is updating | `cache`
`nginxplus_cache_revalidated_responses` | Counter | Total number of cache revalidations | `cache`
`nginxplus_cache_revalidated_bytes` | Counter | Total number of bytes returned from cache revalidations | `cache`
`nginxplus_cache_miss_responses` | Counter | Total number of cache misses | `cache`
`nginxplus_cache_miss_bytes` | Counter | Total number of bytes returned from cache misses | `cache`
`nginxplus_cache_expired_responses` | Counter | Total number of cache hits with expired TTL | `cache`
`nginxplus_cache_expired_bytes` | Counter | Total number of bytes returned from cache hits with expired TTL | `cache`
`nginxplus_cache_expired_responses_written` | Counter | Total number of cache hits with expired TTL written to cache | `cache`
`nginxplus_cache_expired_bytes_written` | Counter | Total number of bytes written to cache from cache hits with expired TTL | `cache`
`nginxplus_cache_bypass_responses` | Counter | Total number of cache bypasses | `cache`
`nginxplus_cache_bypass_bytes` | Counter | Total number of bytes returned from cache bypasses | `cache`
`nginxplus_cache_bypass_responses_written` | Counter | Total number of cache bypasses written to cache | `cache`
`nginxplus_cache_bypass_bytes_written` | Counter | Total number of bytes written to cache from cache bypasses | `cache`

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
Expand Down
88 changes: 87 additions & 1 deletion collector/nginx_plus.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type LabelUpdater interface {
DeleteServerZoneLabels(zoneNames []string)
UpdateStreamServerZoneLabels(streamServerZoneLabelValues map[string][]string)
DeleteStreamServerZoneLabels(zoneNames []string)
UpdateCacheZoneLabels(cacheLabelValues map[string][]string)
DeleteCacheZoneLabels(cacheNames []string)
}

// NginxPlusCollector collects NGINX Plus metrics. It implements prometheus.Collector interface.
Expand All @@ -42,6 +44,7 @@ type NginxPlusCollector struct {
limitRequestMetrics map[string]*prometheus.Desc
limitConnectionMetrics map[string]*prometheus.Desc
streamLimitConnectionMetrics map[string]*prometheus.Desc
cacheZoneMetrics map[string]*prometheus.Desc
upMetric prometheus.Gauge
mutex sync.Mutex
variableLabelNames VariableLabelNames
Expand All @@ -51,6 +54,7 @@ type NginxPlusCollector struct {
streamServerZoneLabels map[string][]string
upstreamServerPeerLabels map[string][]string
streamUpstreamServerPeerLabels map[string][]string
cacheZoneLabels map[string][]string
variableLabelsMutex sync.RWMutex
logger log.Logger
}
Expand Down Expand Up @@ -163,6 +167,24 @@ func (c *NginxPlusCollector) DeleteStreamServerZoneLabels(zoneNames []string) {
c.variableLabelsMutex.Unlock()
}

// UpdateCacheZoneLabels updates the Upstream Cache Zone labels
func (c *NginxPlusCollector) UpdateCacheZoneLabels(cacheZoneLabelValues map[string][]string) {
c.variableLabelsMutex.Lock()
for k, v := range cacheZoneLabelValues {
c.cacheZoneLabels[k] = v
}
c.variableLabelsMutex.Unlock()
}

// DeleteCacheZoneLabels deletes the Cache Zone Labels
func (c *NginxPlusCollector) DeleteCacheZoneLabels(cacheZoneNames []string) {
c.variableLabelsMutex.Lock()
for _, k := range cacheZoneNames {
delete(c.cacheZoneLabels, k)
}
c.variableLabelsMutex.Unlock()
}

func (c *NginxPlusCollector) getUpstreamServerLabelValues(upstreamName string) []string {
c.variableLabelsMutex.RLock()
defer c.variableLabelsMutex.RUnlock()
Expand Down Expand Up @@ -207,11 +229,12 @@ type VariableLabelNames struct {
StreamUpstreamServerPeerVariableLabelNames []string
StreamServerZoneVariableLabelNames []string
StreamUpstreamServerVariableLabelNames []string
CacheZoneLabelNames []string
}

// NewVariableLabels creates a new struct for VariableNames for the collector
func NewVariableLabelNames(upstreamServerVariableLabelNames []string, serverZoneVariableLabelNames []string, upstreamServerPeerVariableLabelNames []string,
streamUpstreamServerVariableLabelNames []string, streamServerZoneLabels []string, streamUpstreamServerPeerVariableLabelNames []string,
streamUpstreamServerVariableLabelNames []string, streamServerZoneLabels []string, streamUpstreamServerPeerVariableLabelNames []string, cacheZoneLabelNames []string,
) VariableLabelNames {
return VariableLabelNames{
UpstreamServerVariableLabelNames: upstreamServerVariableLabelNames,
Expand All @@ -220,6 +243,7 @@ func NewVariableLabelNames(upstreamServerVariableLabelNames []string, serverZone
StreamUpstreamServerVariableLabelNames: streamUpstreamServerVariableLabelNames,
StreamServerZoneVariableLabelNames: streamServerZoneLabels,
StreamUpstreamServerPeerVariableLabelNames: streamUpstreamServerPeerVariableLabelNames,
CacheZoneLabelNames: cacheZoneLabelNames,
}
}

Expand Down Expand Up @@ -496,6 +520,29 @@ func NewNginxPlusCollector(nginxClient *plusclient.NginxClient, namespace string
"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),
cacheZoneMetrics: map[string]*prometheus.Desc{
"size": newCacheZoneMetric(namespace, "size", "Total size of the cache", constLabels),
"max_size": newCacheZoneMetric(namespace, "max_size", "Maximum size of the cache", constLabels),
"cold": newCacheZoneMetric(namespace, "cold", "Is the cache considered cold", constLabels),
"hit_responses": newCacheZoneMetric(namespace, "hit_responses", "Total number of cache hits", constLabels),
"hit_bytes": newCacheZoneMetric(namespace, "hit_bytes", "Total number of bytes returned from cache", constLabels),
"stale_responses": newCacheZoneMetric(namespace, "stale_responses", "Total number of stale cache hits", constLabels),
"stale_bytes": newCacheZoneMetric(namespace, "stale_bytes", "Total number of bytes returned from stale cache", constLabels),
"updating_responses": newCacheZoneMetric(namespace, "updating_responses", "Total number of cache hits while cache is updating", constLabels),
"updating_bytes": newCacheZoneMetric(namespace, "updating_bytes", "Total number of bytes returned from cache while cache is updating", constLabels),
"revalidated_responses": newCacheZoneMetric(namespace, "revalidated_responses", "Total number of cache revalidations", constLabels),
"revalidated_bytes": newCacheZoneMetric(namespace, "revalidated_bytes", "Total number of bytes returned from cache revalidations", constLabels),
"miss_responses": newCacheZoneMetric(namespace, "miss_responses", "Total number of cache misses", constLabels),
"miss_bytes": newCacheZoneMetric(namespace, "miss_bytes", "Total number of bytes returned from cache misses", constLabels),
"expired_responses": newCacheZoneMetric(namespace, "expired_responses", "Total number of cache hits with expired TTL", constLabels),
"expired_bytes": newCacheZoneMetric(namespace, "expired_bytes", "Total number of bytes returned from cache hits with expired TTL", constLabels),
"expired_responses_written": newCacheZoneMetric(namespace, "expired_responses_written", "Total number of cache hits with expired TTL written to cache", constLabels),
"expired_bytes_written": newCacheZoneMetric(namespace, "expired_bytes_written", "Total number of bytes written to cache from cache hits with expired TTL", constLabels),
"bypass_responses": newCacheZoneMetric(namespace, "bypass_responses", "Total number of cache bypasses", constLabels),
"bypass_bytes": newCacheZoneMetric(namespace, "bypass_bytes", "Total number of bytes returned from cache bypasses", constLabels),
"bypass_responses_written": newCacheZoneMetric(namespace, "bypass_responses_written", "Total number of cache bypasses written to cache", constLabels),
"bypass_bytes_written": newCacheZoneMetric(namespace, "bypass_bytes_written", "Total number of bytes written to cache from cache bypasses", constLabels),
},
}
}

Expand Down Expand Up @@ -543,6 +590,9 @@ func (c *NginxPlusCollector) Describe(ch chan<- *prometheus.Desc) {
for _, m := range c.streamLimitConnectionMetrics {
ch <- m
}
for _, m := range c.cacheZoneMetrics {
ch <- m
}
}

// Collect fetches metrics from NGINX Plus and sends them to the provided channel.
Expand Down Expand Up @@ -1125,6 +1175,38 @@ func (c *NginxPlusCollector) Collect(ch chan<- prometheus.Metric) {
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)
}

for name, zone := range stats.Caches {

var cold float64
if zone.Cold {
cold = 1.0
} else {
cold = 0.0
}

ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["size"], prometheus.GaugeValue, float64(zone.Size), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["max_size"], prometheus.GaugeValue, float64(zone.MaxSize), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["cold"], prometheus.GaugeValue, cold, name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["hit_responses"], prometheus.CounterValue, float64(zone.Hit.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["hit_bytes"], prometheus.CounterValue, float64(zone.Hit.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["stale_responses"], prometheus.CounterValue, float64(zone.Stale.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["stale_bytes"], prometheus.CounterValue, float64(zone.Stale.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["updating_responses"], prometheus.CounterValue, float64(zone.Updating.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["updating_bytes"], prometheus.CounterValue, float64(zone.Updating.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["revalidated_responses"], prometheus.CounterValue, float64(zone.Revalidated.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["revalidated_bytes"], prometheus.CounterValue, float64(zone.Revalidated.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["miss_responses"], prometheus.CounterValue, float64(zone.Miss.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["miss_bytes"], prometheus.CounterValue, float64(zone.Miss.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["expired_responses"], prometheus.CounterValue, float64(zone.Expired.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["expired_bytes"], prometheus.CounterValue, float64(zone.Expired.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["expired_responses_written"], prometheus.CounterValue, float64(zone.Expired.ResponsesWritten), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["expired_bytes_written"], prometheus.CounterValue, float64(zone.Expired.BytesWritten), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["bypass_responses"], prometheus.CounterValue, float64(zone.Bypass.Responses), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["bypass_bytes"], prometheus.CounterValue, float64(zone.Bypass.Bytes), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["bypass_responses_written"], prometheus.CounterValue, float64(zone.Bypass.ResponsesWritten), name)
ch <- prometheus.MustNewConstMetric(c.cacheZoneMetrics["bypass_bytes_written"], prometheus.CounterValue, float64(zone.Bypass.BytesWritten), name)
}
}

var upstreamServerStates = map[string]float64{
Expand Down Expand Up @@ -1195,3 +1277,7 @@ func newLimitConnectionMetric(namespace string, metricName string, docString str
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)
}

func newCacheZoneMetric(namespace string, metricName string, docString string, constLabels prometheus.Labels) *prometheus.Desc {
return prometheus.NewDesc(prometheus.BuildFQName(namespace, "cache", metricName), docString, []string{"zone"}, constLabels)
}
2 changes: 1 addition & 1 deletion exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func main() {
level.Error(logger).Log("msg", "Could not create Nginx Plus Client", "error", err.Error())
os.Exit(1)
}
variableLabelNames := collector.NewVariableLabelNames(nil, nil, nil, nil, nil, nil)
variableLabelNames := collector.NewVariableLabelNames(nil, nil, nil, nil, nil, nil, nil)
prometheus.MustRegister(collector.NewNginxPlusCollector(plusClient, "nginxplus", variableLabelNames, constLabels, logger))
} else {
ossClient := client.NewNginxClient(httpClient, *scrapeURI)
Expand Down

0 comments on commit d57f771

Please sign in to comment.