프로메테우스 가이드북은 A to Z Metnros (Udemy) — Prometheus | The Complete Hands-On for Monitoring & Alerting를 듣고 작성한 가이드북입니다.
가이드북의 전체 목차 및 인덱싱은 프로메테우스 가이드북 — 소개 페이지를 참고해주세요.
사전 지식
앞서 Metric Type, Metric Name Convention 그리고 Python Application 예제를 학습하였습니다. 이번에는 같은 내용을 Golang Application에 대해서 진행할 것입니다.
예제
Golang Application
Prometheus Client - add new COUNTER
Prometheus Server
Prometheus Client - add new GAUGE
Prometheus Client - add new SUMMARY
Golang Application
다음의 코드를 counter.go
로 작성해주세요.
package main
imoprt (
"net/http"
"fmt"
"log"
"github.com/gorilla/mux"
)
func main() {
startMyApp()
}
func startMyApp() {
router := mux.NewRouter()
router.HandleFunc("/birthday/{name}", func(rw http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars("name")
greetings := fmt.Sprintf("Happy Birthday %S :)", name)
rw.Write([]byte(greetings))
}).Methods("GET")
log.Println("Starting the application servers...")
http.ListenAndServe(":8000", router)
}
위 서버를 실행하기 위해서 아래 명령어를 사용할 수 있습니다.
go run counter.go
Prometheus Client - add new COUNTER
작성한 Golang Application에 Prometheus Client 관련 코드를 추가하였습니다.
추가한 REQUEST_COUNT
는 [GET] /birthday/{name}의 요청 숫자를 수집하는 기능을 담당합니다. 또한 매트릭을 수집하기 위한 promhttp.Handler()
도 등록되어 있습니다.
import (
# ...
"github.com/prometheus/client_golang/prometheus", # ⛳️
"github.com/prometheus/client_golang/prometheus/promhttp", # ⛳️
"github.com/prometheus/client_golang/prometheus/promauto", # ⛳️
)
var REQUEST_COUNT = promauto.NewCounter(prometheus.CounterOpts{
Name: "go_app_requests_count",
Help: "Total App HTTP Request Count"
}) # ⛳️
func main() {} # ...
func startMyApp() {
router := mux.NewRouter()
router.HandleFunc("/birthday/{name}", func(rw http.ResponseWriter, r *http.Request) {
# ...
router.HandleFunc("/birthday/{name}", func(rw http.ResponseWriter, r *http.Request) {
# ...
REQUEST_COUNT.Inc() # ⛳️
}).Method("GET")
router.Path('/metrics').Handler(promhttp.Handler()) # ⛳️
# ...
}
Python Application에서는 localhost:8000
에 App Server가 localhost:8001
에 Metric Server가 실행되었습니다.
하지만 Golang Application에서는 localhost:8000
에서 App/Metric Server가 실행됩니다. 다른 점은 localhost:8000/metrics
쪽으로 promhttp.Handler()가 등록이 된다는 점입니다.
Prometheus Server
Golang Application에 Prometheus Client를 등록하였으니, Promethes Server의 scrap_configs
에 새로운 대상으로 등록해야 합니다.
# ...
scrp_configs:
# ...
- job_name: "prom_go_app"
static_configs:
- targets: ["localhost:8000"]
Prometheus Client - add new GAUGE
다음과 같이 Gauge Metric을 수집하도록 구성된 Golang Application이 있습니다.
# ...
var REQUEST_INPROGRESS = promauto.NewGauge(promtheus.GuageOpts{
Name: "go_app_requests_inprogress",
Help: "Number of application requests in progress"
})
func main() {} # ...
func startMyApp() {
router := mux.NewRouter()
router.HandleFunc("/birthday/{name}", func(rw http.ResponseWriter, r *http.Request) {
# ...
router.HandleFunc("/birthday/{name}", func(rw http.ResponseWriter, r *http.Request) {
REQUEST_INPROGRESS.Inc() # ⛳️
# ...
time.Sleep(S * time.Second) # ⛳️
REQUEST_INPROGRESS.Dec() # ⛳️
}).Method("GET")
router.Path('/metrics').Handler(promhttp.Handler()) # ⛳️
}
Prometheus Client - add new SUMMARY
다음과 같이 Summry Metric을 수집하도록 구성된 Golang Application이 있습니다.
# ...
var REQUEST_RESPOND_TIME = promauto.NewSummaryVec(prometheus.SummaryOpts{
Name: "go_app_response_latency_seconds",
Help: "Response latency in seconds"
})
func routeMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
start_time := time.Now()
route := mux.CurrentRoute(r)
path, _ := route.GetPathTemplate()
next.ServeHTTP(w, r)
time_taken := time.Since(start_time)
REQUEST_RESPOND_TIME.WithLabelValues(path).Observe(time_taken.Seconds()) # ⛳️
}
}
func main() {
startMyApp()
}
func startMyApp() {
router := mux.NewRouter()
router.HandleFunc("/birthday/{name}", func (rw http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["name"]
time.Sleep(5 * time.Second)
rs.Wirte([]byte(greetings))
}).Methods("GET")
router.Use(routeMiddleware) # ⛳️
log.Println("Starting the application server...")
router.Path("/metrics").Handler(promhttp.Handler())
http.ListenAndServe(":8000", router)
}