From 9d580c30cf752eac8fa12b0332addb5f3c2f504a Mon Sep 17 00:00:00 2001 From: Dan Fuhry Date: Fri, 21 Mar 2025 23:07:41 -0400 Subject: [PATCH] add prometheus_http_discovery program --- .gitignore | 1 + metrics/prometheus_http_discovery/Makefile | 14 +++ metrics/prometheus_http_discovery/main.go | 115 ++++++++++++++++++ .../systemd/prometheus-http-discovery.service | 10 ++ 4 files changed, 140 insertions(+) create mode 100644 metrics/prometheus_http_discovery/Makefile create mode 100644 metrics/prometheus_http_discovery/main.go create mode 100644 metrics/prometheus_http_discovery/systemd/prometheus-http-discovery.service diff --git a/.gitignore b/.gitignore index de7cd73..50a6a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ http/samlproxy/samlproxy automation/bryston_ctl/cli/cli automation/bryston_ctl/client/client automation/bryston_ctl/server/server +metrics/prometheus_http_discovery/prometheus_http_discovery /vendor/ diff --git a/metrics/prometheus_http_discovery/Makefile b/metrics/prometheus_http_discovery/Makefile new file mode 100644 index 0000000..bfab546 --- /dev/null +++ b/metrics/prometheus_http_discovery/Makefile @@ -0,0 +1,14 @@ +GOSRC = $(wildcard *.go) +GOEXE = $(shell basename `pwd`) +GOBUILDFLAGS := -buildmode=pie -trimpath + +all: $(GOEXE) + +clean: + rm -fv $(GOEXE) + +.PHONY: all clean + +$(GOEXE): %: $(GOSRC) + go build $(GOBUILDFLAGS) -o $@ $< + diff --git a/metrics/prometheus_http_discovery/main.go b/metrics/prometheus_http_discovery/main.go new file mode 100644 index 0000000..7e6462a --- /dev/null +++ b/metrics/prometheus_http_discovery/main.go @@ -0,0 +1,115 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "net/http" + "os/signal" + "sync" + "syscall" + "time" + + "github.com/coreos/go-systemd/daemon" + + "go.fuhry.dev/runtime/constants" + "go.fuhry.dev/runtime/mtls" + "go.fuhry.dev/runtime/sd" + "go.fuhry.dev/runtime/utils/log" +) + +type endpoint struct { + Targets []string `json:"targets"` + Labels map[string]string `json:"labels"` +} + +func main() { + mtls.SetDefaultIdentity("node-exporter") + ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + serverCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + + port := flag.Uint("port", 9102, "port to listen on") + + flag.Parse() + + id := mtls.DefaultIdentity() + tlsConfig, err := id.TlsConfig(serverCtx) + if err != nil { + log.Panic(err) + } + pv := mtls.NewPeerNameVerifier() + pv.AllowFrom(mtls.Service, "prometheus") + pv.AllowFrom(mtls.Service, "healthcheck") + err = pv.ConfigureServer(tlsConfig) + if err != nil { + log.Panic(err) + } + + mux := http.NewServeMux() + loggingMiddleware := log.NewLoggingMiddleware(mux) + sdWatchers := make(map[string]*sd.SDWatcher, 0) + sdLock := sync.Mutex{} + mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(fmt.Sprintf("

%s Prometheus HTTP discovery servicer

", constants.OrgName))) + }) + mux.HandleFunc("/endpoints/{service}", func(w http.ResponseWriter, r *http.Request) { + service := r.PathValue("service") + sdLock.Lock() + if _, ok := sdWatchers[service]; !ok { + sdWatchers[service] = &sd.SDWatcher{ + Service: service, + Protocol: sd.ProtocolTCP, + } + } + watcher := sdWatchers[service] + sdLock.Unlock() + + endpoints, err := watcher.GetAddrs(serverCtx) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + targets := make([]*endpoint, 0) + for _, ep := range endpoints { + targets = append(targets, &endpoint{ + Targets: []string{ + fmt.Sprintf("%s:%d", ep.Hostname, ep.Port), + }, + Labels: map[string]string{ + "shard": ep.Shard, + "host": ep.Hostname, + }, + }) + } + + out, err := json.MarshalIndent(targets, "", " ") + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + w.Header().Set("content-type", "application/json") + + w.Write(out) + }) + server := &http.Server{ + Addr: fmt.Sprintf("[::1]:%d", *port), + TLSConfig: tlsConfig, + Handler: loggingMiddleware.HandlerFunc(), + } + + go server.ListenAndServeTLS("", "") + + daemon.SdNotify(false, daemon.SdNotifyReady) + + <-ctx.Done() + cancel() + + shutdownCtx, _ := context.WithTimeout(context.Background(), 5*time.Second) + server.Shutdown(shutdownCtx) +} diff --git a/metrics/prometheus_http_discovery/systemd/prometheus-http-discovery.service b/metrics/prometheus_http_discovery/systemd/prometheus-http-discovery.service new file mode 100644 index 0000000..9b63216 --- /dev/null +++ b/metrics/prometheus_http_discovery/systemd/prometheus-http-discovery.service @@ -0,0 +1,10 @@ +[Unit] +Description=Prometheus HTTP endpoint discoverer monitors service discovery entries and returns Prometheus http_sd_config JSON + +[Service] +Type=notify +User=nobody +ExecStart=/usr/bin/prometheus-http-discovery + +[Install] +WantedBy=default.target -- 2.50.1