smokeping_prober icon indicating copy to clipboard operation
smokeping_prober copied to clipboard

[Feature Request] Reload configuration dynamically with signal HUP

Open carlosrodfern opened this issue 2 years ago • 4 comments

It would be nice to implement configuration reload with HUP. An example code is https://github.com/prometheus/blackbox_exporter/blob/c908cba63b5256af83d0553e7fb5049f709aaeac/main.go#L130

I'm planning to bring an PR for it.

carlosrodfern avatar Sep 12 '23 04:09 carlosrodfern

Looking into it and it seems that it will be a significant refactor for little gain since the workaround is just restarting the process. I'll close this issue.

carlosrodfern avatar Oct 21 '23 00:10 carlosrodfern

It would be nice to have some day.

SuperQ avatar Oct 21 '23 04:10 SuperQ

@SuperQ , I was just going the route of getting there programmatically by refreshing the actual variables. It will definitely require a good amount of shuffling around to keep the state.

However, I have another solution that it is simpler, but the program logs would appear as if it were rebooting, and it would reset any existing state (e.g., histograms). It is using execve(2). Basically, reexec the program.

The code change would look like this:

diff --git a/main.go b/main.go
index 9357297..cbbcbcd 100644
--- a/main.go
+++ b/main.go
@@ -20,11 +20,13 @@ import (
 	"net/http"
 	_ "net/http/pprof"
 	"os"
+	"os/signal"
 	"strconv"
 	"strings"
+	"syscall"
 	"time"
 
-	"github.com/prometheus-community/pro-bing"
+	probing "github.com/prometheus-community/pro-bing"
 	"github.com/superq/smokeping_prober/config"
 
 	"github.com/alecthomas/kingpin/v2"
@@ -228,6 +230,18 @@ func main() {
 		http.Handle("/", landingPage)
 	}
 
+	hup := make(chan os.Signal, 1)
+	signal.Notify(hup, syscall.SIGHUP)
+	go func() {
+		for {
+			<-hup
+			level.Info(logger).Log("msg", "Reexecuting and reloading the configuration")
+			if err := syscall.Exec("/proc/self/exe", os.Args, os.Environ()); err != nil {
+				level.Error(logger).Log("msg", "Error reloading config", "err", err)
+			}
+		}
+	}()
+
 	server := &http.Server{}
 	if err := web.ListenAndServe(server, webConfig, logger); err != nil {
 		level.Error(logger).Log("err", err)

That change just works. If you like this idea, I can submit a PR with these changes.

carlosrodfern avatar Oct 31 '23 04:10 carlosrodfern

My plan was to not keep any state between reloads. Just stop all pingers, clear the metrics registry, and start new pingers. This makes more sense from a intention of reload signal.

SuperQ avatar Oct 31 '23 09:10 SuperQ