Skip to content

Commit

Permalink
Add labels SELECT|INSERT|UPDATE|DELETE|OTHER
Browse files Browse the repository at this point in the history
Signed-off-by: Deryugin, Nikolay <[email protected]>
  • Loading branch information
Deryugin, Nikolay committed Nov 28, 2023
1 parent ba92187 commit 90ba068
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 36 deletions.
47 changes: 32 additions & 15 deletions collector/pg_stat_statements.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,39 +43,46 @@ var (
statStatementsCallsTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, statStatementsSubsystem, "calls_total"),
"Number of times executed",
[]string{"user", "datname", "queryid", "query"},
[]string{"user", "datname", "queryid", "query", "stmt_type"},
prometheus.Labels{},
)
statStatementsSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, statStatementsSubsystem, "seconds_total"),
"Total time spent in the statement, in seconds",
[]string{"user", "datname", "queryid", "query"},
[]string{"user", "datname", "queryid", "query", "stmt_type"},
prometheus.Labels{},
)
statStatementsRowsTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, statStatementsSubsystem, "rows_total"),
"Total number of rows retrieved or affected by the statement",
[]string{"user", "datname", "queryid", "query"},
[]string{"user", "datname", "queryid", "query", "stmt_type"},
prometheus.Labels{},
)
statStatementsBlockReadSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, statStatementsSubsystem, "block_read_seconds_total"),
"Total time the statement spent reading blocks, in seconds",
[]string{"user", "datname", "queryid", "query"},
[]string{"user", "datname", "queryid", "query", "stmt_type"},
prometheus.Labels{},
)
statStatementsBlockWriteSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, statStatementsSubsystem, "block_write_seconds_total"),
"Total time the statement spent writing blocks, in seconds",
[]string{"user", "datname", "queryid", "query"},
[]string{"user", "datname", "queryid", "query", "stmt_type"},
prometheus.Labels{},
)

