Skip to content

Commit 7a9d0e6

Browse files
authored
PMM-10512, PMM-10820 Capture usename and application_name for pg_stat_activity, update exporter (percona#77)
1 parent b74ef57 commit 7a9d0e6

File tree

4 files changed

+82
-24
lines changed

4 files changed

+82
-24
lines changed

cmd/postgres_exporter/postgres_exporter.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,12 @@ var builtinMetricMaps = map[string]intermediateMetricMap{
297297
},
298298
"pg_stat_activity": {
299299
map[string]ColumnMapping{
300-
"datname": {LABEL, "Name of this database", nil, nil},
301-
"state": {LABEL, "connection state", nil, semver.MustParseRange(">=9.2.0")},
302-
"count": {GAUGE, "number of connections in this state", nil, nil},
303-
"max_tx_duration": {GAUGE, "max duration in seconds any active transaction has been running", nil, nil},
300+
"datname": {LABEL, "Name of this database", nil, nil},
301+
"state": {LABEL, "connection state", nil, semver.MustParseRange(">=9.2.0")},
302+
"usename": {LABEL, "Name of the user logged into this backend", nil, nil},
303+
"application_name": {LABEL, "Name of the application that is connected to this backend", nil, nil},
304+
"count": {GAUGE, "number of connections in this state", nil, nil},
305+
"max_tx_duration": {GAUGE, "max duration in seconds any active transaction has been running", nil, nil},
304306
},
305307
true,
306308
0,

cmd/postgres_exporter/queries.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ var queryOverrides = map[string][]OverrideQuery{
137137
SELECT
138138
pg_database.datname,
139139
tmp.state,
140+
tmp2.usename,
141+
tmp2.application_name,
140142
COALESCE(count,0) as count,
141143
COALESCE(max_tx_duration,0) as max_tx_duration
142144
FROM
@@ -153,9 +155,11 @@ var queryOverrides = map[string][]OverrideQuery{
153155
SELECT
154156
datname,
155157
state,
158+
usename,
159+
application_name,
156160
count(*) AS count,
157161
MAX(EXTRACT(EPOCH FROM now() - xact_start))::float AS max_tx_duration
158-
FROM pg_stat_activity GROUP BY datname,state) AS tmp2
162+
FROM pg_stat_activity GROUP BY datname,state,usename,application_name) AS tmp2
159163
ON tmp.state = tmp2.state AND pg_database.datname = tmp2.datname
160164
`,
161165
},
@@ -165,9 +169,11 @@ var queryOverrides = map[string][]OverrideQuery{
165169
SELECT
166170
datname,
167171
'unknown' AS state,
172+
usename,
173+
application_name,
168174
COALESCE(count(*),0) AS count,
169175
COALESCE(MAX(EXTRACT(EPOCH FROM now() - xact_start))::float,0) AS max_tx_duration
170-
FROM pg_stat_activity GROUP BY datname
176+
FROM pg_stat_activity GROUP BY datname,usename,application_name
171177
`,
172178
},
173179
},

percona_tests/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ test-performance:
88
extraMetrics = false
99
multipleLabels = false
1010
dumpMetrics = false
11+
endpoint = ''
1112

1213
test-metrics:
1314
go test -v -run '^TestMissingMetrics$$' -args -doRun=true
@@ -22,7 +23,7 @@ test-resolutions:
2223
go test -v -run '^TestResolutions$$' -args -doRun=true
2324

2425
dump-metrics:
25-
go test -v -run '^TestDumpMetrics$$' -args -doRun=true -extraMetrics=$(extraMetrics) -multipleLabels=$(multipleLabels) -dumpMetrics=$(dumpMetrics)
26+
go test -v -run '^TestDumpMetrics$$' -args -doRun=true -extraMetrics=$(extraMetrics) -multipleLabels=$(multipleLabels) -endpoint=$(endpoint) -dumpMetrics=true
2627

2728
test-consistency: test-metrics test-resolutions test-resolutions-duplicates
2829

percona_tests/metrics_test.go

