...

Source file src/github.com/cybertec-postgresql/pgwatch/v3/internal/reaper/file.go

Documentation: github.com/cybertec-postgresql/pgwatch/v3/internal/reaper

     1  package reaper
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  
     7  	"slices"
     8  
     9  	"github.com/cybertec-postgresql/pgwatch/v3/internal/metrics"
    10  	"github.com/cybertec-postgresql/pgwatch/v3/internal/sources"
    11  )
    12  
    13  func DoesEmergencyTriggerfileExist(fname string) bool {
    14  	// Main idea of the feature is to be able to quickly free monitored DBs / network of any extra "monitoring effect" load.
    15  	// In highly automated K8s / IaC environments such a temporary change might involve pull requests, peer reviews, CI/CD etc
    16  	// which can all take too long vs "exec -it pgwatch-pod -- touch /tmp/pgwatch-emergency-pause".
    17  	// After creating the file it can still take up to --servers-refresh-loop-seconds (2min def.) for change to take effect!
    18  	if fname == "" {
    19  		return false
    20  	}
    21  	_, err := os.Stat(fname)
    22  	return err == nil
    23  }
    24  
    25  const (
    26  	metricCPULoad           = "cpu_load"
    27  	metricPsutilCPU         = "psutil_cpu"
    28  	metricPsutilDisk        = "psutil_disk"
    29  	metricPsutilDiskIoTotal = "psutil_disk_io_total"
    30  	metricPsutilMem         = "psutil_mem"
    31  )
    32  
    33  const (
    34  	sqlPgDirs = `select current_setting('data_directory') as dd, current_setting('log_directory') as ld`
    35  	sqlTsDirs = `select spcname::text as name, pg_catalog.pg_tablespace_location(oid) as location from pg_catalog.pg_tablespace where not spcname like any(array[E'pg\\_%'])`
    36  )
    37  
    38  var directlyFetchableOSMetrics = []string{metricPsutilCPU, metricPsutilDisk, metricPsutilDiskIoTotal, metricPsutilMem, metricCPULoad}
    39  
    40  func IsDirectlyFetchableMetric(metric string) bool {
    41  	return slices.Contains(directlyFetchableOSMetrics, metric)
    42  }
    43  
    44  func (r *Reaper) FetchStatsDirectlyFromOS(ctx context.Context, md *sources.SourceConn, metricName string) (*metrics.MeasurementEnvelope, error) {
    45  	var data, dataDirs, dataTblspDirs metrics.Measurements
    46  	var err error
    47  
    48  	switch metricName {
    49  	case metricCPULoad:
    50  		data, err = GetLoadAvgLocal()
    51  	case metricPsutilCPU:
    52  		data, err = GetGoPsutilCPU(md.GetMetricInterval(metricName))
    53  	case metricPsutilDisk:
    54  		if dataDirs, err = QueryMeasurements(ctx, md.Name, sqlPgDirs); err != nil {
    55  			return nil, err
    56  		}
    57  		if dataTblspDirs, err = QueryMeasurements(ctx, md.Name, sqlTsDirs); err != nil {
    58  			return nil, err
    59  		}
    60  		data, err = GetGoPsutilDiskPG(dataDirs, dataTblspDirs)
    61  	case metricPsutilDiskIoTotal:
    62  		data, err = GetGoPsutilDiskTotals()
    63  	case metricPsutilMem:
    64  		data, err = GetGoPsutilMem()
    65  	}
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	m, _ := metricDefs.GetMetricDef(metricName)
    70  	return &metrics.MeasurementEnvelope{
    71  		DBName:           md.Name,
    72  		SourceType:       string(md.Kind),
    73  		MetricName:       metricName,
    74  		CustomTags:       md.CustomTags,
    75  		Data:             data,
    76  		MetricDef:        m,
    77  		RealDbname:       md.RealDbname,
    78  		SystemIdentifier: md.SystemIdentifier,
    79  	}, nil
    80  }
    81