Skip to content

Commit 2402783

Browse files
SticksmanSuperQ
andauthored
Bugfix: Make statsreset nullable (#877)
* Stats_reset as null seems to actually be legitimate for new databases, so don't fail for it --------- Signed-off-by: Felix Yuan <felix.yuan@reddit.com> Co-authored-by: Ben Kochie <superq@gmail.com>
1 parent b74852a commit 2402783

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

collector/pg_stat_database.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,13 @@ func (c *PGStatDatabaseCollector) Update(ctx context.Context, instance *instance
344344
level.Debug(c.log).Log("msg", "Skipping collecting metric because it has no blk_write_time")
345345
continue
346346
}
347+
348+
statsResetMetric := 0.0
347349
if !statsReset.Valid {
348-
level.Debug(c.log).Log("msg", "Skipping collecting metric because it has no stats_reset")
349-
continue
350+
level.Debug(c.log).Log("msg", "No metric for stats_reset, will collect 0 instead")
351+
}
352+
if statsReset.Valid {
353+
statsResetMetric = float64(statsReset.Time.Unix())
350354
}
351355

352356
labels := []string{datid.String, datname.String}
@@ -466,7 +470,7 @@ func (c *PGStatDatabaseCollector) Update(ctx context.Context, instance *instance
466470
ch <- prometheus.MustNewConstMetric(
467471
statDatabaseStatsReset,
468472
prometheus.CounterValue,
469-
float64(statsReset.Time.Unix()),
473+
statsResetMetric,
470474
labels...,
471475
)
472476
}

collector/pg_stat_database_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,101 @@ func TestPGStatDatabaseCollectorRowLeakTest(t *testing.T) {
406406
t.Errorf("there were unfulfilled exceptions: %s", err)
407407
}
408408
}
409+
410+
func TestPGStatDatabaseCollectorTestNilStatReset(t *testing.T) {
411+
db, mock, err := sqlmock.New()
412+
if err != nil {
413+
t.Fatalf("Error opening a stub db connection: %s", err)
414+
}
415+
defer db.Close()
416+
417+
inst := &instance{db: db}
418+
419+
columns := []string{
420+
"datid",
421+
"datname",
422+
"numbackends",
423+
"xact_commit",
424+
"xact_rollback",
425+
"blks_read",
426+
"blks_hit",
427+
"tup_returned",
428+
"tup_fetched",
429+
"tup_inserted",
430+
"tup_updated",
431+
"tup_deleted",
432+
"conflicts",
433+
"temp_files",
434+
"temp_bytes",
435+
"deadlocks",
436+
"blk_read_time",
437+
"blk_write_time",
438+
"stats_reset",
439+
}
440+
441+
rows := sqlmock.NewRows(columns).
442+
AddRow(
443+
"pid",
444+
"postgres",
445+
354,
446+
4945,
447+
289097744,
448+
1242257,
449+
int64(3275602074),
450+
89320867,
451+
450139,
452+
2034563757,
453+
0,
454+
int64(2725688749),
455+
23,
456+
52,
457+
74,
458+
925,
459+
16,
460+
823,
461+
nil)
462+
463+
mock.ExpectQuery(sanitizeQuery(statDatabaseQuery)).WillReturnRows(rows)
464+
465+
ch := make(chan prometheus.Metric)
466+
go func() {
467+
defer close(ch)
468+
c := PGStatDatabaseCollector{
469+
log: log.With(log.NewNopLogger(), "collector", "pg_stat_database"),
470+
}
471+
472+
if err := c.Update(context.Background(), inst, ch); err != nil {
473+
t.Errorf("Error calling PGStatDatabaseCollector.Update: %s", err)
474+
}
475+
}()
476+
477+
expected := []MetricResult{
478+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_GAUGE, value: 354},
479+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 4945},
480+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 289097744},
481+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 1242257},
482+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 3275602074},
483+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 89320867},
484+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 450139},
485+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2034563757},
486+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
487+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 2725688749},
488+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 23},
489+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 52},
490+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 74},
491+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 925},
492+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 16},
493+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 823},
494+
{labels: labelMap{"datid": "pid", "datname": "postgres"}, metricType: dto.MetricType_COUNTER, value: 0},
495+
}
496+
497+
convey.Convey("Metrics comparison", t, func() {
498+
for _, expect := range expected {
499+
m := readMetric(<-ch)
500+
convey.So(expect, convey.ShouldResemble, m)
501+
}
502+
})
503+
if err := mock.ExpectationsWereMet(); err != nil {
504+
t.Errorf("there were unfulfilled exceptions: %s", err)
505+
}
506+
}

0 commit comments

Comments
 (0)