@@ -52,16 +52,13 @@ var (
52
52
53
53
// Exporter collects MySQL metrics. It implements prometheus.Collector.
54
54
type Exporter struct {
55
- dsn string
56
- scrapers []Scraper
57
- error prometheus.Gauge
58
- totalScrapes prometheus.Counter
59
- scrapeErrors * prometheus.CounterVec
60
- mysqldUp prometheus.Gauge
55
+ dsn string
56
+ scrapers []Scraper
57
+ metrics Metrics
61
58
}
62
59
63
60
// New returns a new MySQL exporter for the provided DSN.
64
- func New (dsn string , scrapers []Scraper ) * Exporter {
61
+ func New (dsn string , metrics Metrics , scrapers []Scraper ) * Exporter {
65
62
// Setup extra params for the DSN, default to having a lock timeout.
66
63
dsnParams := []string {fmt .Sprintf (timeoutParam , * exporterLockTimeout )}
67
64
@@ -79,79 +76,37 @@ func New(dsn string, scrapers []Scraper) *Exporter {
79
76
return & Exporter {
80
77
dsn : dsn ,
81
78
scrapers : scrapers ,
82
- totalScrapes : prometheus .NewCounter (prometheus.CounterOpts {
83
- Namespace : namespace ,
84
- Subsystem : exporter ,
85
- Name : "scrapes_total" ,
86
- Help : "Total number of times MySQL was scraped for metrics." ,
87
- }),
88
- scrapeErrors : prometheus .NewCounterVec (prometheus.CounterOpts {
89
- Namespace : namespace ,
90
- Subsystem : exporter ,
91
- Name : "scrape_errors_total" ,
92
- Help : "Total number of times an error occurred scraping a MySQL." ,
93
- }, []string {"collector" }),
94
- error : prometheus .NewGauge (prometheus.GaugeOpts {
95
- Namespace : namespace ,
96
- Subsystem : exporter ,
97
- Name : "last_scrape_error" ,
98
- Help : "Whether the last scrape of metrics from MySQL resulted in an error (1 for error, 0 for success)." ,
99
- }),
100
- mysqldUp : prometheus .NewGauge (prometheus.GaugeOpts {
101
- Namespace : namespace ,
102
- Name : "up" ,
103
- Help : "Whether the MySQL server is up." ,
104
- }),
79
+ metrics : metrics ,
105
80
}
106
81
}
107
82
108
83
// Describe implements prometheus.Collector.
109
84
func (e * Exporter ) Describe (ch chan <- * prometheus.Desc ) {
110
- // We cannot know in advance what metrics the exporter will generate
111
- // from MySQL. So we use the poor man's describe method: Run a collect
112
- // and send the descriptors of all the collected metrics. The problem
113
- // here is that we need to connect to the MySQL DB. If it is currently
114
- // unavailable, the descriptors will be incomplete. Since this is a
115
- // stand-alone exporter and not used as a library within other code
116
- // implementing additional metrics, the worst that can happen is that we
117
- // don't detect inconsistent metrics created by this exporter
118
- // itself. Also, a change in the monitored MySQL instance may change the
119
- // exported metrics during the runtime of the exporter.
120
-
121
- metricCh := make (chan prometheus.Metric )
122
- doneCh := make (chan struct {})
123
-
124
- go func () {
125
- for m := range metricCh {
126
- ch <- m .Desc ()
127
- }
128
- close (doneCh )
129
- }()
130
-
131
- e .Collect (metricCh )
132
- close (metricCh )
133
- <- doneCh
85
+ ch <- e .metrics .TotalScrapes .Desc ()
86
+ ch <- e .metrics .Error .Desc ()
87
+ e .metrics .ScrapeErrors .Describe (ch )
88
+ ch <- e .metrics .MySQLUp .Desc ()
134
89
}
135
90
136
91
// Collect implements prometheus.Collector.
137
92
func (e * Exporter ) Collect (ch chan <- prometheus.Metric ) {
138
93
e .scrape (ch )
139
94
140
- ch <- e .totalScrapes
141
- ch <- e .error
142
- e .scrapeErrors .Collect (ch )
143
- ch <- e .mysqldUp
95
+ ch <- e .metrics . TotalScrapes
96
+ ch <- e .metrics . Error
97
+ e .metrics . ScrapeErrors .Collect (ch )
98
+ ch <- e .metrics . MySQLUp
144
99
}
145
100
146
101
func (e * Exporter ) scrape (ch chan <- prometheus.Metric ) {
147
- e .totalScrapes .Inc ()
102
+ e .metrics . TotalScrapes .Inc ()
148
103
var err error
149
104
150
105
scrapeTime := time .Now ()
151
106
db , err := sql .Open ("mysql" , e .dsn )
152
107
if err != nil {
153
108
log .Errorln ("Error opening connection to database:" , err )
154
- e .error .Set (1 )
109
+ e .metrics . Error .Set (1 )
155
110
return
156
111
}
157
112
defer db .Close ()
@@ -165,13 +120,13 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
165
120
isUpRows , err := db .Query (upQuery )
166
121
if err != nil {
167
122
log .Errorln ("Error pinging mysqld:" , err )
168
- e .mysqldUp .Set (0 )
169
- e .error .Set (1 )
123
+ e .metrics . MySQLUp .Set (0 )
124
+ e .metrics . Error .Set (1 )
170
125
return
171
126
}
172
127
isUpRows .Close ()
173
128
174
- e .mysqldUp .Set (1 )
129
+ e .metrics . MySQLUp .Set (1 )
175
130
176
131
ch <- prometheus .MustNewConstMetric (scrapeDurationDesc , prometheus .GaugeValue , time .Since (scrapeTime ).Seconds (), "connection" )
177
132
@@ -185,10 +140,48 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
185
140
scrapeTime := time .Now ()
186
141
if err := scraper .Scrape (db , ch ); err != nil {
187
142
log .Errorln ("Error scraping for " + label + ":" , err )
188
- e .scrapeErrors .WithLabelValues (label ).Inc ()
189
- e .error .Set (1 )
143
+ e .metrics . ScrapeErrors .WithLabelValues (label ).Inc ()
144
+ e .metrics . Error .Set (1 )
190
145
}
191
146
ch <- prometheus .MustNewConstMetric (scrapeDurationDesc , prometheus .GaugeValue , time .Since (scrapeTime ).Seconds (), label )
192
147
}(scraper )
193
148
}
194
149
}
150
+
151
+ // Metrics represents exporter metrics which values can be carried between http requests.
152
+ type Metrics struct {
153
+ TotalScrapes prometheus.Counter
154
+ ScrapeErrors * prometheus.CounterVec
155
+ Error prometheus.Gauge
156
+ MySQLUp prometheus.Gauge
157
+ }
158
+
159
+ // NewMetrics creates new Metrics instance.
160
+ func NewMetrics () Metrics {
161
+ subsystem := exporter
162
+ return Metrics {
163
+ TotalScrapes : prometheus .NewCounter (prometheus.CounterOpts {
164
+ Namespace : namespace ,
165
+ Subsystem : subsystem ,
166
+ Name : "scrapes_total" ,
167
+ Help : "Total number of times MySQL was scraped for metrics." ,
168
+ }),
169
+ ScrapeErrors : prometheus .NewCounterVec (prometheus.CounterOpts {
170
+ Namespace : namespace ,
171
+ Subsystem : subsystem ,
172
+ Name : "scrape_errors_total" ,
173
+ Help : "Total number of times an error occurred scraping a MySQL." ,
174
+ }, []string {"collector" }),
175
+ Error : prometheus .NewGauge (prometheus.GaugeOpts {
176
+ Namespace : namespace ,
177
+ Subsystem : subsystem ,
178
+ Name : "last_scrape_error" ,
179
+ Help : "Whether the last scrape of metrics from MySQL resulted in an error (1 for error, 0 for success)." ,
180
+ }),
181
+ MySQLUp : prometheus .NewGauge (prometheus.GaugeOpts {
182
+ Namespace : namespace ,
183
+ Name : "up" ,
184
+ Help : "Whether the MySQL server is up." ,
185
+ }),
186
+ }
187
+ }
0 commit comments