Skip to content

Commit 040169c

Browse files
authored
Merge pull request #1 from stanhu/sh-better-labels-support
Improve label support
2 parents 66effaf + 4db7f68 commit 040169c

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

Diff for: collector.go

+31-19
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
var (
1818
metricMaps = map[string]map[string]ColumnMapping{
1919
"stats": {
20+
"database": {LABEL, "N/A", 1, "N/A"},
2021
"total_query_count": {COUNTER, "queries_pooled_total", 1, "Total number of SQL queries pooled"},
2122
"total_query_time": {COUNTER, "queries_duration_seconds", 1e-6, "Total number of seconds spent by pgbouncer when actively connected to PostgreSQL, executing queries"},
2223
"total_received": {COUNTER, "received_bytes_total", 1, "Total volume in bytes of network traffic received by pgbouncer, shown as bytes"},
@@ -27,6 +28,8 @@ var (
2728
"total_xact_time": {COUNTER, "server_in_transaction_seconds", 1e-6, "Total number of seconds spent by pgbouncer when connected to PostgreSQL in a transaction, either idle in transaction or executing queries"},
2829
},
2930
"pools": {
31+
"database": {LABEL, "N/A", 1, "N/A"},
32+
"user": {LABEL, "N/A", 1, "N/A"},
3033
"cl_active": {GAUGE, "client_active_connections", 1, "Client connections linked to server connection and able to process queries, shown as connection"},
3134
"cl_waiting": {GAUGE, "client_waiting_connections", 1, "Client connections waiting on a server connection, shown as connection"},
3235
"sv_active": {GAUGE, "server_active_connections", 1, "Server connections linked to a client connection, shown as connection"},
@@ -111,43 +114,43 @@ func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace st
111114
nonfatalErrors := []error{}
112115

113116
for rows.Next() {
114-
var database string
115-
var user string
117+
labelValues := make([]string, len(mapping.labels))
116118
err = rows.Scan(scanArgs...)
117119
if err != nil {
118120
return []error{}, errors.New(fmt.Sprintln("Error retrieving rows:", namespace, err))
119121
}
120122

123+
for i, label := range mapping.labels {
124+
for idx, columnName := range columnNames {
125+
if columnName == label {
126+
labelValues[i] = columnData[idx].(string)
127+
128+
// Prometheus will fail hard if the database and usernames are not UTF-8
129+
if !utf8.ValidString(labelValues[i]) {
130+
nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Column %s in %s has an invalid UTF-8 for a label: %s ", columnName, namespace, columnData[idx])))
131+
continue
132+
}
133+
}
134+
}
135+
}
136+
121137
// Loop over column names, and match to scan data. Unknown columns
122138
// will be filled with an untyped metric number *if* they can be
123139
// converted to float64s. NULLs are allowed and treated as NaN.
124140
for idx, columnName := range columnNames {
125-
if columnName == "database" {
126-
log.Debug("Fetching data for row belonging to database ", columnData[idx])
127-
database = columnData[idx].(string)
128-
} else if columnName == "user" {
129-
log.Debug("Fetching data for row belonging to user ", columnData[idx])
130-
user = columnData[idx].(string)
131-
}
132-
133141
if metricMapping, ok := mapping.columnMappings[columnName]; ok {
134142
// Is this a metricy metric?
135143
if metricMapping.discard {
136144
continue
137145
}
138146

139-
// Prometheus will fail hard if the database and usernames are not UTF-8
140-
if !utf8.ValidString(database) || !utf8.ValidString(user) {
141-
continue
142-
}
143-
144147
value, ok := metricMapping.conversion(columnData[idx])
145148
if !ok {
146149
nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unexpected error parsing column: ", namespace, columnName, columnData[idx])))
147150
continue
148151
}
149152
// Generate the metric
150-
ch <- prometheus.MustNewConstMetric(metricMapping.desc, metricMapping.vtype, value, database, user)
153+
ch <- prometheus.MustNewConstMetric(metricMapping.desc, metricMapping.vtype, value, labelValues...)
151154
}
152155
}
153156
}
@@ -309,30 +312,39 @@ func makeDescMap(metricMaps map[string]map[string]ColumnMapping, namespace strin
309312

310313
for metricNamespace, mappings := range metricMaps {
311314
thisMap := make(map[string]MetricMap)
315+
var labels = make([]string, 0)
316+
317+
// First collect all the labels since the metrics will need them
318+
for columnName, columnMapping := range mappings {
319+
if columnMapping.usage == LABEL {
320+
log.Debugf("Adding label \"%s\" for %s\n", columnName, metricNamespace)
321+
labels = append(labels, columnName)
322+
}
323+
}
312324

313325
for columnName, columnMapping := range mappings {
314326
// Determine how to convert the column based on its usage.
315327
switch columnMapping.usage {
316328
case COUNTER:
317329
thisMap[columnName] = MetricMap{
318330
vtype: prometheus.CounterValue,
319-
desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_%s", namespace, metricNamespace, columnMapping.metric), columnMapping.description, []string{"database", "user"}, nil),
331+
desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_%s", namespace, metricNamespace, columnMapping.metric), columnMapping.description, labels, nil),
320332
conversion: func(in interface{}) (float64, bool) {
321333
return dbToFloat64(in, columnMapping.factor)
322334
},
323335
}
324336
case GAUGE:
325337
thisMap[columnName] = MetricMap{
326338
vtype: prometheus.GaugeValue,
327-
desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_%s", namespace, metricNamespace, columnMapping.metric), columnMapping.description, []string{"database", "user"}, nil),
339+
desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_%s", namespace, metricNamespace, columnMapping.metric), columnMapping.description, labels, nil),
328340
conversion: func(in interface{}) (float64, bool) {
329341
return dbToFloat64(in, columnMapping.factor)
330342
},
331343
}
332344
}
333345
}
334346

335-
metricMap[metricNamespace] = MetricMapNamespace{thisMap}
347+
metricMap[metricNamespace] = MetricMapNamespace{thisMap, labels}
336348
}
337349

338350
return metricMap

Diff for: struct.go

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const (
6767
// Groups metric maps under a shared set of labels
6868
type MetricMapNamespace struct {
6969
columnMappings map[string]MetricMap // Column mappings in this namespace
70+
labels []string
7071
}
7172

7273
// Stores the prometheus metric description which a given column will be mapped

0 commit comments

Comments
 (0)