@@ -11,8 +11,8 @@ import (
1111
1212// Config holds all configuration for the application
1313type Config struct {
14- // Alertmanager configuration
15- Alertmanager AlertmanagerConfig `json:"alertmanager "`
14+ // Alertmanager configurations, supports multiple instances
15+ Alertmanagers [] AlertmanagerConfig `json:"alertmanagers "`
1616
1717 // GUI configuration
1818 GUI GUIConfig `json:"gui"`
@@ -24,11 +24,40 @@ type Config struct {
2424 Polling PollingConfig `json:"polling"`
2525
2626 // Column configuration for GUI
27- ColumnWidths map [string ]float32 `json:"column_widths"`
27+ ColumnWidths map [string ]float32 `json:"column_widths"`
28+ Backend BackendConfig `json:"backend"`
29+ ResolvedAlerts ResolvedAlertsConfig `json:"resolved_alerts"`
30+ }
31+
32+ type BackendConfig struct {
33+ Enabled bool `json:"enabled"`
34+ GRPCListen string `json:"grpc_listen"` // Port for gRPC server (e.g., ":50051")
35+ GRPCClient string `json:"grpc_client"` // Address for gRPC client (e.g., "localhost:50051")
36+ HTTPListen string `json:"http_listen"` // Port for HTTP server (e.g., ":8080")
37+ Database DatabaseConfig `json:"database"`
38+ }
39+
40+ type DatabaseConfig struct {
41+ Type string `json:"type"` // "sqlite" or "postgres"
42+ Host string `json:"host"`
43+ Port int `json:"port"`
44+ Name string `json:"name"`
45+ User string `json:"user"`
46+ Password string `json:"password"`
47+ SSLMode string `json:"ssl_mode"`
48+ SQLitePath string `json:"sqlite_path"`
49+ }
50+
51+ // ResolvedAlertsConfig contains resolved alerts settings
52+ type ResolvedAlertsConfig struct {
53+ Enabled bool `json:"enabled"` // Enable resolved alerts tracking
54+ NotificationsEnabled bool `json:"notifications_enabled"` // Send notifications for resolved alerts
55+ RetentionDuration time.Duration `json:"retention_duration"` // How long to keep resolved alerts
2856}
2957
3058// AlertmanagerConfig contains Alertmanager-specific settings
3159type AlertmanagerConfig struct {
60+ Name string `json:"name"`
3261 URL string `json:"url"`
3362 Username string `json:"username"`
3463 Password string `json:"password"`
@@ -57,10 +86,13 @@ type GUIConfig struct {
5786
5887// FilterStateConfig contains the state of filters
5988type FilterStateConfig struct {
60- SearchText string `json:"search_text"`
61- SelectedSeverities map [string ]bool `json:"selected_severities"`
62- SelectedStatuses map [string ]bool `json:"selected_statuses"`
63- SelectedTeams map [string ]bool `json:"selected_teams"`
89+ SearchText string `json:"search_text"`
90+ SelectedAlertmanagers map [string ]bool `json:"selected_alertmanagers"`
91+ SelectedSeverities map [string ]bool `json:"selected_severities"`
92+ SelectedStatuses map [string ]bool `json:"selected_statuses"`
93+ SelectedTeams map [string ]bool `json:"selected_teams"`
94+ SelectedAcks map [string ]bool `json:"selected_acks"`
95+ SelectedComments map [string ]bool `json:"selected_comments"`
6496}
6597
6698// NotificationConfig contains notification settings
@@ -91,10 +123,13 @@ func DefaultConfig() *Config {
91123 }
92124
93125 return & Config {
94- Alertmanager : AlertmanagerConfig {
95- URL : "http://localhost:9093" ,
96- Headers : headers ,
97- OAuth : oauthConfig ,
126+ Alertmanagers : []AlertmanagerConfig {
127+ {
128+ Name : "Default" ,
129+ URL : "http://localhost:9093" ,
130+ Headers : headers ,
131+ OAuth : oauthConfig ,
132+ },
98133 },
99134 GUI : GUIConfig {
100135 Width : 1920 ,
@@ -105,10 +140,13 @@ func DefaultConfig() *Config {
105140 ShowTrayIcon : true ,
106141 BackgroundMode : false ,
107142 FilterState : FilterStateConfig {
108- SearchText : "" ,
109- SelectedSeverities : map [string ]bool {"All" : true },
110- SelectedStatuses : map [string ]bool {"All" : true },
111- SelectedTeams : map [string ]bool {"All" : true },
143+ SearchText : "" ,
144+ SelectedAlertmanagers : map [string ]bool {"All" : true },
145+ SelectedSeverities : map [string ]bool {"All" : true },
146+ SelectedStatuses : map [string ]bool {"All" : true },
147+ SelectedTeams : map [string ]bool {"All" : true },
148+ SelectedAcks : map [string ]bool {"All" : true },
149+ SelectedComments : map [string ]bool {"All" : true },
112150 },
113151 },
114152 Notifications : NotificationConfig {
@@ -131,6 +169,27 @@ func DefaultConfig() *Config {
131169 Polling : PollingConfig {
132170 Interval : 30 * time .Second ,
133171 },
172+ Backend : BackendConfig {
173+ Enabled : false ,
174+ GRPCListen : ":50051" ,
175+ GRPCClient : "localhost:50051" ,
176+ HTTPListen : ":8080" ,
177+ Database : DatabaseConfig {
178+ Type : "sqlite" ,
179+ SQLitePath : "./notificator.db" ,
180+ Host : "localhost" ,
181+ Port : 5432 ,
182+ Name : "notificator" ,
183+ User : "notificator" ,
184+ Password : "" ,
185+ SSLMode : "disable" ,
186+ },
187+ },
188+ ResolvedAlerts : ResolvedAlertsConfig {
189+ Enabled : true , // Enable by default
190+ NotificationsEnabled : true , // Send notifications by default
191+ RetentionDuration : 1 * time .Hour , // Keep for 1 hour by default
192+ },
134193 }
135194}
136195
@@ -179,6 +238,12 @@ func LoadConfig(configPath string) (*Config, error) {
179238 if config .GUI .FilterState .SelectedTeams == nil {
180239 config .GUI .FilterState .SelectedTeams = map [string ]bool {"All" : true }
181240 }
241+ if config .GUI .FilterState .SelectedAcks == nil {
242+ config .GUI .FilterState .SelectedAcks = map [string ]bool {"All" : true }
243+ }
244+ if config .GUI .FilterState .SelectedComments == nil {
245+ config .GUI .FilterState .SelectedComments = map [string ]bool {"All" : true }
246+ }
182247
183248 return & config , nil
184249}
@@ -242,11 +307,93 @@ func ParseHeadersFromEnv(envVar string) map[string]string {
242307func (c * Config ) MergeHeaders () {
243308 envHeaders := ParseHeadersFromEnv ("METRICS_PROVIDER_HEADERS" )
244309
245- if c .Alertmanager .Headers == nil {
246- c .Alertmanager .Headers = make (map [string ]string )
310+ // Apply environment headers to all alertmanagers
311+ for i := range c .Alertmanagers {
312+ if c .Alertmanagers [i ].Headers == nil {
313+ c .Alertmanagers [i ].Headers = make (map [string ]string )
314+ }
315+
316+ for key , value := range envHeaders {
317+ c .Alertmanagers [i ].Headers [key ] = value
318+ }
247319 }
320+ }
248321
249- for key , value := range envHeaders {
250- c .Alertmanager .Headers [key ] = value
322+ // GetAlertmanagerByName returns an Alertmanager configuration by name
323+ func (c * Config ) GetAlertmanagerByName (name string ) * AlertmanagerConfig {
324+ for i := range c .Alertmanagers {
325+ if c .Alertmanagers [i ].Name == name {
326+ return & c .Alertmanagers [i ]
327+ }
251328 }
329+ return nil
330+ }
331+
332+ // GetAlertmanagerByURL returns an Alertmanager configuration by URL
333+ func (c * Config ) GetAlertmanagerByURL (url string ) * AlertmanagerConfig {
334+ for i := range c .Alertmanagers {
335+ if c .Alertmanagers [i ].URL == url {
336+ return & c .Alertmanagers [i ]
337+ }
338+ }
339+ return nil
340+ }
341+
342+ // AddAlertmanager adds a new Alertmanager configuration
343+ func (c * Config ) AddAlertmanager (config AlertmanagerConfig ) {
344+ // Ensure unique name
345+ if c .GetAlertmanagerByName (config .Name ) != nil {
346+ // Find a unique name
347+ baseName := config .Name
348+ counter := 1
349+ for c .GetAlertmanagerByName (config .Name ) != nil {
350+ config .Name = fmt .Sprintf ("%s_%d" , baseName , counter )
351+ counter ++
352+ }
353+ }
354+ c .Alertmanagers = append (c .Alertmanagers , config )
355+ }
356+
357+ // RemoveAlertmanager removes an Alertmanager configuration by name
358+ func (c * Config ) RemoveAlertmanager (name string ) bool {
359+ for i := range c .Alertmanagers {
360+ if c .Alertmanagers [i ].Name == name {
361+ c .Alertmanagers = append (c .Alertmanagers [:i ], c .Alertmanagers [i + 1 :]... )
362+ return true
363+ }
364+ }
365+ return false
366+ }
367+
368+ // GetAlertmanagerNames returns a list of all Alertmanager names
369+ func (c * Config ) GetAlertmanagerNames () []string {
370+ names := make ([]string , len (c .Alertmanagers ))
371+ for i , am := range c .Alertmanagers {
372+ names [i ] = am .Name
373+ }
374+ return names
375+ }
376+
377+ // ValidateAlertmanagers validates all Alertmanager configurations
378+ func (c * Config ) ValidateAlertmanagers () error {
379+ if len (c .Alertmanagers ) == 0 {
380+ return fmt .Errorf ("at least one Alertmanager must be configured" )
381+ }
382+
383+ names := make (map [string ]bool )
384+ urls := make (map [string ]bool )
385+
386+ for i , am := range c .Alertmanagers {
387+ if am .Name == "" {
388+ return fmt .Errorf ("alertmanager at index %d has no name" , i )
389+ }
390+ names [am .Name ] = true
391+
392+ if am .URL == "" {
393+ return fmt .Errorf ("alertmanager '%s' has no URL" , am .Name )
394+ }
395+ urls [am .URL ] = true
396+ }
397+
398+ return nil
252399}
0 commit comments