...

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

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

     1  package reaper
     2  
     3  import (
     4  	"maps"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/cybertec-postgresql/pgwatch/v3/internal/metrics"
     9  	"github.com/cybertec-postgresql/pgwatch/v3/internal/sinks"
    10  	"github.com/sirupsen/logrus"
    11  )
    12  
    13  const (
    14  	monitoredDbsDatastoreSyncIntervalSeconds = 600              // write actively monitored DBs listing to metrics store after so many seconds
    15  	monitoredDbsDatastoreSyncMetricName      = "configured_dbs" // FYI - for Postgres datastore there's also the admin.all_unique_dbnames table with all recent DB unique names with some metric data
    16  
    17  	dbSizeCachingInterval = 30 * time.Minute
    18  	dbMetricJoinStr       = "¤¤¤" // just some unlikely string for a DB name to avoid using maps of maps for DB+metric data
    19  
    20  )
    21  
    22  type ConcurrentMetricDefs struct {
    23  	*metrics.Metrics
    24  	sync.RWMutex
    25  }
    26  
    27  func NewConcurrentMetricDefs() *ConcurrentMetricDefs {
    28  	return &ConcurrentMetricDefs{
    29  		Metrics: &metrics.Metrics{
    30  			MetricDefs: make(metrics.MetricDefs),
    31  			PresetDefs: make(metrics.PresetDefs),
    32  		},
    33  	}
    34  }
    35  
    36  func (cmd *ConcurrentMetricDefs) GetMetricDef(name string) (m metrics.Metric, ok bool) {
    37  	cmd.RLock()
    38  	defer cmd.RUnlock()
    39  	m, ok = cmd.MetricDefs[name]
    40  	return
    41  }
    42  
    43  func (cmd *ConcurrentMetricDefs) GetPresetDef(name string) (m metrics.Preset, ok bool) {
    44  	cmd.RLock()
    45  	defer cmd.RUnlock()
    46  	m, ok = cmd.PresetDefs[name]
    47  	return
    48  }
    49  
    50  func (cmd *ConcurrentMetricDefs) GetPresetMetrics(name string) (m map[string]float64) {
    51  	cmd.RLock()
    52  	defer cmd.RUnlock()
    53  	return cmd.PresetDefs[name].Metrics
    54  }
    55  
    56  func (cmd *ConcurrentMetricDefs) Assign(newDefs *metrics.Metrics) {
    57  	cmd.Lock()
    58  	defer cmd.Unlock()
    59  	cmd.MetricDefs = maps.Clone(newDefs.MetricDefs)
    60  	cmd.PresetDefs = maps.Clone(newDefs.PresetDefs)
    61  }
    62  
    63  type ChangeDetectionResults struct { // for passing around DDL/index/config change detection results
    64  	Created int
    65  	Altered int
    66  	Dropped int
    67  }
    68  
    69  type ExistingPartitionInfo struct {
    70  	StartTime time.Time
    71  	EndTime   time.Time
    72  }
    73  
    74  // LoadMetrics loads metric definitions from the reader
    75  func (r *Reaper) LoadMetrics() (err error) {
    76  	var newDefs *metrics.Metrics
    77  	if newDefs, err = r.MetricsReaderWriter.GetMetrics(); err != nil {
    78  		return
    79  	}
    80  	metricDefs.Assign(newDefs)
    81  	if definer, ok := r.SinksWriter.(sinks.MetricsDefiner); ok {
    82  		err = definer.DefineMetrics(newDefs)
    83  	}
    84  	r.logger.
    85  		WithField("metrics", len(newDefs.MetricDefs)).
    86  		WithField("presets", len(newDefs.PresetDefs)).
    87  		Log(func() logrus.Level {
    88  			if len(newDefs.PresetDefs)*len(newDefs.MetricDefs) == 0 {
    89  				return logrus.WarnLevel
    90  			}
    91  			return logrus.InfoLevel
    92  		}(), "metrics and presets refreshed")
    93  	// update the monitored sources with real metric definitions from presets
    94  	for _, md := range r.monitoredSources {
    95  		if md.PresetMetrics > "" {
    96  			md.Metrics = metricDefs.GetPresetMetrics(md.PresetMetrics)
    97  		}
    98  		if md.PresetMetricsStandby > "" {
    99  			md.MetricsStandby = metricDefs.GetPresetMetrics(md.PresetMetricsStandby)
   100  		}
   101  	}
   102  	return
   103  }
   104