pangolin_exporter
446 строк · 13.3 Кб
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.
13
14package collector
15
16import (
17"context"
18"database/sql"
19
20"github.com/go-kit/log"
21"github.com/prometheus/client_golang/prometheus"
22)
23
24const userTableSubsystem = "stat_user_tables"
25
26func init() {
27registerCollector(userTableSubsystem, defaultEnabled, NewPGStatUserTablesCollector)
28}
29
30type PGStatUserTablesCollector struct {
31log log.Logger
32}
33
34func NewPGStatUserTablesCollector(config collectorConfig) (Collector, error) {
35return &PGStatUserTablesCollector{log: config.logger}, nil
36}
37
38var (
39statUserTablesSeqScan = prometheus.NewDesc(
40prometheus.BuildFQName(namespace, userTableSubsystem, "seq_scan"),
41"Number of sequential scans initiated on this table",
42[]string{"datname", "schemaname", "relname"},
43prometheus.Labels{},
44)
45statUserTablesSeqTupRead = prometheus.NewDesc(
46prometheus.BuildFQName(namespace, userTableSubsystem, "seq_tup_read"),
47"Number of live rows fetched by sequential scans",
48[]string{"datname", "schemaname", "relname"},
49prometheus.Labels{},
50)
51statUserTablesIdxScan = prometheus.NewDesc(
52prometheus.BuildFQName(namespace, userTableSubsystem, "idx_scan"),
53"Number of index scans initiated on this table",
54[]string{"datname", "schemaname", "relname"},
55prometheus.Labels{},
56)
57statUserTablesIdxTupFetch = prometheus.NewDesc(
58prometheus.BuildFQName(namespace, userTableSubsystem, "idx_tup_fetch"),
59"Number of live rows fetched by index scans",
60[]string{"datname", "schemaname", "relname"},
61prometheus.Labels{},
62)
63statUserTablesNTupIns = prometheus.NewDesc(
64prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_ins"),
65"Number of rows inserted",
66[]string{"datname", "schemaname", "relname"},
67prometheus.Labels{},
68)
69statUserTablesNTupUpd = prometheus.NewDesc(
70prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_upd"),
71"Number of rows updated",
72[]string{"datname", "schemaname", "relname"},
73prometheus.Labels{},
74)
75statUserTablesNTupDel = prometheus.NewDesc(
76prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_del"),
77"Number of rows deleted",
78[]string{"datname", "schemaname", "relname"},
79prometheus.Labels{},
80)
81statUserTablesNTupHotUpd = prometheus.NewDesc(
82prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_hot_upd"),
83"Number of rows HOT updated (i.e., with no separate index update required)",
84[]string{"datname", "schemaname", "relname"},
85prometheus.Labels{},
86)
87statUserTablesNLiveTup = prometheus.NewDesc(
88prometheus.BuildFQName(namespace, userTableSubsystem, "n_live_tup"),
89"Estimated number of live rows",
90[]string{"datname", "schemaname", "relname"},
91prometheus.Labels{},
92)
93statUserTablesNDeadTup = prometheus.NewDesc(
94prometheus.BuildFQName(namespace, userTableSubsystem, "n_dead_tup"),
95"Estimated number of dead rows",
96[]string{"datname", "schemaname", "relname"},
97prometheus.Labels{},
98)
99statUserTablesNModSinceAnalyze = prometheus.NewDesc(
100prometheus.BuildFQName(namespace, userTableSubsystem, "n_mod_since_analyze"),
101"Estimated number of rows changed since last analyze",
102[]string{"datname", "schemaname", "relname"},
103prometheus.Labels{},
104)
105statUserTablesLastVacuum = prometheus.NewDesc(
106prometheus.BuildFQName(namespace, userTableSubsystem, "last_vacuum"),
107"Last time at which this table was manually vacuumed (not counting VACUUM FULL)",
108[]string{"datname", "schemaname", "relname"},
109prometheus.Labels{},
110)
111statUserTablesLastAutovacuum = prometheus.NewDesc(
112prometheus.BuildFQName(namespace, userTableSubsystem, "last_autovacuum"),
113"Last time at which this table was vacuumed by the autovacuum daemon",
114[]string{"datname", "schemaname", "relname"},
115prometheus.Labels{},
116)
117statUserTablesLastAnalyze = prometheus.NewDesc(
118prometheus.BuildFQName(namespace, userTableSubsystem, "last_analyze"),
119"Last time at which this table was manually analyzed",
120[]string{"datname", "schemaname", "relname"},
121prometheus.Labels{},
122)
123statUserTablesLastAutoanalyze = prometheus.NewDesc(
124prometheus.BuildFQName(namespace, userTableSubsystem, "last_autoanalyze"),
125"Last time at which this table was analyzed by the autovacuum daemon",
126[]string{"datname", "schemaname", "relname"},
127prometheus.Labels{},
128)
129statUserTablesVacuumCount = prometheus.NewDesc(
130prometheus.BuildFQName(namespace, userTableSubsystem, "vacuum_count"),
131"Number of times this table has been manually vacuumed (not counting VACUUM FULL)",
132[]string{"datname", "schemaname", "relname"},
133prometheus.Labels{},
134)
135statUserTablesAutovacuumCount = prometheus.NewDesc(
136prometheus.BuildFQName(namespace, userTableSubsystem, "autovacuum_count"),
137"Number of times this table has been vacuumed by the autovacuum daemon",
138[]string{"datname", "schemaname", "relname"},
139prometheus.Labels{},
140)
141statUserTablesAnalyzeCount = prometheus.NewDesc(
142prometheus.BuildFQName(namespace, userTableSubsystem, "analyze_count"),
143"Number of times this table has been manually analyzed",
144[]string{"datname", "schemaname", "relname"},
145prometheus.Labels{},
146)
147statUserTablesAutoanalyzeCount = prometheus.NewDesc(
148prometheus.BuildFQName(namespace, userTableSubsystem, "autoanalyze_count"),
149"Number of times this table has been analyzed by the autovacuum daemon",
150[]string{"datname", "schemaname", "relname"},
151prometheus.Labels{},
152)
153statUserTablesTotalSize = prometheus.NewDesc(
154prometheus.BuildFQName(namespace, userTableSubsystem, "size_bytes"),
155"Total disk space used by this table, in bytes, including all indexes and TOAST data",
156[]string{"datname", "schemaname", "relname"},
157prometheus.Labels{},
158)
159
160statUserTablesQuery = `SELECT
161current_database() datname,
162schemaname,
163relname,
164seq_scan,
165seq_tup_read,
166idx_scan,
167idx_tup_fetch,
168n_tup_ins,
169n_tup_upd,
170n_tup_del,
171n_tup_hot_upd,
172n_live_tup,
173n_dead_tup,
174n_mod_since_analyze,
175COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum,
176COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum,
177COALESCE(last_analyze, '1970-01-01Z') as last_analyze,
178COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze,
179vacuum_count,
180autovacuum_count,
181analyze_count,
182autoanalyze_count,
183pg_total_relation_size(relid) as total_size
184FROM
185pg_stat_user_tables`
186)
187
188func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
189db := instance.getDB()
190rows, err := db.QueryContext(ctx,
191statUserTablesQuery)
192
193if err != nil {
194return err
195}
196defer rows.Close()
197
198for rows.Next() {
199var datname, schemaname, relname sql.NullString
200var seqScan, seqTupRead, idxScan, idxTupFetch, nTupIns, nTupUpd, nTupDel, nTupHotUpd, nLiveTup, nDeadTup,
201nModSinceAnalyze, vacuumCount, autovacuumCount, analyzeCount, autoanalyzeCount, totalSize sql.NullInt64
202var lastVacuum, lastAutovacuum, lastAnalyze, lastAutoanalyze sql.NullTime
203
204if err := rows.Scan(&datname, &schemaname, &relname, &seqScan, &seqTupRead, &idxScan, &idxTupFetch, &nTupIns, &nTupUpd, &nTupDel, &nTupHotUpd, &nLiveTup, &nDeadTup, &nModSinceAnalyze, &lastVacuum, &lastAutovacuum, &lastAnalyze, &lastAutoanalyze, &vacuumCount, &autovacuumCount, &analyzeCount, &autoanalyzeCount, &totalSize); err != nil {
205return err
206}
207
208datnameLabel := "unknown"
209if datname.Valid {
210datnameLabel = datname.String
211}
212schemanameLabel := "unknown"
213if schemaname.Valid {
214schemanameLabel = schemaname.String
215}
216relnameLabel := "unknown"
217if relname.Valid {
218relnameLabel = relname.String
219}
220
221seqScanMetric := 0.0
222if seqScan.Valid {
223seqScanMetric = float64(seqScan.Int64)
224}
225ch <- prometheus.MustNewConstMetric(
226statUserTablesSeqScan,
227prometheus.CounterValue,
228seqScanMetric,
229datnameLabel, schemanameLabel, relnameLabel,
230)
231
232seqTupReadMetric := 0.0
233if seqTupRead.Valid {
234seqTupReadMetric = float64(seqTupRead.Int64)
235}
236ch <- prometheus.MustNewConstMetric(
237statUserTablesSeqTupRead,
238prometheus.CounterValue,
239seqTupReadMetric,
240datnameLabel, schemanameLabel, relnameLabel,
241)
242
243idxScanMetric := 0.0
244if idxScan.Valid {
245idxScanMetric = float64(idxScan.Int64)
246}
247ch <- prometheus.MustNewConstMetric(
248statUserTablesIdxScan,
249prometheus.CounterValue,
250idxScanMetric,
251datnameLabel, schemanameLabel, relnameLabel,
252)
253
254idxTupFetchMetric := 0.0
255if idxTupFetch.Valid {
256idxTupFetchMetric = float64(idxTupFetch.Int64)
257}
258ch <- prometheus.MustNewConstMetric(
259statUserTablesIdxTupFetch,
260prometheus.CounterValue,
261idxTupFetchMetric,
262datnameLabel, schemanameLabel, relnameLabel,
263)
264
265nTupInsMetric := 0.0
266if nTupIns.Valid {
267nTupInsMetric = float64(nTupIns.Int64)
268}
269ch <- prometheus.MustNewConstMetric(
270statUserTablesNTupIns,
271prometheus.CounterValue,
272nTupInsMetric,
273datnameLabel, schemanameLabel, relnameLabel,
274)
275
276nTupUpdMetric := 0.0
277if nTupUpd.Valid {
278nTupUpdMetric = float64(nTupUpd.Int64)
279}
280ch <- prometheus.MustNewConstMetric(
281statUserTablesNTupUpd,
282prometheus.CounterValue,
283nTupUpdMetric,
284datnameLabel, schemanameLabel, relnameLabel,
285)
286
287nTupDelMetric := 0.0
288if nTupDel.Valid {
289nTupDelMetric = float64(nTupDel.Int64)
290}
291ch <- prometheus.MustNewConstMetric(
292statUserTablesNTupDel,
293prometheus.CounterValue,
294nTupDelMetric,
295datnameLabel, schemanameLabel, relnameLabel,
296)
297
298nTupHotUpdMetric := 0.0
299if nTupHotUpd.Valid {
300nTupHotUpdMetric = float64(nTupHotUpd.Int64)
301}
302ch <- prometheus.MustNewConstMetric(
303statUserTablesNTupHotUpd,
304prometheus.CounterValue,
305nTupHotUpdMetric,
306datnameLabel, schemanameLabel, relnameLabel,
307)
308
309nLiveTupMetric := 0.0
310if nLiveTup.Valid {
311nLiveTupMetric = float64(nLiveTup.Int64)
312}
313ch <- prometheus.MustNewConstMetric(
314statUserTablesNLiveTup,
315prometheus.GaugeValue,
316nLiveTupMetric,
317datnameLabel, schemanameLabel, relnameLabel,
318)
319
320nDeadTupMetric := 0.0
321if nDeadTup.Valid {
322nDeadTupMetric = float64(nDeadTup.Int64)
323}
324ch <- prometheus.MustNewConstMetric(
325statUserTablesNDeadTup,
326prometheus.GaugeValue,
327nDeadTupMetric,
328datnameLabel, schemanameLabel, relnameLabel,
329)
330
331nModSinceAnalyzeMetric := 0.0
332if nModSinceAnalyze.Valid {
333nModSinceAnalyzeMetric = float64(nModSinceAnalyze.Int64)
334}
335ch <- prometheus.MustNewConstMetric(
336statUserTablesNModSinceAnalyze,
337prometheus.GaugeValue,
338nModSinceAnalyzeMetric,
339datnameLabel, schemanameLabel, relnameLabel,
340)
341
342lastVacuumMetric := 0.0
343if lastVacuum.Valid {
344lastVacuumMetric = float64(lastVacuum.Time.Unix())
345}
346ch <- prometheus.MustNewConstMetric(
347statUserTablesLastVacuum,
348prometheus.GaugeValue,
349lastVacuumMetric,
350datnameLabel, schemanameLabel, relnameLabel,
351)
352
353lastAutovacuumMetric := 0.0
354if lastAutovacuum.Valid {
355lastAutovacuumMetric = float64(lastAutovacuum.Time.Unix())
356}
357ch <- prometheus.MustNewConstMetric(
358statUserTablesLastAutovacuum,
359prometheus.GaugeValue,
360lastAutovacuumMetric,
361datnameLabel, schemanameLabel, relnameLabel,
362)
363
364lastAnalyzeMetric := 0.0
365if lastAnalyze.Valid {
366lastAnalyzeMetric = float64(lastAnalyze.Time.Unix())
367}
368ch <- prometheus.MustNewConstMetric(
369statUserTablesLastAnalyze,
370prometheus.GaugeValue,
371lastAnalyzeMetric,
372datnameLabel, schemanameLabel, relnameLabel,
373)
374
375lastAutoanalyzeMetric := 0.0
376if lastAutoanalyze.Valid {
377lastAutoanalyzeMetric = float64(lastAutoanalyze.Time.Unix())
378}
379ch <- prometheus.MustNewConstMetric(
380statUserTablesLastAutoanalyze,
381prometheus.GaugeValue,
382lastAutoanalyzeMetric,
383datnameLabel, schemanameLabel, relnameLabel,
384)
385
386vacuumCountMetric := 0.0
387if vacuumCount.Valid {
388vacuumCountMetric = float64(vacuumCount.Int64)
389}
390ch <- prometheus.MustNewConstMetric(
391statUserTablesVacuumCount,
392prometheus.CounterValue,
393vacuumCountMetric,
394datnameLabel, schemanameLabel, relnameLabel,
395)
396
397autovacuumCountMetric := 0.0
398if autovacuumCount.Valid {
399autovacuumCountMetric = float64(autovacuumCount.Int64)
400}
401ch <- prometheus.MustNewConstMetric(
402statUserTablesAutovacuumCount,
403prometheus.CounterValue,
404autovacuumCountMetric,
405datnameLabel, schemanameLabel, relnameLabel,
406)
407
408analyzeCountMetric := 0.0
409if analyzeCount.Valid {
410analyzeCountMetric = float64(analyzeCount.Int64)
411}
412ch <- prometheus.MustNewConstMetric(
413statUserTablesAnalyzeCount,
414prometheus.CounterValue,
415analyzeCountMetric,
416datnameLabel, schemanameLabel, relnameLabel,
417)
418
419autoanalyzeCountMetric := 0.0
420if autoanalyzeCount.Valid {
421autoanalyzeCountMetric = float64(autoanalyzeCount.Int64)
422}
423ch <- prometheus.MustNewConstMetric(
424statUserTablesAutoanalyzeCount,
425prometheus.CounterValue,
426autoanalyzeCountMetric,
427datnameLabel, schemanameLabel, relnameLabel,
428)
429
430totalSizeMetric := 0.0
431if totalSize.Valid {
432totalSizeMetric = float64(totalSize.Int64)
433}
434ch <- prometheus.MustNewConstMetric(
435statUserTablesTotalSize,
436prometheus.GaugeValue,
437totalSizeMetric,
438datnameLabel, schemanameLabel, relnameLabel,
439)
440}
441
442if err := rows.Err(); err != nil {
443return err
444}
445return nil
446}
447