mirror of
https://github.com/TronoSfera/backupy-agent.git
synced 2026-05-18 10:03:30 +03:00
Source ports from the TronoSfera/backupy-cloud monorepo:
- apps/agent/ — Go agent (WSS client, persistent queue, Docker
discovery, 5 DB drivers: PG/MySQL/Mongo/Redis/SQLite,
pre/post hooks, Prometheus metrics)
- apps/backupy-decrypt/ — standalone CLI for client-side decryption
- packages/proto/ — protobuf wire format (generated .pb.go committed
so the repo builds without protoc)
- docs/ — agent spec + wire-protocol contract
Apache-2.0 license. Image published to ghcr.io/tronosfera/backupy-agent
on every v* tag via .github/workflows/release.yml (multi-arch amd64+arm64).
66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package metrics
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
)
|
|
|
|
// DefaultAddr is the loopback-only default address the operator should
|
|
// stick with unless they have a specific reason to override it.
|
|
const DefaultAddr = "127.0.0.1:9090"
|
|
|
|
// ListenAndServe binds `addr` and serves `/metrics` over plain HTTP
|
|
// using the default Prometheus gatherer. The HTTP server is shut down
|
|
// gracefully when `ctx` is cancelled.
|
|
//
|
|
// `addr` MUST resolve to a loopback interface in production. The
|
|
// function does not enforce this — operators may need to expose
|
|
// metrics over a private network behind a reverse proxy — but the
|
|
// package documentation calls out the policy and the default in
|
|
// DefaultAddr is loopback.
|
|
func ListenAndServe(ctx context.Context, addr string) error {
|
|
if addr == "" {
|
|
addr = DefaultAddr
|
|
}
|
|
mux := http.NewServeMux()
|
|
mux.Handle("/metrics", promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{}))
|
|
|
|
srv := &http.Server{
|
|
Addr: addr,
|
|
Handler: mux,
|
|
ReadHeaderTimeout: 5 * time.Second,
|
|
}
|
|
|
|
ln, err := net.Listen("tcp", addr)
|
|
if err != nil {
|
|
return fmt.Errorf("metrics: listen on %s: %w", addr, err)
|
|
}
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
serveErr := srv.Serve(ln)
|
|
if serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) {
|
|
errCh <- serveErr
|
|
return
|
|
}
|
|
errCh <- nil
|
|
}()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
shutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
_ = srv.Shutdown(shutCtx)
|
|
<-errCh
|
|
return nil
|
|
case err := <-errCh:
|
|
return err
|
|
}
|
|
}
|