feat: add metrics

This commit is contained in:
Jonas Kaninda
2024-11-10 17:06:58 +01:00
parent a549e33e9a
commit 00702e138b
7 changed files with 114 additions and 2 deletions

67
internal/prometheus.go Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright 2024 Jonas Kaninda
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package pkg
import (
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"net/http"
"strconv"
)
type PrometheusRoute struct {
name string
path string
}
var totalRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Number of get requests.",
},
[]string{"path"},
)
var responseStatus = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "response_status",
Help: "Status of HTTP response",
},
[]string{"status"},
)
var httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "http_response_time_seconds",
Help: "Duration of HTTP requests.",
}, []string{"path"})
func prometheusMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
route := mux.CurrentRoute(r)
path, _ := route.GetPathTemplate()
timer := prometheus.NewTimer(httpDuration.WithLabelValues(path))
responseStatus.WithLabelValues(strconv.Itoa(http.StatusOK)).Inc()
totalRequests.WithLabelValues(path).Inc()
timer.ObserveDuration()
next.ServeHTTP(w, r)
})
}

View File

@@ -29,7 +29,7 @@ import (
// ProxyHandler proxies requests to the backend
func (proxyRoute ProxyRoute) ProxyHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logger.Info("%s %s %s %s", r.Method, getRealIP(r), r.URL, r.UserAgent())
logger.Info("%s %s %s %s", r.Method, getRealIP(r), r.URL.Path, r.UserAgent())
// Check Method if is allowed
if len(proxyRoute.methods) > 0 {
if !slices.Contains(proxyRoute.methods, r.Method) {

View File

@@ -20,9 +20,17 @@ import (
"github.com/jkaninda/goma-gateway/internal/middleware"
"github.com/jkaninda/goma-gateway/pkg/logger"
"github.com/jkaninda/goma-gateway/util"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"time"
)
func init() {
_ = prometheus.Register(totalRequests)
_ = prometheus.Register(responseStatus)
_ = prometheus.Register(httpDuration)
}
// Initialize the routes
func (gatewayServer GatewayServer) Initialize() *mux.Router {
gateway := gatewayServer.gateway
@@ -32,11 +40,18 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router {
DisableRouteHealthCheckError: gateway.DisableRouteHealthCheckError,
Routes: gateway.Routes,
}
if gateway.EnableMetrics {
// Prometheus endpoint
r.Path("/metrics").Handler(promhttp.Handler())
r.Use(prometheusMiddleware)
}
// Routes health check
if !gateway.DisableHealthCheckStatus {
r.HandleFunc("/healthz", heath.HealthCheckHandler).Methods("GET")
r.HandleFunc("/health/routes", heath.HealthCheckHandler).Methods("GET")
}
// Health check
r.HandleFunc("/health/live", heath.HealthReadyHandler).Methods("GET")
r.HandleFunc("/readyz", heath.HealthReadyHandler).Methods("GET")
@@ -223,6 +238,7 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router {
} else {
router.PathPrefix("").Handler(proxyRoute.ProxyHandler())
}
} else {
logger.Error("Error, path is empty in route %s", route.Name)
logger.Error("Route path ignored: %s", route.Path)

View File

@@ -196,6 +196,7 @@ type Gateway struct {
DisableDisplayRouteOnStart bool `yaml:"disableDisplayRouteOnStart"`
// DisableKeepAlive allows enabling and disabling KeepALive server
DisableKeepAlive bool `yaml:"disableKeepAlive"`
EnableMetrics bool `yaml:"enableMetrics"`
// InterceptErrors holds the status codes to intercept the error from backend
InterceptErrors []int `yaml:"interceptErrors"`
// Cors holds proxy global cors