diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..36272d1 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,24 @@ +name: build + +on: + push: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Build and Push Docker Image + uses: docker/build-push-action@v4 + with: + push: true + tags: | + ghcr.io/PEERINGTestbed/peeringmon_exporter:${{ github.sha }} + ghcr.io/PEERINGTestbed/peeringmon_exporter:latest diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fbf66d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.22 + +WORKDIR /app + +COPY . . + +RUN go mod tidy +RUN go build -o /peeringmon_exporter + +EXPOSE 2112 + +CMD [ "/peeringmon_exporter" ] diff --git a/main.go b/main.go index 12674dd..bb05627 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,18 @@ package main import ( + "context" "encoding/json" + "errors" + "flag" "io/ioutil" "net/http" "os" + "os/signal" + "strconv" "strings" "sync" + "syscall" "time" "github.com/rs/zerolog" @@ -17,11 +23,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" ) -const ( - appID = "PEERINGMON-DEV" - port = ":2112" -) - var prefixes = []string{ // PEERING v6 "2804:269c:fe41::/48", @@ -76,6 +77,9 @@ var prefixes = []string{ var prefixStates = []*PrefixState{} +var port int +var appId string + var ( prefixStateGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "prefix_visibility", @@ -91,7 +95,7 @@ type PrefixState struct { func (p *PrefixState) checkState() { log.Trace().Str("Prefix", p.Prefix).Msg("checking prefix state") - url := "https://stat.ripe.net/data/visibility/data.json?data_overload_limit=ignore&include=peers_seeing&resource=" + p.Prefix + "&sourceapp=" + appID + url := "https://stat.ripe.net/data/visibility/data.json?data_overload_limit=ignore&include=peers_seeing&resource=" + p.Prefix + "&sourceapp=" + appId resp, err := http.Get(url) if err != nil { log.Error().Err(err).Msg("Fetching ripestat") @@ -129,15 +133,26 @@ func (p *PrefixState) checkState() { func updateStates() { log.Debug().Msg("Updating Prefixes") for _, ps := range prefixStates { - ps.checkState() + go ps.checkState() } } -func main() { +func init() { zerolog.TimeFieldFormat = zerolog.TimeFormatUnix log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout}) zerolog.SetGlobalLevel(zerolog.DebugLevel) - log.Info().Msg("Starting PEERINGMON Exporter") + + flag.StringVar(&appId, "appid", "exporter", "provide a unique identifier to every data call") + flag.IntVar(&port, "port", 2112, "port") +} + +func main() { + flag.Parse() + + log.Info(). + Str("appID", appId). + Str("Data Source", "RIPE RIS via RIPEstat API"). + Msg("Starting PEERINGMON Exporter") for _, prefix := range prefixes { prefixStates = append(prefixStates, &PrefixState{ @@ -157,9 +172,29 @@ func main() { } }() - log.Info().Msg("Starting exporter on port " + port) http.Handle("/metrics", promhttp.Handler()) - if err := http.ListenAndServe(port, nil); err != nil { - log.Error().Err(err).Msg("Failed on http listening") + + done := make(chan os.Signal, 1) + signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + + srv := &http.Server{ + Addr: ":" + strconv.Itoa(port), + } + + go func() { + if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + log.Fatal().Err(err).Msg("Failed to start HTTP server") + } + }() + log.Info().Int("port", port).Msg("Started exporter") + + <-done + log.Info().Msg("Stopping") + shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), 10*time.Second) + defer shutdownRelease() + + if err := srv.Shutdown(shutdownCtx); err != nil { + log.Fatal().Err(err).Msg("Failed to gracefully stop server") } + log.Info().Msg("Graceful Shutdown Successful, bye") } diff --git a/peeringmon_exporter b/peeringmon_exporter new file mode 100755 index 0000000..46b4218 Binary files /dev/null and b/peeringmon_exporter differ