@@ -2,12 +2,12 @@ package main
2
2
3
3
import (
4
4
"flag"
5
- "strings"
6
5
"fmt"
7
6
"net/http"
7
+ "os"
8
8
"strconv"
9
+ "strings"
9
10
"sync"
10
- "os"
11
11
12
12
"github.com/Snapbug/gomemcache/memcache"
13
13
"github.com/golang/glog"
@@ -18,6 +18,16 @@ const (
18
18
namespace = "memcache"
19
19
)
20
20
21
+ var (
22
+ cacheOperations = []string {"get" , "delete" , "incr" , "decr" , "cas" , "touch" }
23
+ cacheStatuses = []string {"hits" , "misses" }
24
+ usageTimes = []string {"current" , "total" }
25
+ usageResources = []string {"items" , "connections" }
26
+ bytesDirections = []string {"read" , "written" }
27
+ removalsStatuses = []string {"expired" , "evicted" }
28
+ )
29
+
30
+ // Exporter collects metrics from a set of memcache servers.
21
31
type Exporter struct {
22
32
mutex sync.RWMutex
23
33
mc * memcache.Client
@@ -29,38 +39,39 @@ type Exporter struct {
29
39
removals * prometheus.CounterVec
30
40
}
31
41
42
+ // NewExporter returns an initialized exporter
32
43
func NewExporter (mc * memcache.Client ) * Exporter {
33
44
return & Exporter {
34
45
mc : mc ,
35
46
up : prometheus .NewGaugeVec (
36
47
prometheus.GaugeOpts {
37
48
Name : "up" ,
38
49
Namespace : namespace ,
39
- Help : "If the servers were up." ,
50
+ Help : "Are the servers up." ,
40
51
},
41
52
[]string {"server" },
42
53
),
43
54
uptime : prometheus .NewCounterVec (
44
55
prometheus.CounterOpts {
45
56
Name : "uptime" ,
46
57
Namespace : namespace ,
47
- Help : "The time the server has been up ." ,
58
+ Help : "The uptime of the server." ,
48
59
},
49
60
[]string {"server" },
50
61
),
51
62
cache : prometheus .NewCounterVec (
52
63
prometheus.CounterOpts {
53
64
Name : "cache" ,
54
65
Namespace : namespace ,
55
- Help : "The cache operations broken down by command and result (hit or miss )." ,
66
+ Help : "The cache hits/misses broken down by command (get, set, etc. )." ,
56
67
},
57
68
[]string {"server" , "command" , "status" },
58
69
),
59
70
usage : prometheus .NewGaugeVec (
60
71
prometheus.GaugeOpts {
61
72
Name : "usage" ,
62
73
Namespace : namespace ,
63
- Help : "Details the usage of the server, by time (current/total) and resource (items/connections )." ,
74
+ Help : "Details the resource usage (items/connections) of the server, by time (current/total)." ,
64
75
},
65
76
[]string {"server" , "time" , "resource" },
66
77
),
@@ -76,13 +87,15 @@ func NewExporter(mc *memcache.Client) *Exporter {
76
87
prometheus.CounterOpts {
77
88
Name : "removal" ,
78
89
Namespace : namespace ,
79
- Help : "Removal statuses from the cache either expired/ evicted and if they were touched ." ,
90
+ Help : "Number of items that have been evicted/expired (status), and if the were fetched ever or not ." ,
80
91
},
81
92
[]string {"server" , "status" , "fetched" },
82
93
),
83
94
}
84
95
}
85
96
97
+ // Describe describes all the metrics exported by the memcache exporter. It
98
+ // implements prometheus.Collector.
86
99
func (e * Exporter ) Describe (ch chan <- * prometheus.Desc ) {
87
100
e .up .Describe (ch )
88
101
e .cache .Describe (ch )
@@ -91,7 +104,10 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
91
104
e .removals .Describe (ch )
92
105
}
93
106
107
+ // Collect fetches the statistics from the configured memcache servers, and
108
+ // delivers them as prometheus metrics. It implements prometheus.Collector.
94
109
func (e * Exporter ) Collect (ch chan <- prometheus.Metric ) {
110
+ // prevent concurrent metric collections
95
111
e .mutex .Lock ()
96
112
defer e .mutex .Unlock ()
97
113
@@ -105,7 +121,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
105
121
stats , err := e .mc .Stats ()
106
122
107
123
if err != nil {
108
- glog .Fatalf ("Failed to collect stats from memcache: %s" , err )
124
+ glog .Infof ("Failed to collect stats from memcache: %s" , err )
109
125
return
110
126
}
111
127
@@ -119,43 +135,43 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
119
135
e .removals .WithLabelValues (server .String ()).Set (float64 (m ))
120
136
}
121
137
122
- for _ , c := range [] string { "get" , "delete" , "incr" , "decr" , "cas" , "touch" } {
123
- for _ , s := range [] string { "hits" , "misses" } {
124
- m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_%s" , c , s )], 10 , 64 )
138
+ for _ , op := range cacheOperations {
139
+ for _ , st := range cacheStatuses {
140
+ m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_%s" , op , st )], 10 , 64 )
125
141
if err != nil {
126
- e .cache .WithLabelValues (server .String (), c , s ).Set (0 )
142
+ e .cache .WithLabelValues (server .String (), op , st ).Set (0 )
127
143
} else {
128
- e .cache .WithLabelValues (server .String (), c , s ).Set (float64 (m ))
144
+ e .cache .WithLabelValues (server .String (), op , st ).Set (float64 (m ))
129
145
}
130
146
}
131
147
}
132
148
133
- for _ , c := range [] string { "current" , "total" } {
134
- for _ , s := range [] string { "items" , "connections" } {
135
- m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_%s" , c , s )], 10 , 64 )
149
+ for _ , t := range usageTimes {
150
+ for _ , r := range usageResources {
151
+ m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_%s" , t , r )], 10 , 64 )
136
152
if err != nil {
137
- e .usage .WithLabelValues (server .String (), c , s ).Set (0 )
153
+ e .usage .WithLabelValues (server .String (), t , r ).Set (0 )
138
154
} else {
139
- e .usage .WithLabelValues (server .String (), c , s ).Set (float64 (m ))
155
+ e .usage .WithLabelValues (server .String (), t , r ).Set (float64 (m ))
140
156
}
141
157
}
142
158
}
143
159
144
- for _ , c := range [] string { "read" , "written" } {
145
- m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("bytes_%s" , c )], 10 , 64 )
160
+ for _ , dir := range bytesDirections {
161
+ m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("bytes_%s" , dir )], 10 , 64 )
146
162
if err != nil {
147
- e .bytes .WithLabelValues (server .String (), c ).Set (0 )
163
+ e .bytes .WithLabelValues (server .String (), dir ).Set (0 )
148
164
} else {
149
- e .bytes .WithLabelValues (server .String (), c ).Set (float64 (m ))
165
+ e .bytes .WithLabelValues (server .String (), dir ).Set (float64 (m ))
150
166
}
151
167
}
152
168
153
- for _ , c := range [] string { "expired" , "evicted" } {
154
- m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_unfetched" , c )], 10 , 64 )
169
+ for _ , st := range removalsStatuses {
170
+ m , err := strconv .ParseUint (stats [server ][fmt .Sprintf ("%s_unfetched" , st )], 10 , 64 )
155
171
if err != nil {
156
- e .removals .WithLabelValues (server .String (), c , "unfetched" ).Set (0 )
172
+ e .removals .WithLabelValues (server .String (), st , "unfetched" ).Set (0 )
157
173
} else {
158
- e .removals .WithLabelValues (server .String (), c , "unfetched" ).Set (float64 (m ))
174
+ e .removals .WithLabelValues (server .String (), st , "unfetched" ).Set (float64 (m ))
159
175
}
160
176
}
161
177
m , err = strconv .ParseUint (stats [server ]["evictions" ], 10 , 64 )
0 commit comments