From 213628b9585eefaa7c6caff16d4afa8a656d2470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Pa=C3=9F?= <22845248+mpass99@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:55:23 +0100 Subject: [PATCH] Debug Health route latency. --- internal/api/health.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/internal/api/health.go b/internal/api/health.go index 5c2699f..3da4121 100644 --- a/internal/api/health.go +++ b/internal/api/health.go @@ -1,13 +1,18 @@ package api import ( + "context" "errors" "fmt" + "github.com/coreos/go-systemd/v22/daemon" "github.com/openHPI/poseidon/internal/config" "github.com/openHPI/poseidon/internal/environment" "github.com/openHPI/poseidon/pkg/dto" "net/http" + "os" + "runtime/pprof" "strings" + "time" ) var ErrorPrewarmingPoolDepleting = errors.New("the prewarming pool is depleting") @@ -17,6 +22,10 @@ var ErrorPrewarmingPoolDepleting = errors.New("the prewarming pool is depleting" // If it is not, the response won't reach the client. func Health(manager environment.Manager) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { + ctx, cancel := context.WithCancel(request.Context()) + defer cancel() + go debugGoroutines(ctx) + if err := checkPrewarmingPool(manager); err != nil { sendJSON(writer, &dto.InternalServerError{Message: err.Error(), ErrorCode: dto.PrewarmingPoolDepleting}, http.StatusServiceUnavailable, request.Context()) @@ -40,3 +49,24 @@ func checkPrewarmingPool(manager environment.Manager) error { } return nil } + +// debugGoroutines temporarily debugs a behavior where we observe long latencies in the Health route. +func debugGoroutines(ctx context.Context) { + interval, err := daemon.SdWatchdogEnabled(false) + if err != nil || interval == 0 { + return + } + log.Trace("Starting timeout for debugging the Goroutines") + + const notificationIntervalFactor = 3 + select { + case <-ctx.Done(): + return + case <-time.After(interval / notificationIntervalFactor): + log.Warn("Health route latency is too high") + err := pprof.Lookup("goroutine").WriteTo(os.Stderr, 1) + if err != nil { + log.WithError(err).Warn("Failed to log the goroutines") + } + } +}