...
1 package reaper
2
3 import (
4 "context"
5 "os"
6
7 "slices"
8
9 "github.com/cybertec-postgresql/pgwatch/v5/internal/metrics"
10 "github.com/cybertec-postgresql/pgwatch/v5/internal/sources"
11 )
12
13 func DoesEmergencyTriggerfileExist(fname string) bool {
14
15
16
17
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 sqlPgDirs = `select name, path from
34 (values
35 ('data_directory', current_setting('data_directory')),
36 ('pg_wal', current_setting('data_directory')||'/pg_wal'),
37 ('log_directory', case
38 when current_setting('log_directory') ~ '^(\w:)?\/.+' then current_setting('log_directory')
39 else current_setting('data_directory') || '/' || current_setting('log_directory')
40 end)) as d(name, path)
41 union all
42 select spcname::text, pg_catalog.pg_tablespace_location(oid)
43 from pg_catalog.pg_tablespace where spcname !~ 'pg_.+'`
44
45 var directlyFetchableOSMetrics = []string{metricPsutilCPU, metricPsutilDisk, metricPsutilDiskIoTotal, metricPsutilMem, metricCPULoad}
46
47 func IsDirectlyFetchableMetric(md *sources.SourceConn, metric string) bool {
48 return slices.Contains(directlyFetchableOSMetrics, metric) && md.IsClientOnSameHost()
49 }
50
51 func (r *Reaper) FetchStatsDirectlyFromOS(ctx context.Context, md *sources.SourceConn, metricName string) (*metrics.MeasurementEnvelope, error) {
52 var data, pgDirs metrics.Measurements
53 var err error
54
55 switch metricName {
56 case metricCPULoad:
57 data, err = GetLoadAvgLocal()
58 case metricPsutilCPU:
59 data, err = GetGoPsutilCPU(md.GetMetricInterval(metricName))
60 case metricPsutilDisk:
61 if pgDirs, err = QueryMeasurements(ctx, md, sqlPgDirs); err != nil {
62 return nil, err
63 }
64 data, err = GetGoPsutilDiskPG(pgDirs)
65 case metricPsutilDiskIoTotal:
66 data, err = GetGoPsutilDiskTotals()
67 case metricPsutilMem:
68 data, err = GetGoPsutilMem()
69 }
70 if err != nil {
71 return nil, err
72 }
73 return &metrics.MeasurementEnvelope{
74 DBName: md.Name,
75 MetricName: metricName,
76 CustomTags: md.CustomTags,
77 Data: data,
78 }, nil
79 }
80