pangolin_exporter
523 строки · 17.7 Кб
1// Copyright 2023 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13package collector
14
15import (
16"context"
17"testing"
18"time"
19
20"github.com/DATA-DOG/go-sqlmock"
21"github.com/go-kit/log"
22"github.com/prometheus/client_golang/prometheus"
23dto "github.com/prometheus/client_model/go"
24"github.com/smartystreets/goconvey/convey"
25)
26
27func TestPGStatDatabaseCollector(t *testing.T) {
28db, mock, err := sqlmock.New()
29if err != nil {
30t.Fatalf("Error opening a stub db connection: %s", err)
31}
32defer db.Close()
33
34inst := &instance{db: db}
35
36columns := []string{
37"datid",
38"datname",
39"numbackends",
40"xact_commit",
41"xact_rollback",
42"blks_read",
43"blks_hit",
44"tup_returned",
45"tup_fetched",
46"tup_inserted",
47"tup_updated",
48"tup_deleted",
49"conflicts",
50"temp_files",
51"temp_bytes",
52"deadlocks",
53"blk_read_time",
54"blk_write_time",
55"active_time",
56"stats_reset",
57}
58
59srT, err := time.Parse("2006-01-02 15:04:05.00000-07", "2023-05-25 17:10:42.81132-07")
60if err != nil {
61t.Fatalf("Error parsing time: %s", err)
62}
63
64rows := sqlmock.NewRows(columns).
65AddRow(
66"pid",
67"postgres",
68354,
694945,
70289097744,
711242257,
72int64(3275602074),
7389320867,
74450139,
752034563757,
760,
77int64(2725688749),
7823,
7952,
8074,
81925,
8216,
83823,
8433,
85srT)
86
87mock.ExpectQuery(sanitizeQuery(statDatabaseQuery)).WillReturnRows(rows)
88
89ch := make(chan prometheus.Metric)
90go func() {
91defer close(ch)
92c := PGStatDatabaseCollector{
93log: log.With(log.NewNopLogger(), "collector", "pg_stat_database"),
94}
95
96if err := c.Update(context.Background(), inst, ch); err != nil {
97t.Errorf("Error calling PGStatDatabaseCollector.Update: %s", err)
98}
99}()
100
101expected := []MetricResult{
102{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 354},
103{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4945},
104{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097744},
105{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242257},
106{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602074},
107{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320867},
108{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450139},
109{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563757},
110{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
111{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688749},
112{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 23},
113{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 52},
114{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 74},
115{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 925},
116{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 16},
117{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 823},
118{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0.033},
119{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1685059842},
120}
121
122convey.Convey("Metrics comparison", t, func() {
123for _, expect := range expected {
124m := readMetric(<-ch)
125convey.So(expect, convey.ShouldResemble, m)
126}
127})
128if err := mock.ExpectationsWereMet(); err != nil {
129t.Errorf("there were unfulfilled exceptions: %s", err)
130}
131}
132
133func TestPGStatDatabaseCollectorNullValues(t *testing.T) {
134db, mock, err := sqlmock.New()
135if err != nil {
136t.Fatalf("Error opening a stub db connection: %s", err)
137}
138defer db.Close()
139
140srT, err := time.Parse("2006-01-02 15:04:05.00000-07", "2023-05-25 17:10:42.81132-07")
141if err != nil {
142t.Fatalf("Error parsing time: %s", err)
143}
144inst := &instance{db: db}
145
146columns := []string{
147"datid",
148"datname",
149"numbackends",
150"xact_commit",
151"xact_rollback",
152"blks_read",
153"blks_hit",
154"tup_returned",
155"tup_fetched",
156"tup_inserted",
157"tup_updated",
158"tup_deleted",
159"conflicts",
160"temp_files",
161"temp_bytes",
162"deadlocks",
163"blk_read_time",
164"blk_write_time",
165"active_time",
166"stats_reset",
167}
168
169rows := sqlmock.NewRows(columns).
170AddRow(
171nil,
172"postgres",
173354,
1744945,
175289097744,
1761242257,
177int64(3275602074),
17889320867,
179450139,
1802034563757,
1810,
182int64(2725688749),
18323,
18452,
18574,
186925,
18716,
188823,
18932,
190srT).
191AddRow(
192"pid",
193"postgres",
194354,
1954945,
196289097744,
1971242257,
198int64(3275602074),
19989320867,
200450139,
2012034563757,
2020,
203int64(2725688749),
20423,
20552,
20674,
207925,
20816,
209823,
21032,
211srT)
212mock.ExpectQuery(sanitizeQuery(statDatabaseQuery)).WillReturnRows(rows)
213
214ch := make(chan prometheus.Metric)
215go func() {
216defer close(ch)
217c := PGStatDatabaseCollector{
218log: log.With(log.NewNopLogger(), "collector", "pg_stat_database"),
219}
220
221if err := c.Update(context.Background(), inst, ch); err != nil {
222t.Errorf("Error calling PGStatDatabaseCollector.Update: %s", err)
223}
224}()
225
226expected := []MetricResult{
227{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 354},
228{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4945},
229{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097744},
230{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242257},
231{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602074},
232{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320867},
233{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450139},
234{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563757},
235{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
236{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688749},
237{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 23},
238{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 52},
239{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 74},
240{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 925},
241{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 16},
242{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 823},
243{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0.032},
244{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1685059842},
245}
246
247convey.Convey("Metrics comparison", t, func() {
248for _, expect := range expected {
249m := readMetric(<-ch)
250convey.So(expect, convey.ShouldResemble, m)
251}
252})
253if err := mock.ExpectationsWereMet(); err != nil {
254t.Errorf("there were unfulfilled exceptions: %s", err)
255}
256}
257func TestPGStatDatabaseCollectorRowLeakTest(t *testing.T) {
258db, mock, err := sqlmock.New()
259if err != nil {
260t.Fatalf("Error opening a stub db connection: %s", err)
261}
262defer db.Close()
263
264inst := &instance{db: db}
265
266columns := []string{
267"datid",
268"datname",
269"numbackends",
270"xact_commit",
271"xact_rollback",
272"blks_read",
273"blks_hit",
274"tup_returned",
275"tup_fetched",
276"tup_inserted",
277"tup_updated",
278"tup_deleted",
279"conflicts",
280"temp_files",
281"temp_bytes",
282"deadlocks",
283"blk_read_time",
284"blk_write_time",
285"active_time",
286"stats_reset",
287}
288
289srT, err := time.Parse("2006-01-02 15:04:05.00000-07", "2023-05-25 17:10:42.81132-07")
290if err != nil {
291t.Fatalf("Error parsing time: %s", err)
292}
293
294rows := sqlmock.NewRows(columns).
295AddRow(
296"pid",
297"postgres",
298354,
2994945,
300289097744,
3011242257,
302int64(3275602074),
30389320867,
304450139,
3052034563757,
3060,
307int64(2725688749),
30823,
30952,
31074,
311925,
31216,
313823,
31414,
315srT).
316AddRow(
317nil,
318nil,
319nil,
320nil,
321nil,
322nil,
323nil,
324nil,
325nil,
326nil,
327nil,
328nil,
329nil,
330nil,
331nil,
332nil,
333nil,
334nil,
335nil,
336nil,
337).
338AddRow(
339"pid",
340"postgres",
341355,
3424946,
343289097745,
3441242258,
345int64(3275602075),
34689320868,
347450140,
3482034563758,
3491,
350int64(2725688750),
35124,
35253,
35375,
354926,
35517,
356824,
35715,
358srT)
359mock.ExpectQuery(sanitizeQuery(statDatabaseQuery)).WillReturnRows(rows)
360
361ch := make(chan prometheus.Metric)
362go func() {
363defer close(ch)
364c := PGStatDatabaseCollector{
365log: log.With(log.NewNopLogger(), "collector", "pg_stat_database"),
366}
367
368if err := c.Update(context.Background(), inst, ch); err != nil {
369t.Errorf("Error calling PGStatDatabaseCollector.Update: %s", err)
370}
371}()
372
373expected := []MetricResult{
374{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 354},
375{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4945},
376{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097744},
377{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242257},
378{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602074},
379{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320867},
380{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450139},
381{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563757},
382{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
383{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688749},
384{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 23},
385{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 52},
386{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 74},
387{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 925},
388{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 16},
389{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 823},
390{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0.014},
391{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1685059842},
392
393{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 355},
394{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4946},
395{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097745},
396{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242258},
397{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602075},
398{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320868},
399{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450140},
400{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563758},
401{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1},
402{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688750},
403{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 24},
404{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 53},
405{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 75},
406{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 926},
407{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 17},
408{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 824},
409{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0.015},
410{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1685059842},
411}
412
413convey.Convey("Metrics comparison", t, func() {
414for _, expect := range expected {
415m := readMetric(<-ch)
416convey.So(expect, convey.ShouldResemble, m)
417}
418})
419if err := mock.ExpectationsWereMet(); err != nil {
420t.Errorf("there were unfulfilled exceptions: %s", err)
421}
422}
423
424func TestPGStatDatabaseCollectorTestNilStatReset(t *testing.T) {
425db, mock, err := sqlmock.New()
426if err != nil {
427t.Fatalf("Error opening a stub db connection: %s", err)
428}
429defer db.Close()
430
431inst := &instance{db: db}
432
433columns := []string{
434"datid",
435"datname",
436"numbackends",
437"xact_commit",
438"xact_rollback",
439"blks_read",
440"blks_hit",
441"tup_returned",
442"tup_fetched",
443"tup_inserted",
444"tup_updated",
445"tup_deleted",
446"conflicts",
447"temp_files",
448"temp_bytes",
449"deadlocks",
450"blk_read_time",
451"blk_write_time",
452"active_time",
453"stats_reset",
454}
455
456rows := sqlmock.NewRows(columns).
457AddRow(
458"pid",
459"postgres",
460354,
4614945,
462289097744,
4631242257,
464int64(3275602074),
46589320867,
466450139,
4672034563757,
4680,
469int64(2725688749),
47023,
47152,
47274,
473925,
47416,
475823,
4767,
477nil)
478
479mock.ExpectQuery(sanitizeQuery(statDatabaseQuery)).WillReturnRows(rows)
480
481ch := make(chan prometheus.Metric)
482go func() {
483defer close(ch)
484c := PGStatDatabaseCollector{
485log: log.With(log.NewNopLogger(), "collector", "pg_stat_database"),
486}
487
488if err := c.Update(context.Background(), inst, ch); err != nil {
489t.Errorf("Error calling PGStatDatabaseCollector.Update: %s", err)
490}
491}()
492
493expected := []MetricResult{
494{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 354},
495{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4945},
496{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097744},
497{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242257},
498{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602074},
499{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320867},
500{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450139},
501{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563757},
502{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
503{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688749},
504{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 23},
505{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 52},
506{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 74},
507{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 925},
508{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 16},
509{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 823},
510{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0.007},
511{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
512}
513
514convey.Convey("Metrics comparison", t, func() {
515for _, expect := range expected {
516m := readMetric(<-ch)
517convey.So(expect, convey.ShouldResemble, m)
518}
519})
520if err := mock.ExpectationsWereMet(); err != nil {
521t.Errorf("there were unfulfilled exceptions: %s", err)
522}
523}
524