Files
coder/coderd/database/dbmetrics/dbmetrics_test.go
Spike Curtis 5861e516b9 chore: add standard test logger ignoring db canceled (#15556)
Refactors our use of `slogtest` to instantiate a "standard logger" across most of our tests.  This standard logger incorporates https://github.com/coder/slog/pull/217 to also ignore database query canceled errors by default, which are a source of low-severity flakes.

Any test that has set non-default `slogtest.Options` is left alone. In particular, `coderdtest` defaults to ignoring all errors. We might consider revisiting that decision now that we have better tools to target the really common flaky Error logs on shutdown.
2024-11-18 14:09:22 +04:00

110 lines
3.2 KiB
Go

package dbmetrics_test
import (
"bytes"
"testing"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/coderd/coderdtest/promhelp"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbmem"
"github.com/coder/coder/v2/coderd/database/dbmetrics"
"github.com/coder/coder/v2/testutil"
)
func TestInTxMetrics(t *testing.T) {
t.Parallel()
successLabels := prometheus.Labels{
"success": "true",
"tx_id": "unlabeled",
}
const inTxHistMetricName = "coderd_db_tx_duration_seconds"
const inTxCountMetricName = "coderd_db_tx_executions_count"
t.Run("QueryMetrics", func(t *testing.T) {
t.Parallel()
db := dbmem.New()
reg := prometheus.NewRegistry()
db = dbmetrics.NewQueryMetrics(db, testutil.Logger(t), reg)
err := db.InTx(func(s database.Store) error {
return nil
}, nil)
require.NoError(t, err)
// Check that the metrics are registered
inTxMetric := promhelp.HistogramValue(t, reg, inTxHistMetricName, successLabels)
require.NotNil(t, inTxMetric)
require.Equal(t, uint64(1), inTxMetric.GetSampleCount())
})
t.Run("DBMetrics", func(t *testing.T) {
t.Parallel()
db := dbmem.New()
reg := prometheus.NewRegistry()
db = dbmetrics.NewDBMetrics(db, testutil.Logger(t), reg)
err := db.InTx(func(s database.Store) error {
return nil
}, nil)
require.NoError(t, err)
// Check that the metrics are registered
inTxMetric := promhelp.HistogramValue(t, reg, inTxHistMetricName, successLabels)
require.NotNil(t, inTxMetric)
require.Equal(t, uint64(1), inTxMetric.GetSampleCount())
})
// Test log output and metrics on failures
// Log example:
// [erro] database transaction hit serialization error and had to retry success=false executions=2 id=foobar_factory
t.Run("SerializationError", func(t *testing.T) {
t.Parallel()
var output bytes.Buffer
logger := slog.Make(sloghuman.Sink(&output))
reg := prometheus.NewRegistry()
db := dbmetrics.NewDBMetrics(dbmem.New(), logger, reg)
const id = "foobar_factory"
txOpts := database.DefaultTXOptions().WithID(id)
database.IncrementExecutionCount(txOpts) // 2 executions
err := db.InTx(func(s database.Store) error {
return xerrors.Errorf("some dumb error")
}, txOpts)
require.Error(t, err)
// Check that the metrics are registered
inTxHistMetric := promhelp.HistogramValue(t, reg, inTxHistMetricName, prometheus.Labels{
"success": "false",
"tx_id": id,
})
require.NotNil(t, inTxHistMetric)
require.Equal(t, uint64(1), inTxHistMetric.GetSampleCount())
inTxCountMetric := promhelp.CounterValue(t, reg, inTxCountMetricName, prometheus.Labels{
"success": "false",
"retries": "1",
"tx_id": id,
})
require.NotNil(t, inTxCountMetric)
require.Equal(t, 1, inTxCountMetric)
// Also check the logs
require.Contains(t, output.String(), "some dumb error")
require.Contains(t, output.String(), "database transaction hit serialization error and had to retry")
require.Contains(t, output.String(), "success=false")
require.Contains(t, output.String(), "executions=2")
require.Contains(t, output.String(), "id="+id)
})
}