Skip to content

Commit bfe2a76

Browse files
author
Adrien ZAGABE
committed
adding top queries execution collector
1 parent 74800f4 commit bfe2a76

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

collector/pg_top_queries_execution.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package collector
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
7+
"github.com/go-kit/log"
8+
"github.com/prometheus/client_golang/prometheus"
9+
)
10+
11+
const statTopQueriesExecutionTime = "stat_top_queries"
12+
13+
func init() {
14+
registerCollector(statTopQueriesExecutionTime, true, NewPGStatTopQueriesExecutionTime)
15+
}
16+
17+
type PGStatTopQueriesExecutionTime struct {
18+
log log.Logger
19+
}
20+
21+
func NewPGStatTopQueriesExecutionTime(config collectorConfig) (Collector, error) {
22+
return &PGStatTopQueriesExecutionTime{log: config.logger}, nil
23+
}
24+
25+
var (
26+
statTotalExecutionTime = prometheus.NewDesc(
27+
prometheus.BuildFQName(namespace, statTopQueriesExecutionTime, "total_seconds"),
28+
"Total time spent in the statement, in milliseconds",
29+
[]string{"queryid", "datname", "user"},
30+
prometheus.Labels{},
31+
)
32+
statMinimumExecutionTime = prometheus.NewDesc(
33+
prometheus.BuildFQName(namespace, statTopQueriesExecutionTime, "min_time_seconds"),
34+
"Minimum time spent in the statement, in milliseconds",
35+
[]string{"queryid", "datname", "user"},
36+
prometheus.Labels{},
37+
)
38+
39+
statMaximumExecutionTime = prometheus.NewDesc(
40+
prometheus.BuildFQName(namespace, statTopQueriesExecutionTime, "max_time_seconds"),
41+
"Maximum time spent in the statement, in milliseconds",
42+
[]string{"queryid", "datname", "user"},
43+
prometheus.Labels{},
44+
)
45+
46+
statMeanExecutionTime = prometheus.NewDesc(
47+
prometheus.BuildFQName(namespace, statTopQueriesExecutionTime, "mean_time"),
48+
"Mean time spent in the statement, in milliseconds",
49+
[]string{"queryid", "datname", "user"},
50+
prometheus.Labels{},
51+
)
52+
53+
statTopQueryExecutionQuery = `SELECT
54+
pg_get_userbyid(userid) as user,
55+
pg_database.datname,
56+
pg_stat_statements.queryid,
57+
pg_stat_statements.mean_time / 1000.0 as mean_time,
58+
pg_stat_statements.total_time / 1000.0 as total_seconds,
59+
pg_stat_statements.min_time / 1000.0 as min_time_seconds,
60+
pg_stat_statements.max_time / 1000.0 as max_time_seconds,
61+
pg_stat_statements.calls
62+
FROM pg_stat_statements
63+
JOIN pg_database
64+
ON pg_database.id = pg_stat_statements.dbid
65+
WHERE
66+
total_time > (
67+
SELECT percentile_cont(0.1)
68+
WITHIN GROUP (ORDER BY total_time)
69+
FROM pg_stat_statements
70+
)
71+
ORDER BY total_seconds DESC
72+
LIMIT 100;`
73+
)
74+
75+
func (PGStatTopQueriesExecutionTime) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
76+
db := instance.getDB()
77+
rows, err := db.QueryContext(ctx, statTopQueryExecutionQuery)
78+
79+
if err != nil {
80+
return err
81+
}
82+
defer rows.Close()
83+
84+
for rows.Next() {
85+
var user, datName, queryid sql.NullString
86+
var meanTime, totalSeconds, minTimeSeconds, maxTimeSeconds sql.NullFloat64
87+
var calls sql.NullInt64
88+
89+
if err := rows.Scan(&user, &datName, &meanTime, &totalSeconds, &minTimeSeconds, &maxTimeSeconds, &calls); err != nil {
90+
return err
91+
}
92+
93+
userLabel := "unknown"
94+
if user.Valid {
95+
userLabel = user.String
96+
}
97+
98+
datnameLabel := "unknown"
99+
if datName.Valid {
100+
datnameLabel = datName.String
101+
}
102+
103+
queryIdLabel := "unknown"
104+
if queryid.Valid {
105+
queryIdLabel = queryid.String
106+
}
107+
108+
totalSecondsMetric := 0.0
109+
if totalSeconds.Valid {
110+
totalSecondsMetric = totalSeconds.Float64
111+
}
112+
ch <- prometheus.MustNewConstMetric(
113+
statTotalExecutionTime,
114+
prometheus.CounterValue,
115+
totalSecondsMetric,
116+
userLabel, datnameLabel, queryIdLabel,
117+
)
118+
119+
meanTimeSecondsMetric := 0.0
120+
if meanTime.Valid {
121+
meanTimeSecondsMetric = meanTime.Float64
122+
}
123+
ch <- prometheus.MustNewConstMetric(
124+
statMeanExecutionTime,
125+
prometheus.CounterValue,
126+
meanTimeSecondsMetric,
127+
userLabel, datnameLabel, queryIdLabel,
128+
)
129+
130+
minTimeSecondsMetric := 0.0
131+
if minTimeSeconds.Valid {
132+
minTimeSecondsMetric = minTimeSeconds.Float64
133+
}
134+
ch <- prometheus.MustNewConstMetric(
135+
statMinimumExecutionTime,
136+
prometheus.CounterValue,
137+
minTimeSecondsMetric,
138+
userLabel, datnameLabel, queryIdLabel,
139+
)
140+
141+
maxTimeSecondsMetric := 0.0
142+
if maxTimeSeconds.Valid {
143+
maxTimeSecondsMetric = maxTimeSeconds.Float64
144+
}
145+
ch <- prometheus.MustNewConstMetric(
146+
statMaximumExecutionTime,
147+
prometheus.CounterValue,
148+
maxTimeSecondsMetric,
149+
userLabel, datnameLabel, queryIdLabel,
150+
)
151+
152+
callsMetric := 0.0
153+
if calls.Valid {
154+
callsMetric = float64(calls.Int64)
155+
}
156+
157+
ch <- prometheus.MustNewConstMetric(
158+
statTotalExecutionTime,
159+
prometheus.CounterValue,
160+
callsMetric,
161+
userLabel, datnameLabel, queryIdLabel,
162+
)
163+
}
164+
return nil
165+
}

0 commit comments

Comments
 (0)