Skip to content

Commit a1a4d57

Browse files
committed
config auto reload flag
1 parent 7422e87 commit a1a4d57

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

main.go

+33
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func main() {
7373
flag.StringVar(&opts.LogFormat, "log-format", "console", "Define log format. Allowed values: console, json")
7474
flag.BoolVar(&opts.VerifyConfig, "verify-config", false, "Enable this flag to check config file loads, then exit")
7575
flag.BoolVar(&opts.Version, "version", false, "set to print version information")
76+
flag.BoolVar(&opts.EnableAutoReload, "enable-auto-reload", true, "Enable automatic config reload when the config file changes")
7677
flag.Parse()
7778

7879
if opts.Version {
@@ -126,6 +127,38 @@ func main() {
126127
os.Exit(1)
127128
}
128129

130+
var configWatcher *config.ConfigWatcher
131+
if opts.EnableAutoReload && opts.ConfigFile != "" {
132+
configWatcher, err = config.NewConfigWatcher(logger, opts.ConfigFile, func() {
133+
// Create a new config instance for reloading
134+
newCfg := config.Config{
135+
Listen: config.ListenConfig{
136+
Port: 4040,
137+
MetricsEndpoint: "/metrics",
138+
},
139+
}
140+
141+
if err := config.LoadConfigFromFile(logger, &newCfg, opts.ConfigFile); err != nil {
142+
logger.Errorf("error reloading config: %v", err)
143+
return
144+
}
145+
146+
if stabilityError := newCfg.StabilityWarnings(); stabilityError != nil && !opts.EnableExperimentalFeatures {
147+
logger.Errorf("reloaded config contains experimental features but they are not enabled")
148+
return
149+
}
150+
151+
// Update the current config
152+
cfg = newCfg
153+
logger.Info("configuration reloaded successfully")
154+
})
155+
if err != nil {
156+
logger.Errorf("error setting up config watcher: %v", err)
157+
} else {
158+
defer configWatcher.Close()
159+
}
160+
}
161+
129162
if cfg.Consul.Enable {
130163
setupConsul(logger, &cfg, stopChan, &stopHandlers)
131164
}

pkg/config/structs.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type StartupFlags struct {
1414
MetricsEndpoint string
1515
VerifyConfig bool
1616
Version bool
17+
EnableAutoReload bool
1718

1819
LogLevel string
1920
LogFormat string

pkg/config/watcher.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package config
2+
3+
import (
4+
"github.com/fsnotify/fsnotify"
5+
"github.com/martin-helmich/prometheus-nginxlog-exporter/log"
6+
)
7+
8+
// ConfigWatcher watches a configuration file for changes
9+
type ConfigWatcher struct {
10+
watcher *fsnotify.Watcher
11+
logger *log.Logger
12+
configFile string
13+
onChange func()
14+
}
15+
16+
// NewConfigWatcher creates a new configuration watcher
17+
func NewConfigWatcher(logger *log.Logger, configFile string, onChange func()) (*ConfigWatcher, error) {
18+
watcher, err := fsnotify.NewWatcher()
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
w := &ConfigWatcher{
24+
watcher: watcher,
25+
logger: logger,
26+
configFile: configFile,
27+
onChange: onChange,
28+
}
29+
30+
if err := watcher.Add(configFile); err != nil {
31+
watcher.Close()
32+
return nil, err
33+
}
34+
35+
go w.watch()
36+
37+
return w, nil
38+
}
39+
40+
// watch monitors the config file for changes
41+
func (w *ConfigWatcher) watch() {
42+
for {
43+
select {
44+
case event, ok := <-w.watcher.Events:
45+
if !ok {
46+
return
47+
}
48+
if event.Op&fsnotify.Write == fsnotify.Write {
49+
w.logger.Infof("config file changed, triggering reload")
50+
w.onChange()
51+
}
52+
case err, ok := <-w.watcher.Errors:
53+
if !ok {
54+
return
55+
}
56+
w.logger.Errorf("error watching config file: %v", err)
57+
}
58+
}
59+
}
60+
61+
// Close stops watching the configuration file
62+
func (w *ConfigWatcher) Close() error {
63+
return w.watcher.Close()
64+
}

0 commit comments

Comments
 (0)