github.com/netdata/go.d.plugin@v0.58.1/modules/postgres/do_query_global.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package postgres 4 5 import ( 6 "fmt" 7 "strconv" 8 ) 9 10 func (p *Postgres) doQueryGlobalMetrics() error { 11 if err := p.doQueryConnectionsUsed(); err != nil { 12 return fmt.Errorf("querying server connections used error: %v", err) 13 } 14 if err := p.doQueryConnectionsState(); err != nil { 15 return fmt.Errorf("querying server connections state error: %v", err) 16 } 17 if err := p.doQueryCheckpoints(); err != nil { 18 return fmt.Errorf("querying database conflicts error: %v", err) 19 } 20 if err := p.doQueryUptime(); err != nil { 21 return fmt.Errorf("querying server uptime error: %v", err) 22 } 23 if err := p.doQueryTXIDWraparound(); err != nil { 24 return fmt.Errorf("querying txid wraparound error: %v", err) 25 } 26 if err := p.doQueryWALWrites(); err != nil { 27 return fmt.Errorf("querying wal writes error: %v", err) 28 } 29 if err := p.doQueryCatalogRelations(); err != nil { 30 return fmt.Errorf("querying catalog relations error: %v", err) 31 } 32 if p.pgVersion >= pgVersion94 { 33 if err := p.doQueryAutovacuumWorkers(); err != nil { 34 return fmt.Errorf("querying autovacuum workers error: %v", err) 35 } 36 } 37 if p.pgVersion >= pgVersion10 { 38 if err := p.doQueryXactQueryRunningTime(); err != nil { 39 return fmt.Errorf("querying xact/query running time: %v", err) 40 } 41 } 42 43 if !p.isSuperUser() { 44 return nil 45 } 46 47 if p.pgVersion >= pgVersion94 { 48 if err := p.doQueryWALFiles(); err != nil { 49 return fmt.Errorf("querying wal files error: %v", err) 50 } 51 } 52 if err := p.doQueryWALArchiveFiles(); err != nil { 53 return fmt.Errorf("querying wal archive files error: %v", err) 54 } 55 56 return nil 57 } 58 59 func (p *Postgres) doQueryConnectionsUsed() error { 60 q := queryServerCurrentConnectionsUsed() 61 62 var v string 63 if err := p.doQueryRow(q, &v); err != nil { 64 return err 65 } 66 67 p.mx.connUsed = parseInt(v) 68 69 return nil 70 } 71 72 func (p *Postgres) doQueryConnectionsState() error { 73 q := queryServerConnectionsState() 74 75 var state string 76 return p.doQuery(q, func(column, value string, rowEnd bool) { 77 switch column { 78 case "state": 79 state = value 80 case "count": 81 switch state { 82 case "active": 83 p.mx.connStateActive = parseInt(value) 84 case "idle": 85 p.mx.connStateIdle = parseInt(value) 86 case "idle in transaction": 87 p.mx.connStateIdleInTrans = parseInt(value) 88 case "idle in transaction (aborted)": 89 p.mx.connStateIdleInTransAborted = parseInt(value) 90 case "fastpath function call": 91 p.mx.connStateFastpathFunctionCall = parseInt(value) 92 case "disabled": 93 p.mx.connStateDisabled = parseInt(value) 94 } 95 } 96 }) 97 } 98 99 func (p *Postgres) doQueryCheckpoints() error { 100 q := queryCheckpoints() 101 102 return p.doQuery(q, func(column, value string, _ bool) { 103 switch column { 104 case "checkpoints_timed": 105 p.mx.checkpointsTimed = parseInt(value) 106 case "checkpoints_req": 107 p.mx.checkpointsReq = parseInt(value) 108 case "checkpoint_write_time": 109 p.mx.checkpointWriteTime = parseInt(value) 110 case "checkpoint_sync_time": 111 p.mx.checkpointSyncTime = parseInt(value) 112 case "buffers_checkpoint_bytes": 113 p.mx.buffersCheckpoint = parseInt(value) 114 case "buffers_clean_bytes": 115 p.mx.buffersClean = parseInt(value) 116 case "maxwritten_clean": 117 p.mx.maxwrittenClean = parseInt(value) 118 case "buffers_backend_bytes": 119 p.mx.buffersBackend = parseInt(value) 120 case "buffers_backend_fsync": 121 p.mx.buffersBackendFsync = parseInt(value) 122 case "buffers_alloc_bytes": 123 p.mx.buffersAlloc = parseInt(value) 124 } 125 }) 126 } 127 128 func (p *Postgres) doQueryUptime() error { 129 q := queryServerUptime() 130 131 var s string 132 if err := p.doQueryRow(q, &s); err != nil { 133 return err 134 } 135 136 p.mx.uptime = parseFloat(s) 137 138 return nil 139 } 140 141 func (p *Postgres) doQueryTXIDWraparound() error { 142 q := queryTXIDWraparound() 143 144 return p.doQuery(q, func(column, value string, _ bool) { 145 switch column { 146 case "oldest_current_xid": 147 p.mx.oldestXID = parseInt(value) 148 case "percent_towards_wraparound": 149 p.mx.percentTowardsWraparound = parseInt(value) 150 case "percent_towards_emergency_autovacuum": 151 p.mx.percentTowardsEmergencyAutovacuum = parseInt(value) 152 } 153 }) 154 } 155 156 func (p *Postgres) doQueryWALWrites() error { 157 q := queryWALWrites(p.pgVersion) 158 159 var v int64 160 if err := p.doQueryRow(q, &v); err != nil { 161 return err 162 } 163 164 p.mx.walWrites = v 165 166 return nil 167 } 168 169 func (p *Postgres) doQueryWALFiles() error { 170 q := queryWALFiles(p.pgVersion) 171 172 return p.doQuery(q, func(column, value string, _ bool) { 173 switch column { 174 case "wal_recycled_files": 175 p.mx.walRecycledFiles = parseInt(value) 176 case "wal_written_files": 177 p.mx.walWrittenFiles = parseInt(value) 178 } 179 }) 180 } 181 182 func (p *Postgres) doQueryWALArchiveFiles() error { 183 q := queryWALArchiveFiles(p.pgVersion) 184 185 return p.doQuery(q, func(column, value string, _ bool) { 186 switch column { 187 case "wal_archive_files_ready_count": 188 p.mx.walArchiveFilesReady = parseInt(value) 189 case "wal_archive_files_done_count": 190 p.mx.walArchiveFilesDone = parseInt(value) 191 } 192 }) 193 } 194 195 func (p *Postgres) doQueryCatalogRelations() error { 196 q := queryCatalogRelations() 197 198 var kind string 199 var count, size int64 200 return p.doQuery(q, func(column, value string, rowEnd bool) { 201 switch column { 202 case "relkind": 203 kind = value 204 case "count": 205 count = parseInt(value) 206 case "size": 207 size = parseInt(value) 208 } 209 if !rowEnd { 210 return 211 } 212 // https://www.postgresql.org/docs/current/catalog-pg-class.html 213 switch kind { 214 case "r": 215 p.mx.relkindOrdinaryTable = count 216 p.mx.relkindOrdinaryTableSize = size 217 case "i": 218 p.mx.relkindIndex = count 219 p.mx.relkindIndexSize = size 220 case "S": 221 p.mx.relkindSequence = count 222 p.mx.relkindSequenceSize = size 223 case "t": 224 p.mx.relkindTOASTTable = count 225 p.mx.relkindTOASTTableSize = size 226 case "v": 227 p.mx.relkindView = count 228 p.mx.relkindViewSize = size 229 case "m": 230 p.mx.relkindMatView = count 231 p.mx.relkindMatViewSize = size 232 case "c": 233 p.mx.relkindCompositeType = count 234 p.mx.relkindCompositeTypeSize = size 235 case "f": 236 p.mx.relkindForeignTable = count 237 p.mx.relkindForeignTableSize = size 238 case "p": 239 p.mx.relkindPartitionedTable = count 240 p.mx.relkindPartitionedTableSize = size 241 case "I": 242 p.mx.relkindPartitionedIndex = count 243 p.mx.relkindPartitionedIndexSize = size 244 } 245 }) 246 } 247 248 func (p *Postgres) doQueryAutovacuumWorkers() error { 249 q := queryAutovacuumWorkers() 250 251 return p.doQuery(q, func(column, value string, _ bool) { 252 switch column { 253 case "autovacuum_analyze": 254 p.mx.autovacuumWorkersAnalyze = parseInt(value) 255 case "autovacuum_vacuum_analyze": 256 p.mx.autovacuumWorkersVacuumAnalyze = parseInt(value) 257 case "autovacuum_vacuum": 258 p.mx.autovacuumWorkersVacuum = parseInt(value) 259 case "autovacuum_vacuum_freeze": 260 p.mx.autovacuumWorkersVacuumFreeze = parseInt(value) 261 case "autovacuum_brin_summarize": 262 p.mx.autovacuumWorkersBrinSummarize = parseInt(value) 263 } 264 }) 265 } 266 267 func (p *Postgres) doQueryXactQueryRunningTime() error { 268 q := queryXactQueryRunningTime() 269 270 var state string 271 return p.doQuery(q, func(column, value string, _ bool) { 272 switch column { 273 case "state": 274 state = value 275 case "xact_running_time": 276 v, _ := strconv.ParseFloat(value, 64) 277 p.mx.xactTimeHist.Observe(v) 278 case "query_running_time": 279 if state == "active" { 280 v, _ := strconv.ParseFloat(value, 64) 281 p.mx.queryTimeHist.Observe(v) 282 } 283 } 284 }) 285 }