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  }