...
1 package sources
2
3 import (
4 "fmt"
5 "maps"
6 "reflect"
7 "slices"
8
9 "github.com/jackc/pgx/v5"
10 )
11
12 type Kind string
13
14 const (
15 SourcePostgres Kind = "postgres"
16 SourcePostgresContinuous Kind = "postgres-continuous-discovery"
17 SourcePgBouncer Kind = "pgbouncer"
18 SourcePgPool Kind = "pgpool"
19 SourcePatroni Kind = "patroni"
20 SourcePatroniContinuous Kind = "patroni-continuous-discovery"
21 SourcePatroniNamespace Kind = "patroni-namespace-discovery"
22 )
23
24 var Kinds = []Kind{
25 SourcePostgres,
26 SourcePostgresContinuous,
27 SourcePgBouncer,
28 SourcePgPool,
29 SourcePatroni,
30 SourcePatroniContinuous,
31 SourcePatroniNamespace,
32 }
33
34 func (k Kind) IsValid() bool {
35 return slices.Contains(Kinds, k)
36 }
37
38 type (
39
40
41
42
43
44
45 Source struct {
46 Name string `yaml:"name" db:"name"`
47 Group string `yaml:"group" db:"group"`
48 ConnStr string `yaml:"conn_str" db:"connstr"`
49 Metrics map[string]float64 `yaml:"custom_metrics" db:"config"`
50 MetricsStandby map[string]float64 `yaml:"custom_metrics_standby" db:"config_standby"`
51 Kind Kind `yaml:"kind" db:"dbtype"`
52 IncludePattern string `yaml:"include_pattern" db:"include_pattern"`
53 ExcludePattern string `yaml:"exclude_pattern" db:"exclude_pattern"`
54 PresetMetrics string `yaml:"preset_metrics" db:"preset_config"`
55 PresetMetricsStandby string `yaml:"preset_metrics_standby" db:"preset_config_standby"`
56 IsEnabled bool `yaml:"is_enabled" db:"is_enabled"`
57 CustomTags map[string]string `yaml:"custom_tags" db:"custom_tags"`
58 HostConfig HostConfigAttrs `yaml:"host_config" db:"host_config"`
59 OnlyIfMaster bool `yaml:"only_if_master" db:"only_if_master"`
60 }
61
62 Sources []Source
63 )
64
65 func (s Source) IsDefaultGroup() bool {
66 return s.Group == "" || s.Group == "default"
67 }
68
69 func (srcs Sources) Validate() (Sources, error) {
70 names := map[string]any{}
71 for _, src := range srcs {
72 if _, ok := names[src.Name]; ok {
73 return nil, fmt.Errorf("duplicate source with name '%s' found", src.Name)
74 }
75 names[src.Name] = nil
76 if src.Kind == "" {
77 src.Kind = SourcePostgres
78 }
79 }
80 return srcs, nil
81 }
82
83 func (s *Source) GetDatabaseName() string {
84 if с, err := pgx.ParseConfig(s.ConnStr); err == nil {
85 return с.Database
86 }
87 return ""
88 }
89
90 func (s Source) Equal(s2 Source) bool {
91 return s.Name == s2.Name &&
92 s.Group == s2.Group &&
93 s.ConnStr == s2.ConnStr &&
94 s.Kind == s2.Kind &&
95 s.IsEnabled == s2.IsEnabled &&
96 s.IncludePattern == s2.IncludePattern &&
97 s.ExcludePattern == s2.ExcludePattern &&
98 (s.PresetMetrics == s2.PresetMetrics || reflect.DeepEqual(s.Metrics, s2.Metrics)) &&
99 (s.PresetMetricsStandby == s2.PresetMetricsStandby || reflect.DeepEqual(s.MetricsStandby, s2.MetricsStandby)) &&
100 s.OnlyIfMaster == s2.OnlyIfMaster &&
101 reflect.DeepEqual(s.CustomTags, s2.CustomTags) &&
102 reflect.DeepEqual(s.HostConfig, s2.HostConfig)
103 }
104
105 func (s *Source) Clone() *Source {
106 c := new(Source)
107 *c = *s
108 c.Metrics = maps.Clone(s.Metrics)
109 c.MetricsStandby = maps.Clone(s.MetricsStandby)
110 c.CustomTags = maps.Clone(s.CustomTags)
111 return c
112 }
113
114 type HostConfigAttrs struct {
115 DcsType string `yaml:"dcs_type"`
116 DcsEndpoints []string `yaml:"dcs_endpoints"`
117 Scope string
118 Namespace string
119 Username string
120 Password string
121 CAFile string `yaml:"ca_file"`
122 CertFile string `yaml:"cert_file"`
123 KeyFile string `yaml:"key_file"`
124 LogsGlobPath string `yaml:"logs_glob_path"`
125 LogsMatchRegex string `yaml:"logs_match_regex"`
126 PerMetricDisabledTimes []HostConfigPerMetricDisabledTimes `yaml:"per_metric_disabled_intervals"`
127 }
128
129 type HostConfigPerMetricDisabledTimes struct {
130 Metrics []string `yaml:"metrics"`
131 DisabledTimes []string `yaml:"disabled_times"`
132 DisabledDays string `yaml:"disabled_days"`
133 }
134
135 type Reader interface {
136 GetSources() (Sources, error)
137 }
138
139 type Writer interface {
140 WriteSources(Sources) error
141 DeleteSource(string) error
142 UpdateSource(md Source) error
143 }
144
145 type ReaderWriter interface {
146 Reader
147 Writer
148 }
149