GoFiber ve VictoriaMetrics ile Custom Metric Oluşturabilmek

Zeki Ahmet Bayar
HAVELSAN
Published in
3 min readJan 30, 2024

Prometheus time-series veri tabanı konusunda son dönemlerin favorisi ve ben de prometheus’u internal projelerde kullanmak hakkında bir takım araştırmalarda bulundum. Bu araştırmalarım sırasında hem basit bir şekilde metric yayınlayabileceğim hem de bunu Go Fiber/v2 ile yapabileceğim derli toplu bir kaynak bulamadım. Bu sebeple tüm bu konuları bir araya toplamaya karar verdim.

Fiber ile basit bir proje oluşturmak

Fiber aslında nodejs’in web kütüphanesi olan express'den esinlenilerek yapılmış bir framework. Fiber ile basit bir projeyi aşağıdaki gibi oluşturabiliriz.

package main

import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
_ "github.com/joho/godotenv/autoload"
)
func main() {
// Create app
app := fiber.New()
// Set default fiber logger
app.Use(logger.New())
// Register sample GET route as 'hello'
app.Get("/", func(c *fiber.Ctx) error {
return c.JSON("Hello! Welcome to Go World.")
})
// Listen 7806
log.Fatal(app.Listen("0.0.0.0:7806"))
}

Projeyi ayağa kaldırıp, http://localhost:7806 üzerinden erişim sağladığımızda aşağıdaki gibi görünüyor.

VictoriaMetrics ile basit metricler oluşturmak

Prometheus’da tutacağımız metrikleri VictoriaMetrics kütüphanesi ile yayınlayacağız. Basit bir metriği aşağıdaki gibi oluşturabiliriz.

// Set counter metric
func CounterSet(name string, value float64) {
// Create counter
counter := victoria.GetOrCreateFloatCounter(name)
// Set value as counter’s value
counter.Set(value)
}

Bu şekilde oluşturduğumuz bir metrik işlevi, onu her çağırdığımızda veriyi yeniden set edecektir. Eğer setlediğimiz bir veriyi sürekli olarak arttırmak istiyorsak aşağıdaki gibi bir işlev hazırlamamız gerekmekte.

// Counter add
func CounterAdd(name string, value float64) {
// Create counter
counter := victoria.GetOrCreateFloatCounter(name)
// Add value to counter’s last value
counter.Add(value)
}

Eğer her çağırıldığında var olan veriyi azaltacak bir işlev istenirse tahmin edeceğiniz gibi counter objesinin .Sub() methodunu kullanmamız gerekmekte.

// Counter sub
func CounterSub(name string, value float64) {
// Create counter
counter := victoria.GetOrCreateFloatCounter(name)
// Sub value from counter
counter.Sub(value)
}

Oluşturduğumuz bu fonksiyonları başlangıçta yazdığımız api’a bağlamak istersek aşağıdaki gibi görünecektir.

.
.
// Register add metric endpoint
app.Post(“/inc”, func(c *fiber.Ctx) error {
CounterAdd(`sample_metric{value=”sample_value”}`, 1)
return c.JSON(“Incremented sample value metric.”)
})

// Register sub metric endpoint
app.Post("/dec", func(c *fiber.Ctx) error {
CounterSub(`sample_metric{value="sample_value"}`, 1)
return c.JSON("Decremented sample value metric.")
})
.
.

Son olarak bu veriyi yayınlayacağımız metrics ucunu da aşağıdaki gibi register edebiliriz.

// Register metric endpoint as route
app.Get("/metrics",
adaptor.HTTPHandler(http.HandlerFunc(metric)))

// Metrics
func metric(w http.ResponseWriter, req *http.Request) {
victoria.WritePrometheus(w, true)
}

Projeyi bu haliyle çalıştırdıktan sonra metricleri aşağıdaki gibi görüntüleyip daha öncesinde oluşturduğumuz `/inc` ve `/dec` rotaları ile de sample_value verisini değiştirebiliriz.

Projeye son kez dönüp baktığımızda ise şöyle görünüyor.

package main

import (
"log"
"net/http"
victoria "github.com/VictoriaMetrics/metrics"
"github.com/gofiber/adaptor/v2"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
_ "github.com/joho/godotenv/autoload"
)
func main() {
// Create app
app := fiber.New()
// Set default fiber logger
app.Use(logger.New())
// Register sample GET route as 'hello'
app.Get("/", func(c *fiber.Ctx) error {
return c.JSON("Hello! Welcome to Go World.")
})
// Register add metric endpoint
app.Post("/inc", func(c *fiber.Ctx) error {
CounterAdd(`sample_metric{value="sample_value"}`, 1)
return c.JSON("Incremented sample value metric.")
})
// Register sub metric endpoint
app.Post("/dec", func(c *fiber.Ctx) error {
CounterSub(`sample_metric{value="sample_value"}`, 1)
return c.JSON("Decremented sample value metric.")
})
// Register metric endpoint as route
app.Get("/metrics",
adaptor.HTTPHandler(http.HandlerFunc(metric)))
// Listen 7806
log.Fatal(app.Listen("0.0.0.0:7806"))
}
// Add data to existsing metric
func CounterAdd(name string, value float64) {
// Create counter
counter := victoria.GetOrCreateFloatCounter(name)
// Add value to counter's last value
counter.Add(value)
}
// Counter sub
func CounterSub(name string, value float64) {
// Create counter
counter := victoria.GetOrCreateFloatCounter(name)
// Sub value from counter
counter.Sub(value)
}
// Metrics
func metric(w http.ResponseWriter, req *http.Request) {
victoria.WritePrometheus(w, true)
}

Bir sonraki aşamada oluşturduğumuz bu metrikler grafana ile görselleştirilebilir.

--

--