@@ -10,11 +10,11 @@ import (
1010 "net/http"
1111 "os"
1212 "strconv"
13- "sync"
1413 "time"
1514
1615 "github.com/prometheus/client_golang/prometheus"
1716 "github.com/prometheus/client_golang/prometheus/promhttp"
17+ "github.com/prometheus/common/version"
1818)
1919
2020type NginxVts struct {
@@ -142,61 +142,48 @@ func FloatToString(input_num float64) string {
142142}
143143
144144type Exporter struct {
145- URI string
146- mutex sync.RWMutex
145+ URI string
147146
148- serverMetrics , upstreamMetrics , cacheMetrics map [string ]* prometheus.GaugeVec
147+ serverMetrics , upstreamMetrics , cacheMetrics map [string ]* prometheus.Desc
149148}
150149
151- func newServerMetric (metricName string , docString string , labels []string ) * prometheus.GaugeVec {
152- return prometheus .NewGaugeVec (
153- prometheus.GaugeOpts {
154- Namespace : * metricsNamespace ,
155- Name : "server_" + metricName ,
156- Help : docString ,
157- },
158- labels ,
150+ func newServerMetric (metricName string , docString string , labels []string ) * prometheus.Desc {
151+ return prometheus .NewDesc (
152+ prometheus .BuildFQName (* metricsNamespace , "server" , metricName ),
153+ docString , labels , nil ,
159154 )
160155}
161156
162- func newUpstreamMetric (metricName string , docString string , labels []string ) * prometheus.GaugeVec {
163- return prometheus .NewGaugeVec (
164- prometheus.GaugeOpts {
165- Namespace : * metricsNamespace ,
166- Name : "upstream_" + metricName ,
167- Help : docString ,
168- },
169- labels ,
157+ func newUpstreamMetric (metricName string , docString string , labels []string ) * prometheus.Desc {
158+ return prometheus .NewDesc (
159+ prometheus .BuildFQName (* metricsNamespace , "upstream" , metricName ),
160+ docString , labels , nil ,
170161 )
171162}
172163
173- func newCacheMetric (metricName string , docString string , labels []string ) * prometheus.GaugeVec {
174- return prometheus .NewGaugeVec (
175- prometheus.GaugeOpts {
176- Namespace : * metricsNamespace ,
177- Name : "cache_" + metricName ,
178- Help : docString ,
179- },
180- labels ,
164+ func newCacheMetric (metricName string , docString string , labels []string ) * prometheus.Desc {
165+ return prometheus .NewDesc (
166+ prometheus .BuildFQName (* metricsNamespace , "cache" , metricName ),
167+ docString , labels , nil ,
181168 )
182169}
183170
184171func NewExporter (uri string ) * Exporter {
185172
186173 return & Exporter {
187174 URI : uri ,
188- serverMetrics : map [string ]* prometheus.GaugeVec {
175+ serverMetrics : map [string ]* prometheus.Desc {
189176 "connections" : newServerMetric ("connections" , "nginx connections" , []string {"status" }),
190177 "requests" : newServerMetric ("requests" , "requests counter" , []string {"host" , "code" }),
191178 "bytes" : newServerMetric ("bytes" , "request/response bytes" , []string {"host" , "direction" }),
192179 "cache" : newServerMetric ("cache" , "cache counter" , []string {"host" , "status" }),
193180 },
194- upstreamMetrics : map [string ]* prometheus.GaugeVec {
181+ upstreamMetrics : map [string ]* prometheus.Desc {
195182 "requests" : newUpstreamMetric ("requests" , "requests counter" , []string {"upstream" , "code" }),
196183 "bytes" : newUpstreamMetric ("bytes" , "request/response bytes" , []string {"upstream" , "direction" }),
197184 "response" : newUpstreamMetric ("response" , "request response time" , []string {"upstream" , "backend" }),
198185 },
199- cacheMetrics : map [string ]* prometheus.GaugeVec {
186+ cacheMetrics : map [string ]* prometheus.Desc {
200187 "requests" : newCacheMetric ("requests" , "cache requests counter" , []string {"zone" , "status" }),
201188 "bytes" : newCacheMetric ("bytes" , "cache request/response bytes" , []string {"zone" , "direction" }),
202189 },
@@ -205,51 +192,18 @@ func NewExporter(uri string) *Exporter {
205192
206193func (e * Exporter ) Describe (ch chan <- * prometheus.Desc ) {
207194 for _ , m := range e .serverMetrics {
208- m . Describe ( ch )
195+ ch <- m
209196 }
210197 for _ , m := range e .upstreamMetrics {
211- m . Describe ( ch )
198+ ch <- m
212199 }
213200 for _ , m := range e .cacheMetrics {
214- m . Describe ( ch )
201+ ch <- m
215202 }
216203}
217204
218205func (e * Exporter ) Collect (ch chan <- prometheus.Metric ) {
219- e .mutex .Lock ()
220- defer e .mutex .Unlock ()
221-
222- e .resetMetrics ()
223- e .scrape ()
224206
225- e .collectMetrics (ch )
226- }
227-
228- func (e * Exporter ) resetMetrics () {
229- for _ , m := range e .serverMetrics {
230- m .Reset ()
231- }
232- for _ , m := range e .upstreamMetrics {
233- m .Reset ()
234- }
235- for _ , m := range e .cacheMetrics {
236- m .Reset ()
237- }
238- }
239-
240- func (e * Exporter ) collectMetrics (metrics chan <- prometheus.Metric ) {
241- for _ , m := range e .serverMetrics {
242- m .Collect (metrics )
243- }
244- for _ , m := range e .upstreamMetrics {
245- m .Collect (metrics )
246- }
247- for _ , m := range e .cacheMetrics {
248- m .Collect (metrics )
249- }
250- }
251-
252- func (e * Exporter ) scrape () {
253207 body , err := fetchHTTP (e .URI , 2 * time .Second )()
254208 if err != nil {
255209 log .Println ("fetchHTTP failed" , err )
@@ -270,63 +224,78 @@ func (e *Exporter) scrape() {
270224 return
271225 }
272226
273- e .serverMetrics ["connections" ].WithLabelValues ("active" ).Set (float64 (nginxVtx .Connections .Active ))
274- e .serverMetrics ["connections" ].WithLabelValues ("reading" ).Set (float64 (nginxVtx .Connections .Reading ))
275- e .serverMetrics ["connections" ].WithLabelValues ("waiting" ).Set (float64 (nginxVtx .Connections .Waiting ))
276- e .serverMetrics ["connections" ].WithLabelValues ("writing" ).Set (float64 (nginxVtx .Connections .Writing ))
277- e .serverMetrics ["connections" ].WithLabelValues ("accepted" ).Set (float64 (nginxVtx .Connections .Accepted ))
278- e .serverMetrics ["connections" ].WithLabelValues ("handled" ).Set (float64 (nginxVtx .Connections .Handled ))
279- e .serverMetrics ["connections" ].WithLabelValues ("requests" ).Set (float64 (nginxVtx .Connections .Requests ))
227+ // connections
228+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Active ), "active" )
229+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Reading ), "reading" )
230+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Waiting ), "waiting" )
231+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Writing ), "writing" )
232+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Accepted ), "accepted" )
233+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Handled ), "handled" )
234+ ch <- prometheus .MustNewConstMetric (e .serverMetrics ["connections" ], prometheus .GaugeValue , float64 (nginxVtx .Connections .Requests ), "requests" )
280235
236+ // ServerZones
281237 for host , s := range nginxVtx .ServerZones {
282- e .serverMetrics ["requests" ]. WithLabelValues ( host , "total" ). Set ( float64 (s .RequestCounter ))
283- e .serverMetrics ["requests" ]. WithLabelValues ( host , "1xx" ). Set ( float64 (s .Responses .OneXx ))
284- e .serverMetrics ["requests" ]. WithLabelValues ( host , "2xx" ). Set ( float64 (s .Responses .TwoXx ))
285- e .serverMetrics ["requests" ]. WithLabelValues ( host , "3xx" ). Set ( float64 (s .Responses .ThreeXx ))
286- e .serverMetrics ["requests" ]. WithLabelValues ( host , "4xx" ). Set ( float64 (s .Responses .FourXx ))
287- e .serverMetrics ["requests" ]. WithLabelValues ( host , "5xx" ). Set ( float64 (s .Responses .FiveXx ))
288-
289- e .serverMetrics ["cache" ]. WithLabelValues ( host , "bypass" ). Set ( float64 (s .Responses .Bypass ))
290- e .serverMetrics ["cache" ]. WithLabelValues ( host , "expired" ). Set ( float64 (s .Responses .Expired ))
291- e .serverMetrics ["cache" ]. WithLabelValues ( host , "hit" ). Set ( float64 (s .Responses .Hit ))
292- e .serverMetrics ["cache" ]. WithLabelValues ( host , "miss" ). Set ( float64 (s .Responses .Miss ))
293- e .serverMetrics ["cache" ]. WithLabelValues ( host , "revalidated" ). Set ( float64 (s .Responses .Revalidated ))
294- e .serverMetrics ["cache" ]. WithLabelValues ( host , "scarce" ). Set ( float64 (s .Responses .Scarce ))
295- e .serverMetrics ["cache" ]. WithLabelValues ( host , "stale" ). Set ( float64 (s .Responses .Stale ))
296- e .serverMetrics ["cache" ]. WithLabelValues ( host , "updating" ). Set ( float64 (s .Responses .Updating ))
297-
298- e .serverMetrics ["bytes" ]. WithLabelValues ( host , "in" ). Set ( float64 (s .InBytes ))
299- e .serverMetrics ["bytes" ]. WithLabelValues ( host , "out" ). Set ( float64 (s .OutBytes ))
238+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .RequestCounter ), host , "total" )
239+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .OneXx ), host , "1xx" )
240+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .TwoXx ), host , "2xx" )
241+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .ThreeXx ), host , "3xx" )
242+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .FourXx ), host , "4xx" )
243+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .FiveXx ), host , "5xx" )
244+
245+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Bypass ), host , "bypass" )
246+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Expired ), host , "expired" )
247+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Hit ), host , "hit" )
248+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Miss ), host , "miss" )
249+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Revalidated ), host , "revalidated" )
250+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Scarce ), host , "scarce" )
251+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Stale ), host , "stale" )
252+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["cache" ], prometheus . CounterValue , float64 (s .Responses .Updating ), host , "updating" )
253+
254+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["bytes" ], prometheus . CounterValue , float64 (s .InBytes ), host , "in" )
255+ ch <- prometheus . MustNewConstMetric ( e .serverMetrics ["bytes" ], prometheus . CounterValue , float64 (s .OutBytes ), host , "out" )
300256 }
301257
258+ // UpstreamZones
302259 for name , upstreamList := range nginxVtx .UpstreamZones {
260+ var total , one , two , three , four , five , inbytes , outbytes float64
303261 for _ , s := range upstreamList {
304- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , " total" ). Add ( float64 (s .RequestCounter ) )
305- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , "1xx" ). Add ( float64 (s .Responses .OneXx ) )
306- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , "2xx" ). Add ( float64 (s .Responses .TwoXx ) )
307- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , "3xx" ). Add ( float64 (s .Responses .ThreeXx ) )
308- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , "4xx" ). Add ( float64 (s .Responses .FourXx ) )
309- e . upstreamMetrics [ "requests" ]. WithLabelValues ( name , "5xx" ). Add ( float64 (s .Responses .FiveXx ) )
262+ total += float64 (s .RequestCounter )
263+ one += float64 (s .Responses .OneXx )
264+ two += float64 (s .Responses .TwoXx )
265+ three += float64 (s .Responses .ThreeXx )
266+ four += float64 (s .Responses .FourXx )
267+ five += float64 (s .Responses .FiveXx )
310268
311- e . upstreamMetrics [ "bytes" ]. WithLabelValues ( name , "in" ). Add ( float64 (s .InBytes ) )
312- e . upstreamMetrics [ "bytes" ]. WithLabelValues ( name , "out" ). Add ( float64 (s .OutBytes ) )
269+ inbytes += float64 (s .InBytes )
270+ outbytes += float64 (s .OutBytes )
313271
314- e .upstreamMetrics ["response" ]. WithLabelValues ( name , s . Server ). Add ( float64 (s .ResponseMsec ))
272+ ch <- prometheus . MustNewConstMetric ( e .upstreamMetrics ["response" ], prometheus . GaugeValue , float64 (s .ResponseMsec ), name , s . Server )
315273 }
274+
275+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , total , name , "total" )
276+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , one , name , "1xx" )
277+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , two , name , "2xx" )
278+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , three , name , "3xx" )
279+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , four , name , "4xx" )
280+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["requests" ], prometheus .CounterValue , five , name , "5xx" )
281+
282+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["bytes" ], prometheus .CounterValue , inbytes , name , "in" )
283+ ch <- prometheus .MustNewConstMetric (e .upstreamMetrics ["bytes" ], prometheus .CounterValue , outbytes , name , "out" )
316284 }
317285
286+ // CacheZones
318287 for zone , s := range nginxVtx .CacheZones {
319- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "bypass" ). Set ( float64 (s .Responses .Bypass ))
320- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "expired" ). Set ( float64 (s .Responses .Expired ))
321- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "hit" ). Set ( float64 (s .Responses .Hit ))
322- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "miss" ). Set ( float64 (s .Responses .Miss ))
323- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "revalidated" ). Set ( float64 (s .Responses .Revalidated ))
324- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "scarce" ). Set ( float64 (s .Responses .Scarce ))
325- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "stale" ). Set ( float64 (s .Responses .Stale ))
326- e .cacheMetrics ["requests" ]. WithLabelValues ( zone , "updating" ). Set ( float64 (s .Responses .Updating ))
327-
328- e .cacheMetrics ["bytes" ]. WithLabelValues ( zone , "in" ). Set ( float64 (s .InBytes ))
329- e .cacheMetrics ["bytes" ]. WithLabelValues ( zone , "out" ). Set ( float64 (s .OutBytes ))
288+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Bypass ), zone , "bypass" )
289+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Expired ), zone , "expired" )
290+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Hit ), zone , "hit" )
291+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Miss ), zone , "miss" )
292+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Revalidated ), zone , "revalidated" )
293+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Scarce ), zone , "scarce" )
294+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Stale ), zone , "stale" )
295+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["requests" ], prometheus . CounterValue , float64 (s .Responses .Updating ), zone , "updating" )
296+
297+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["bytes" ], prometheus . CounterValue , float64 (s .InBytes ), zone , "in" )
298+ ch <- prometheus . MustNewConstMetric ( e .cacheMetrics ["bytes" ], prometheus . CounterValue , float64 (s .OutBytes ), zone , "out" )
330299 }
331300}
332301
@@ -347,16 +316,29 @@ func fetchHTTP(uri string, timeout time.Duration) func() (io.ReadCloser, error)
347316}
348317
349318var (
319+ showVersion = flag .Bool ("version" , false , "Print version information." )
350320 listenAddress = flag .String ("telemetry.address" , ":9913" , "Address on which to expose metrics." )
351321 metricsEndpoint = flag .String ("telemetry.endpoint" , "/metrics" , "Path under which to expose metrics." )
352322 metricsNamespace = flag .String ("metrics.namespace" , "nginx" , "Prometheus metrics namespace." )
353323 nginxScrapeURI = flag .String ("nginx.scrape_uri" , "http://localhost/status" , "URI to nginx stub status page" )
354324 insecure = flag .Bool ("insecure" , true , "Ignore server certificate if using https" )
355325)
356326
327+ func init () {
328+ prometheus .MustRegister (version .NewCollector ("nginx_vts_exporter" ))
329+ }
330+
357331func main () {
358332 flag .Parse ()
359333
334+ if * showVersion {
335+ fmt .Fprintln (os .Stdout , version .Print ("nginx_vts_exporter" ))
336+ os .Exit (0 )
337+ }
338+
339+ log .Printf ("Starting nginx_vts_exporter %s" , version .Info ())
340+ log .Printf ("Build context %s" , version .BuildContext ())
341+
360342 exporter := NewExporter (* nginxScrapeURI )
361343 prometheus .MustRegister (exporter )
362344 prometheus .Unregister (prometheus .NewProcessCollector (os .Getpid (), "" ))
0 commit comments