pgStatStatementsQuery = `SELECT
pg_get_userbyid(userid) as user,
pg_database.datname,
pg_stat_statements.queryid,
LEFT(pg_stat_statements.query, %d) as query,
LEFT(pg_stat_statements.query, 120) as query,
CASE
WHEN pg_stat_statements.query ILIKE 'SELECT%' THEN 'SELECT'
WHEN pg_stat_statements.query ILIKE 'INSERT%' THEN 'INSERT'
WHEN pg_stat_statements.query ILIKE 'UPDATE%' THEN 'UPDATE'
WHEN pg_stat_statements.query ILIKE 'DELETE%' THEN 'DELETE'
ELSE 'OTHER'
END AS stmt_type,
pg_stat_statements.calls as calls_total,
pg_stat_statements.total_time / 1000.0 as seconds_total,
pg_stat_statements.rows as rows_total,
Expand All @@ -97,7 +104,14 @@ var (
pg_get_userbyid(userid) as user,
pg_database.datname,
pg_stat_statements.queryid,
LEFT(pg_stat_statements.query, %d) as query,
LEFT(pg_stat_statements.query, 120) as query,
CASE
WHEN pg_stat_statements.query ILIKE 'SELECT%' THEN 'SELECT'
WHEN pg_stat_statements.query ILIKE 'INSERT%' THEN 'INSERT'
WHEN pg_stat_statements.query ILIKE 'UPDATE%' THEN 'UPDATE'
WHEN pg_stat_statements.query ILIKE 'DELETE%' THEN 'DELETE'
ELSE 'OTHER'
END AS stmt_type,
pg_stat_statements.calls as calls_total,
pg_stat_statements.total_exec_time / 1000.0 as seconds_total,
pg_stat_statements.rows as rows_total,
Expand Down Expand Up @@ -130,11 +144,11 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
}
defer rows.Close()
for rows.Next() {
var user, datname, queryid, query sql.NullString
var user, datname, queryid, query, stmt_type sql.NullString
var callsTotal, rowsTotal sql.NullInt64
var secondsTotal, blockReadSecondsTotal, blockWriteSecondsTotal sql.NullFloat64

if err := rows.Scan(&user, &datname, &queryid, &query, &callsTotal, &secondsTotal, &rowsTotal, &blockReadSecondsTotal, &blockWriteSecondsTotal); err != nil {
if err := rows.Scan(&user, &datname, &queryid, &query, &stmt_type, &callsTotal, &secondsTotal, &rowsTotal, &blockReadSecondsTotal, &blockWriteSecondsTotal); err != nil {
return err
}

Expand All @@ -154,7 +168,10 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
if query.Valid {
queryLabel = query.String
}

stmt_typeLabel := "unknown"
if stmt_type.Valid {
stmt_typeLabel = stmt_type.String
}
callsTotalMetric := 0.0
if callsTotal.Valid {
callsTotalMetric = float64(callsTotal.Int64)
Expand All @@ -163,7 +180,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
statStatementsCallsTotal,
prometheus.CounterValue,
callsTotalMetric,
userLabel, datnameLabel, queryidLabel, queryLabel,
userLabel, datnameLabel, queryidLabel, queryLabel, stmt_typeLabel,
)

secondsTotalMetric := 0.0
Expand All @@ -174,7 +191,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
statStatementsSecondsTotal,
prometheus.CounterValue,
secondsTotalMetric,
userLabel, datnameLabel, queryidLabel, queryLabel,
userLabel, datnameLabel, queryidLabel, queryLabel, stmt_typeLabel,
)

rowsTotalMetric := 0.0
Expand All @@ -185,7 +202,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
statStatementsRowsTotal,
prometheus.CounterValue,
rowsTotalMetric,
userLabel, datnameLabel, queryidLabel, queryLabel,
userLabel, datnameLabel, queryidLabel, queryLabel, stmt_typeLabel,
)

blockReadSecondsTotalMetric := 0.0
Expand All @@ -196,7 +213,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
statStatementsBlockReadSecondsTotal,
prometheus.CounterValue,
blockReadSecondsTotalMetric,
userLabel, datnameLabel, queryidLabel, queryLabel,
userLabel, datnameLabel, queryidLabel, queryLabel, stmt_typeLabel,
)

blockWriteSecondsTotalMetric := 0.0
Expand All @@ -207,7 +224,7 @@ func (PGStatStatementsCollector) Update(ctx context.Context, instance *instance,
statStatementsBlockWriteSecondsTotal,
prometheus.CounterValue,
blockWriteSecondsTotalMetric,
userLabel, datnameLabel, queryidLabel, queryLabel,
userLabel, datnameLabel, queryidLabel, queryLabel, stmt_typeLabel,
)
}
if err := rows.Err(); err != nil {
Expand Down
42 changes: 21 additions & 21 deletions collector/pg_stat_statements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ func TestPGStateStatementsCollector(t *testing.T) {

inst := &instance{db: db, version: semver.MustParse("12.0.0")}

columns := []string{"user", "datname", "queryid", "query", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
columns := []string{"user", "datname", "queryid", "query", "stmt_type", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
rows := sqlmock.NewRows(columns).
AddRow("postgres", "postgres", 1500, "SELECT", 5, 0.4, 100, 0.1, 0.2)
AddRow("postgres", "postgres", 1500, "SELECT", "SELECT", 5, 0.4, 100, 0.1, 0.2)
mock.ExpectQuery(sanitizeQuery(pgStatStatementsQuery)).WillReturnRows(rows)

ch := make(chan prometheus.Metric)
Expand All @@ -48,11 +48,11 @@ func TestPGStateStatementsCollector(t *testing.T) {
}()

expected := []MetricResult{
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 5},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.4},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 100},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.1},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.2},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 5},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.4},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 100},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.1},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.2},
}

convey.Convey("Metrics comparison", t, func() {
Expand All @@ -75,9 +75,9 @@ func TestPGStateStatementsCollectorNull(t *testing.T) {

inst := &instance{db: db, version: semver.MustParse("13.3.7")}

columns := []string{"user", "datname", "queryid", "query", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
columns := []string{"user", "datname", "queryid", "query", "stmt_type", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
rows := sqlmock.NewRows(columns).
AddRow(nil, nil, nil, nil, nil, nil, nil, nil, nil)
AddRow(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
mock.ExpectQuery(sanitizeQuery(pgStatStatementsNewQuery)).WillReturnRows(rows)

ch := make(chan prometheus.Metric)
Expand All @@ -91,11 +91,11 @@ func TestPGStateStatementsCollectorNull(t *testing.T) {
}()

expected := []MetricResult{
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "stmt_type": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "stmt_type": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "stmt_type": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "stmt_type": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"user": "unknown", "datname": "unknown", "query": "unknown", "stmt_type": "unknown", "queryid": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
}

convey.Convey("Metrics comparison", t, func() {
Expand All @@ -118,9 +118,9 @@ func TestPGStateStatementsCollectorNewPG(t *testing.T) {

inst := &instance{db: db, version: semver.MustParse("13.3.7")}

columns := []string{"user", "datname", "queryid", "query", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
columns := []string{"user", "datname", "queryid", "query", "stmt_type", "calls_total", "seconds_total", "rows_total", "block_read_seconds_total", "block_write_seconds_total"}
rows := sqlmock.NewRows(columns).
AddRow("postgres", "postgres", 1500, "SELECT", 5, 0.4, 100, 0.1, 0.2)
AddRow("postgres", "postgres", 1500, "SELECT", "SELECT", 5, 0.4, 100, 0.1, 0.2)
mock.ExpectQuery(sanitizeQuery(pgStatStatementsNewQuery)).WillReturnRows(rows)

ch := make(chan prometheus.Metric)
Expand All @@ -134,11 +134,11 @@ func TestPGStateStatementsCollectorNewPG(t *testing.T) {
}()

expected := []MetricResult{
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 5},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.4},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 100},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.1},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.2},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 5},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.4},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 100},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.1},
{labels: labelMap{"user": "postgres", "datname": "postgres", "query": "SELECT", "stmt_type": "SELECT", "queryid": "1500"}, metricType: dto.MetricType_COUNTER, value: 0.2},
}

convey.Convey("Metrics comparison", t, func() {
Expand Down

0 comments on commit 90ba068

Please sign in to comment.