+66-17
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ import (
1414
var dumpMetricsFlag = flag.Bool("dumpMetrics", false, "")
1515
var printExtraMetrics = flag.Bool("extraMetrics", false, "")
1616
var printMultipleLabels = flag.Bool("multipleLabels", false, "")
17+
var endpointFlag = flag.String("endpoint", "", "")
1718

1819
type Metric struct {
19-
name string
20-
labels string
20+
name string
21+
labelsRawStr string
22+
labelsWithValues []string
2123
}
2224

2325
type MetricsCollection struct {
@@ -86,13 +88,25 @@ func TestDumpMetrics(t *testing.T) {
8688
return
8789
}
8890

89-
newMetrics, err := getMetrics(updatedExporterFileName)
91+
var ep string
92+
switch *endpointFlag {
93+
case "hr":
94+
ep = highResolutionEndpoint
95+
case "mr":
96+
ep = medResolutionEndpoint
97+
case "lr":
98+
ep = lowResolutionEndpoint
99+
default:
100+
ep = "metrics"
101+
}
102+
103+
newMetrics, err := getMetricsFrom(updatedExporterFileName, ep)
90104
if err != nil {
91105
t.Error(err)
92106
return
93107
}
94108

95-
oldMetrics, err := getMetrics(oldExporterFileName)
109+
oldMetrics, err := getMetricsFrom(oldExporterFileName, ep)
96110
if err != nil {
97111
t.Error(err)
98112
return
@@ -202,20 +216,50 @@ func testResolution(t *testing.T, resolutionEp, resolutionName string) {
202216

203217
missingCount := 0
204218
missingMetrics := ""
205-
for _, metric := range oldMetricsCollection.MetricNamesWithLabels {
206-
if metric == "" || strings.HasPrefix(metric, "# ") {
219+
missingLabelsCount := 0
220+
missingLabels := ""
221+
for _, oldMetric := range oldMetricsCollection.MetricsData {
222+
if oldMetric.name == "" || strings.HasPrefix(oldMetric.name, "# ") {
207223
continue
208224
}
209225

210-
if !contains(newMetricsCollection.MetricNamesWithLabels, metric) {
226+
metricFound := false
227+
labelsMatch := false
228+
for _, newMetric := range newMetricsCollection.MetricsData {
229+
if newMetric.name != oldMetric.name {
230+
continue
231+
}
232+
233+
metricFound = true
234+
235+
if newMetric.labelsRawStr == oldMetric.labelsRawStr {
236+
labelsMatch = true
237+
break
238+
}
239+
240+
if arrIsSubsetOf(oldMetric.labelsWithValues, newMetric.labelsWithValues) {
241+
labelsMatch = true
242+
break
243+
}
244+
}
245+
246+
if !metricFound {
211247
missingCount++
212-
missingMetrics += fmt.Sprintf("%s\n", metric)
248+
missingMetrics += fmt.Sprintf("%s\n", oldMetric.name)
249+
} else if !labelsMatch {
250+
missingLabelsCount++
251+
missingLabels += fmt.Sprintf("%s\n", oldMetric.name)
213252
}
214253
}
254+
215255
if missingCount > 0 {
216256
t.Errorf("%d metrics are missing in new exporter for %s resolution:\n%s", missingCount, resolutionName, missingMetrics)
217257
}
218258

259+
if missingLabelsCount > 0 {
260+
t.Errorf("%d metrics's labels missing in new exporter for %s resolution:\n%s", missingCount, resolutionName, missingLabels)
261+
}
262+
219263
extraCount := 0
220264
extraMetrics := ""
221265
for _, metric := range newMetricsCollection.MetricNamesWithLabels {
@@ -362,13 +406,13 @@ func parseMetricsCollection(metricRaw string) MetricsCollection {
362406
}
363407
}
364408

365-
func arrIsSubsetOf(a, b []string) bool {
366-
if len(a) == 0 {
367-
return len(b) == 0
409+
func arrIsSubsetOf(smaller, larger []string) bool {
410+
if len(smaller) == 0 {
411+
return len(larger) == 0
368412
}
369413

370-
for _, x := range a {
371-
if !contains(b, x) {
414+
for _, x := range smaller {
415+
if !contains(larger, x) {
372416
return false
373417
}
374418
}
@@ -394,10 +438,10 @@ func groupByMetrics(metrics []Metric) map[string][]string {
394438
metric := metrics[i]
395439
if _, ok := mtr[metric.name]; ok {
396440
labels := mtr[metric.name]
397-
labels = append(labels, metric.labels)
441+
labels = append(labels, metric.labelsRawStr)
398442
mtr[metric.name] = labels
399443
} else {
400-
mtr[metric.name] = []string{metric.labels}
444+
mtr[metric.name] = []string{metric.labelsRawStr}
401445
}
402446
}
403447

@@ -414,16 +458,21 @@ func parseMetrics(metrics []string) []Metric {
414458
}
415459

416460
var mName, mLabels string
461+
var labelsArr []string
417462
if strings.Contains(metricRawStr, "{") {
418463
mName = metricRawStr[:strings.Index(metricRawStr, "{")]
419464
mLabels = metricRawStr[strings.Index(metricRawStr, "{")+1 : len(metricRawStr)-1]
465+
if mLabels != "" {
466+
labelsArr = strings.Split(mLabels, ",")
467+
}
420468
} else {
421469
mName = metricRawStr
422470
}
423471

424472
metric := Metric{
425-
name: mName,
426-
labels: mLabels,
473+
name: mName,
474+
labelsRawStr: mLabels,
475+
labelsWithValues: labelsArr,
427476
}
428477

429478
metricsData = append(metricsData, metric)

0 commit comments

Comments
 (0)