diff --git a/.gitea/workflows/demo.yaml b/.gitea/workflows/demo.yaml index e420570..210f327 100644 --- a/.gitea/workflows/demo.yaml +++ b/.gitea/workflows/demo.yaml @@ -21,6 +21,11 @@ jobs: go-version: "1.25.4" cache: true + - name: Build and test application + run: | + go mod tidy + go build -o ./bin/metrics ./cmd + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..314bb41 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "context" + "log" + "net/http" + "os/signal" + "syscall" + "time" + + "github.com/VictoriaMetrics/metrics" +) + +// Register various metrics. +// Metric name may contain labels in Prometheus format - see below. +var ( + // Register counter without labels. + // requestsTotal = metrics.NewCounter("requests_total") + + requestsTotal = metrics.GetOrCreateCounter("requests_total") + + // Register summary with a single label. + requestDuration = metrics.NewSummary(`requests_duration_seconds{path="/foobar/baz"}`) + + // Register gauge with two labels. + // queueSize = metrics.NewGauge(`queue_size{queue="foobar",topic="baz"}`, func() float64 { + // return float64(foobarQueue.Len()) + // }) + + // Register histogram with a single label. + // responseSize = metrics.NewHistogram(`response_size{path="/foo/bar"}`) +) + +func main() { + metrics.ExposeMetadata(true) + + http.HandleFunc("/", Recovery(Metrics(rootHandler))) + + // Expose the registered metrics at `/metrics` path. + http.HandleFunc("/metrics", Recovery(metricsHandler)) + + http.HandleFunc("/hello", Recovery(Metrics(helloHandler))) + + go func() { + if err := http.ListenAndServe(":8080", nil); err != nil { + log.Fatalln(err) + } + }() + + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + + <-ctx.Done() + +} + +func rootHandler(w http.ResponseWriter, req *http.Request) { + w.Write([]byte("Simple GoLang metrics service")) +} + +// metricsHandler ... +func metricsHandler(w http.ResponseWriter, req *http.Request) { + metrics.WritePrometheus(w, true) +} + +// helloHandler ... +func helloHandler(w http.ResponseWriter, req *http.Request) { + w.Write([]byte("Hello!")) +} + +// Metrics ... +func Metrics(h http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + requestsTotal.Inc() + + startTime := time.Now() + + h(w, r) + + requestDuration.UpdateDuration(startTime) + } +} + +// Recovery ... +func Recovery(h http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + defer func() { + if err := recover(); err != nil { + log.Println(err) + } + }() + + h(w, r) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..49c3603 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module kube-vm + +go 1.25.4 + +require github.com/VictoriaMetrics/metrics v1.40.2 + +require ( + github.com/valyala/fastrand v1.1.0 // indirect + github.com/valyala/histogram v1.2.0 // indirect + golang.org/x/sys v0.15.0 // indirect +)