Add basic prometheus metrics

This commit is contained in:
Thor77 2023-02-18 17:05:28 +01:00
parent 8d06835a8d
commit 6375264c26
No known key found for this signature in database
GPG key ID: 5051E71B46AA669A

View file

@ -21,11 +21,16 @@ import (
chimiddleware "github.com/go-chi/chi/middleware"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
fsnotify "gopkg.in/fsnotify.v1"
)
const (
version = "2.8.0"
version = "2.8.0"
metricsNamespace = "webhook"
)
var (
@ -52,6 +57,7 @@ var (
setUID = flag.Int("setuid", 0, "set user ID after opening listening port; must be used with setgid")
httpMethods = flag.String("http-methods", "", `set default allowed HTTP methods (ie. "POST"); separate methods with comma`)
pidPath = flag.String("pidfile", "", "create PID file at the given path")
metrics = flag.Bool("metrics", false, "enable prometheus metrics at /metrics")
responseHeaders hook.ResponseHeaders
hooksFiles hook.HooksFiles
@ -63,6 +69,31 @@ var (
pidFile *pidfile.PIDFile
)
// prometheus metrics
var hookCounter = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: metricsNamespace,
Name: "hook_requests_total",
Help: "Total number of hook requests",
}, []string{"hook"},
)
var hookErrorCounter = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: metricsNamespace,
Name: "hook_errors_total",
Help: "Total number of hook errors",
}, []string{"hook", "error"},
)
var hookSuccessCounter = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: metricsNamespace,
Name: "hook_success_total",
Help: "Total number of successful hook executions",
}, []string{"hook"},
)
func matchLoadedHook(id string) *hook.Hook {
for _, hooks := range loadedHooksFromFiles {
if hook := hooks.Match(id); hook != nil {
@ -270,6 +301,11 @@ func main() {
r.HandleFunc(hooksURL, hookHandler)
if *metrics {
// add /metrics handler
r.Handle("/metrics", promhttp.Handler())
}
// Create common HTTP server settings
svr := &http.Server{
Addr: addr,
@ -315,6 +351,8 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
return
}
hookCounter.With(prometheus.Labels{"hook": matchedHook.ID}).Inc()
// Check for allowed methods
var allowedMethod bool
@ -340,6 +378,8 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
}
if !allowedMethod {
hookErrorCounter.With(prometheus.Labels{"hook": matchedHook.ID, "error": "invalid_method"}).Inc()
w.WriteHeader(http.StatusMethodNotAllowed)
log.Printf("[%s] HTTP %s method not allowed for hook %q", req.ID, r.Method, id)
@ -540,6 +580,8 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
writeHttpResponseCode(w, req.ID, matchedHook.ID, matchedHook.TriggerRuleMismatchHttpResponseCode)
}
hookErrorCounter.With(prometheus.Labels{"hook": matchedHook.ID, "error": "rules"}).Inc()
// if none of the hooks got triggered
log.Printf("[%s] %s got matched, but didn't get triggered because the trigger rules were not satisfied\n", req.ID, matchedHook.ID)
@ -559,6 +601,7 @@ func handleHook(h *hook.Hook, r *hook.Request) (string, error) {
cmdPath, err := exec.LookPath(lookpath)
if err != nil {
hookErrorCounter.With(prometheus.Labels{"hook": h.ID, "error": "command"}).Inc()
log.Printf("[%s] error in %s", r.ID, err)
// check if parameters specified in execute-command by mistake
@ -620,6 +663,7 @@ func handleHook(h *hook.Hook, r *hook.Request) (string, error) {
log.Printf("[%s] command output: %s\n", r.ID, out)
if err != nil {
hookErrorCounter.With(prometheus.Labels{"hook": h.ID, "error": "command"}).Inc()
log.Printf("[%s] error occurred: %+v\n", r.ID, err)
}
@ -633,6 +677,8 @@ func handleHook(h *hook.Hook, r *hook.Request) (string, error) {
}
}
hookSuccessCounter.With(prometheus.Labels{"hook": h.ID}).Inc()
log.Printf("[%s] finished handling %s\n", r.ID, h.ID)
return string(out), err