@@ -81,6 +81,8 @@ type Instance struct {
8181 PreparedStatements bool `toml:"prepared_statements"`
8282 EnableStatementMetrics bool `toml:"enable_statement_metrics"`
8383 StatementMetricsLimit int `toml:"statement_metrics_limit"`
84+ DisablePgStatDatabase bool `toml:"disable_pg_stat_database"`
85+ DisablePgStatBgwriter bool `toml:"disable_pg_stat_bgwriter"`
8486 Metrics []MetricConfig `toml:"metrics"`
8587 TrimServerTagSpace bool `toml:"trim_server_tag_space"`
8688
@@ -94,7 +96,7 @@ type Instance struct {
9496
9597var ignoredColumns = map [string ]bool {"stats_reset" : true }
9698
97- func (p * Instance ) IgnoredColumns () map [string ]bool {
99+ func (ins * Instance ) IgnoredColumns () map [string ]bool {
98100 return ignoredColumns
99101}
100102
@@ -142,17 +144,12 @@ func (ins *Instance) Init() error {
142144}
143145
144146// closes any necessary channels and connections
145- func (p * Instance ) Drop () {
147+ func (ins * Instance ) Drop () {
146148 // Ignore the returned error as we cannot do anything about it anyway
147149 //nolint:errcheck,revive
148150}
149151
150152func (ins * Instance ) Gather (slist * types.SampleList ) {
151- var (
152- err error
153- query string
154- columns []string
155- )
156153 addr , err := ins .SanitizedAddress ()
157154 if err != nil {
158155 log .Println ("E! can't sanitize address :" , err )
@@ -171,40 +168,55 @@ func (ins *Instance) Gather(slist *types.SampleList) {
171168 }
172169 slist .PushSample (inputName , "up" , 1 , tags )
173170
171+ ins .gatherMetrics (slist )
172+ }
173+
174+ func (ins * Instance ) gatherMetrics (slist * types.SampleList ) {
175+ var (
176+ err error
177+ query string
178+ columns []string
179+ )
180+
174181 ins .db .SetMaxOpenConns (ins .MaxOpen )
175182 ins .db .SetMaxIdleConns (ins .MaxIdle )
176183 ins .db .SetConnMaxLifetime (time .Duration (ins .MaxLifetime ))
177184
178- if len (ins .Databases ) == 0 && len (ins .IgnoredDatabases ) == 0 {
179- query = `SELECT * FROM pg_stat_database`
180- } else if len (ins .IgnoredDatabases ) != 0 {
181- query = fmt .Sprintf (`SELECT * FROM pg_stat_database WHERE datname NOT IN ('%s')` ,
182- strings .Join (ins .IgnoredDatabases , "','" ))
183- } else {
184- query = fmt .Sprintf (`SELECT * FROM pg_stat_database WHERE datname IN ('%s')` ,
185- strings .Join (ins .Databases , "','" ))
186- }
187-
188- rows , err := ins .db .Query (query )
189- if err != nil {
190- log .Println ("E! failed to execute Query :" , err )
191- return
192- }
185+ if ! ins .DisablePgStatDatabase {
186+ if len (ins .Databases ) == 0 && len (ins .IgnoredDatabases ) == 0 {
187+ query = `SELECT * FROM pg_stat_database`
188+ } else if len (ins .IgnoredDatabases ) != 0 {
189+ query = fmt .Sprintf (`SELECT * FROM pg_stat_database WHERE datname NOT IN ('%s')` ,
190+ strings .Join (ins .IgnoredDatabases , "','" ))
191+ } else {
192+ query = fmt .Sprintf (`SELECT * FROM pg_stat_database WHERE datname IN ('%s')` ,
193+ strings .Join (ins .Databases , "','" ))
194+ }
193195
194- defer rows .Close ()
196+ rows , err := ins .db .Query (query )
197+ if err != nil {
198+ log .Println ("E! failed to execute Query :" , err )
199+ return
200+ }
195201
196- // grab the column information from the result
197- if columns , err = rows .Columns (); err != nil {
198- log .Println ("E! failed to grab column info:" , err )
199- return
200- }
202+ defer rows .Close ()
201203
202- for rows .Next () {
203- err = ins .accRow (rows , slist , "" , columns , columns , nil )
204- if err != nil {
205- log .Println ("E! failed to get row data:" , err )
204+ // grab the column information from the result
205+ if columns , err = rows .Columns (); err != nil {
206+ log .Println ("E! failed to grab column info:" , err )
206207 return
207208 }
209+
210+ for rows .Next () {
211+ err = ins .accRow (rows , slist , "" , columns , columns , nil )
212+ if err != nil {
213+ log .Println ("E! failed to get row data:" , err )
214+ return
215+ }
216+ }
217+ if err := rows .Err (); err != nil {
218+ log .Println ("E! failed to iterate pg_stat_database rows:" , err )
219+ }
208220 }
209221
210222 // Check Postgres Version
@@ -218,89 +230,100 @@ func (ins *Instance) Gather(slist *types.SampleList) {
218230 ins .Version = version
219231 }
220232
221- if ins .Version < 170000 {
222- query = `SELECT * FROM pg_stat_bgwriter`
223- bgWriterRow , err := ins .db .Query (query )
224- if err != nil {
225- log .Println ("E! failed to execute Query:" , err )
226- return
227- }
228-
229- defer bgWriterRow .Close ()
230-
231- // grab the column information from the result
232- if columns , err = bgWriterRow .Columns (); err != nil {
233- log .Println ("E! failed to grab column info:" , err )
234- return
235- }
236-
237- for bgWriterRow .Next () {
238- err = ins .accRow (bgWriterRow , slist , "" , columns , columns , nil )
233+ if ! ins .DisablePgStatBgwriter {
234+ if ins .Version < 170000 {
235+ query = `SELECT * FROM pg_stat_bgwriter`
236+ bgWriterRow , err := ins .db .Query (query )
239237 if err != nil {
240- log .Println ("E! failed to get row data :" , err )
238+ log .Println ("E! failed to execute Query :" , err )
241239 return
242240 }
243- }
244- } else {
245- // PG 17+ split pg_stat_bgwriter into pg_stat_bgwriter and pg_stat_checkpointer
246241
247- // 1. Query pg_stat_bgwriter (remaining columns)
248- query = `SELECT * FROM pg_stat_bgwriter`
249- bgWriterRow , err := ins .db .Query (query )
250- if err != nil {
251- log .Println ("E! failed to execute Query pg_stat_bgwriter:" , err )
252- return
253- }
254- defer bgWriterRow .Close ()
242+ defer bgWriterRow .Close ()
255243
256- if columns , err = bgWriterRow .Columns (); err != nil {
257- log .Println ("E! failed to grab column info for pg_stat_bgwriter:" , err )
258- return
259- }
244+ // grab the column information from the result
245+ if columns , err = bgWriterRow .Columns (); err != nil {
246+ log .Println ("E! failed to grab column info:" , err )
247+ return
248+ }
260249
261- for bgWriterRow .Next () {
262- err = ins .accRow (bgWriterRow , slist , "" , columns , columns , nil )
250+ for bgWriterRow .Next () {
251+ err = ins .accRow (bgWriterRow , slist , "" , columns , columns , nil )
252+ if err != nil {
253+ log .Println ("E! failed to get row data:" , err )
254+ return
255+ }
256+ }
257+ if err := bgWriterRow .Err (); err != nil {
258+ log .Println ("E! failed to iterate pg_stat_bgwriter rows:" , err )
259+ }
260+ } else {
261+ // PG 17+ split pg_stat_bgwriter into pg_stat_bgwriter and pg_stat_checkpointer
262+
263+ // 1. Query pg_stat_bgwriter (remaining columns)
264+ query = `SELECT * FROM pg_stat_bgwriter`
265+ bgWriterRow , err := ins .db .Query (query )
263266 if err != nil {
264- log .Println ("E! failed to get row data from pg_stat_bgwriter:" , err )
267+ log .Println ("E! failed to execute Query pg_stat_bgwriter:" , err )
265268 return
266269 }
267- }
270+ defer bgWriterRow . Close ()
268271
269- // 2. Query pg_stat_checkpointer (moved columns, aliased to old names for compatibility)
270- // num_timed -> checkpoints_timed
271- // num_requested -> checkpoints_req
272- // write_time -> checkpoint_write_time
273- // sync_time -> checkpoint_sync_time
274- // buffers_written -> buffers_checkpoint
275- query = `SELECT
276- num_timed AS checkpoints_timed,
277- num_requested AS checkpoints_req,
278- write_time AS checkpoint_write_time,
279- sync_time AS checkpoint_sync_time,
280- buffers_written AS buffers_checkpoint,
281- restartpoints_timed,
282- restartpoints_req,
283- restartpoints_done
284- FROM pg_stat_checkpointer`
285-
286- checkpointerRow , err := ins .db .Query (query )
287- if err != nil {
288- log .Println ("E! failed to get row data:" , err )
289- return
290- }
291- defer checkpointerRow .Close ()
272+ if columns , err = bgWriterRow .Columns (); err != nil {
273+ log .Println ("E! failed to grab column info for pg_stat_bgwriter:" , err )
274+ return
275+ }
292276
293- if columns , err = checkpointerRow .Columns (); err != nil {
294- log .Println ("E! failed to grab column info for pg_stat_checkpointer:" , err )
295- return
296- }
277+ for bgWriterRow .Next () {
278+ err = ins .accRow (bgWriterRow , slist , "" , columns , columns , nil )
279+ if err != nil {
280+ log .Println ("E! failed to get row data from pg_stat_bgwriter:" , err )
281+ return
282+ }
283+ }
284+ if err := bgWriterRow .Err (); err != nil {
285+ log .Println ("E! failed to iterate pg_stat_bgwriter rows:" , err )
286+ }
297287
298- for checkpointerRow .Next () {
299- err = ins .accRow (checkpointerRow , slist , "" , columns , columns , nil )
288+ // 2. Query pg_stat_checkpointer (moved columns, aliased to old names for compatibility)
289+ // num_timed -> checkpoints_timed
290+ // num_requested -> checkpoints_req
291+ // write_time -> checkpoint_write_time
292+ // sync_time -> checkpoint_sync_time
293+ // buffers_written -> buffers_checkpoint
294+ query = `SELECT
295+ num_timed AS checkpoints_timed,
296+ num_requested AS checkpoints_req,
297+ write_time AS checkpoint_write_time,
298+ sync_time AS checkpoint_sync_time,
299+ buffers_written AS buffers_checkpoint,
300+ restartpoints_timed,
301+ restartpoints_req,
302+ restartpoints_done
303+ FROM pg_stat_checkpointer`
304+
305+ checkpointerRow , err := ins .db .Query (query )
300306 if err != nil {
301- log .Println ("E! failed to get row data from pg_stat_checkpointer:" , err )
307+ log .Println ("E! failed to execute Query pg_stat_checkpointer:" , err )
302308 return
303309 }
310+ defer checkpointerRow .Close ()
311+
312+ if columns , err = checkpointerRow .Columns (); err != nil {
313+ log .Println ("E! failed to grab column info for pg_stat_checkpointer:" , err )
314+ return
315+ }
316+
317+ for checkpointerRow .Next () {
318+ err = ins .accRow (checkpointerRow , slist , "" , columns , columns , nil )
319+ if err != nil {
320+ log .Println ("E! failed to get row data from pg_stat_checkpointer:" , err )
321+ return
322+ }
323+ }
324+ if err := checkpointerRow .Err (); err != nil {
325+ log .Println ("E! failed to iterate pg_stat_checkpointer rows:" , err )
326+ }
304327 }
305328 }
306329
@@ -396,6 +419,9 @@ func (ins *Instance) getStatementMetrics(slist *types.SampleList, version int) {
396419 return
397420 }
398421 }
422+ if err := statements .Err (); err != nil {
423+ log .Println ("E! failed to iterate pg_stat_statements rows:" , err )
424+ }
399425}
400426
401427func (ins * Instance ) scrapeMetric (waitMetrics * sync.WaitGroup , slist * types.SampleList , metricConf MetricConfig , tags map [string ]string ) {
@@ -458,6 +484,9 @@ func (ins *Instance) scrapeMetric(waitMetrics *sync.WaitGroup, slist *types.Samp
458484 log .Println ("E! no metrics found while parsing" )
459485 }
460486 }
487+ if err := rows .Err (); err != nil {
488+ log .Println ("E! failed to iterate custom query rows:" , err )
489+ }
461490}
462491
463492func (ins * Instance ) parseRow (row map [string ]string , metricConf MetricConfig , slist * types.SampleList , tags map [string ]string ) error {
@@ -523,10 +552,10 @@ func (ins *Instance) accRow(row scanner, slist *types.SampleList, prefix string,
523552
524553 // deconstruct array of variables and send to Scan
525554 err := row .Scan (columnVars ... )
526-
527555 if err != nil {
528556 return err
529557 }
558+
530559 if columnMap ["datname" ] != nil {
531560 // extract the database name from the column map
532561 if dbNameStr , ok := (* columnMap ["datname" ]).(string ); ok {
@@ -658,4 +687,4 @@ func (ins *Instance) SanitizedAddress() (sanitizedAddress string, err error) {
658687 }
659688
660689 return sanitizedAddress , err
661- }
690+ }
0 commit comments