master
go 160 lines 5.11 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package postgres
4
5 import (
6 "fmt"
7 )
8
9 func (c *Collector) doQueryDatabasesMetrics() error {
10 if err := c.doQueryDatabaseStats(); err != nil {
11 return fmt.Errorf("querying database stats error: %v", err)
12 }
13 if err := c.doQueryDatabaseSize(); err != nil {
14 return fmt.Errorf("querying database size error: %v", err)
15 }
16 if c.isPGInRecovery() {
17 if err := c.doQueryDatabaseConflicts(); err != nil {
18 return fmt.Errorf("querying database conflicts error: %v", err)
19 }
20 }
21 if err := c.doQueryDatabaseLocks(); err != nil {
22 return fmt.Errorf("querying database locks error: %v", err)
23 }
24 return nil
25 }
26
27 func (c *Collector) doQueryDatabaseStats() error {
28 q := queryDatabaseStats()
29
30 var db string
31 return c.doQuery(q, func(column, value string, _ bool) {
32 switch column {
33 case "datname":
34 db = value
35 c.getDBMetrics(db).updated = true
36 case "numbackends":
37 c.getDBMetrics(db).numBackends = parseInt(value)
38 case "datconnlimit":
39 c.getDBMetrics(db).datConnLimit = parseInt(value)
40 case "xact_commit":
41 c.getDBMetrics(db).xactCommit = parseInt(value)
42 case "xact_rollback":
43 c.getDBMetrics(db).xactRollback = parseInt(value)
44 case "blks_read_bytes":
45 c.getDBMetrics(db).blksRead.last = parseInt(value)
46 case "blks_hit_bytes":
47 c.getDBMetrics(db).blksHit.last = parseInt(value)
48 case "tup_returned":
49 c.getDBMetrics(db).tupReturned.last = parseInt(value)
50 case "tup_fetched":
51 c.getDBMetrics(db).tupFetched.last = parseInt(value)
52 case "tup_inserted":
53 c.getDBMetrics(db).tupInserted = parseInt(value)
54 case "tup_updated":
55 c.getDBMetrics(db).tupUpdated = parseInt(value)
56 case "tup_deleted":
57 c.getDBMetrics(db).tupDeleted = parseInt(value)
58 case "conflicts":
59 c.getDBMetrics(db).conflicts = parseInt(value)
60 case "temp_files":
61 c.getDBMetrics(db).tempFiles = parseInt(value)
62 case "temp_bytes":
63 c.getDBMetrics(db).tempBytes = parseInt(value)
64 case "deadlocks":
65 c.getDBMetrics(db).deadlocks = parseInt(value)
66 }
67 })
68 }
69
70 func (c *Collector) doQueryDatabaseSize() error {
71 q := queryDatabaseSize(c.pgVersion)
72
73 var db string
74 return c.doQuery(q, func(column, value string, _ bool) {
75 switch column {
76 case "datname":
77 db = value
78 case "size":
79 c.getDBMetrics(db).size = new(parseInt(value))
80 }
81 })
82 }
83
84 func (c *Collector) doQueryDatabaseConflicts() error {
85 q := queryDatabaseConflicts()
86
87 var db string
88 return c.doQuery(q, func(column, value string, _ bool) {
89 switch column {
90 case "datname":
91 db = value
92 c.getDBMetrics(db).updated = true
93 case "confl_tablespace":
94 c.getDBMetrics(db).conflTablespace = parseInt(value)
95 case "confl_lock":
96 c.getDBMetrics(db).conflLock = parseInt(value)
97 case "confl_snapshot":
98 c.getDBMetrics(db).conflSnapshot = parseInt(value)
99 case "confl_bufferpin":
100 c.getDBMetrics(db).conflBufferpin = parseInt(value)
101 case "confl_deadlock":
102 c.getDBMetrics(db).conflDeadlock = parseInt(value)
103 }
104 })
105 }
106
107 func (c *Collector) doQueryDatabaseLocks() error {
108 q := queryDatabaseLocks()
109
110 var db, mode string
111 var granted bool
112 return c.doQuery(q, func(column, value string, _ bool) {
113 switch column {
114 case "datname":
115 db = value
116 c.getDBMetrics(db).updated = true
117 case "mode":
118 mode = value
119 case "granted":
120 granted = value == "true" || value == "t"
121 case "locks_count":
122 // https://github.com/postgres/postgres/blob/7c34555f8c39eeefcc45b3c3f027d7a063d738fc/src/include/storage/lockdefs.h#L36-L45
123 // https://www.postgresql.org/docs/7.2/locking-tables.html
124 switch {
125 case mode == "AccessShareLock" && granted:
126 c.getDBMetrics(db).accessShareLockHeld = parseInt(value)
127 case mode == "AccessShareLock":
128 c.getDBMetrics(db).accessShareLockAwaited = parseInt(value)
129 case mode == "RowShareLock" && granted:
130 c.getDBMetrics(db).rowShareLockHeld = parseInt(value)
131 case mode == "RowShareLock":
132 c.getDBMetrics(db).rowShareLockAwaited = parseInt(value)
133 case mode == "RowExclusiveLock" && granted:
134 c.getDBMetrics(db).rowExclusiveLockHeld = parseInt(value)
135 case mode == "RowExclusiveLock":
136 c.getDBMetrics(db).rowExclusiveLockAwaited = parseInt(value)
137 case mode == "ShareUpdateExclusiveLock" && granted:
138 c.getDBMetrics(db).shareUpdateExclusiveLockHeld = parseInt(value)
139 case mode == "ShareUpdateExclusiveLock":
140 c.getDBMetrics(db).shareUpdateExclusiveLockAwaited = parseInt(value)
141 case mode == "ShareLock" && granted:
142 c.getDBMetrics(db).shareLockHeld = parseInt(value)
143 case mode == "ShareLock":
144 c.getDBMetrics(db).shareLockAwaited = parseInt(value)
145 case mode == "ShareRowExclusiveLock" && granted:
146 c.getDBMetrics(db).shareRowExclusiveLockHeld = parseInt(value)
147 case mode == "ShareRowExclusiveLock":
148 c.getDBMetrics(db).shareRowExclusiveLockAwaited = parseInt(value)
149 case mode == "ExclusiveLock" && granted:
150 c.getDBMetrics(db).exclusiveLockHeld = parseInt(value)
151 case mode == "ExclusiveLock":
152 c.getDBMetrics(db).exclusiveLockAwaited = parseInt(value)
153 case mode == "AccessExclusiveLock" && granted:
154 c.getDBMetrics(db).accessExclusiveLockHeld = parseInt(value)
155 case mode == "AccessExclusiveLock":
156 c.getDBMetrics(db).accessExclusiveLockAwaited = parseInt(value)
157 }
158 }
159 })
160 }