diff --git a/diagnostics/profile.go b/diagnostics/profile.go new file mode 100644 index 00000000000..4a9a16e3bfd --- /dev/null +++ b/diagnostics/profile.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Erigon Authors +// This file is part of Erigon. +// +// Erigon is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Erigon is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Erigon. If not, see . + +package diagnostics + +import ( + "fmt" + "net/http" + "runtime/pprof" + "strings" + + diaglib "github.com/erigontech/erigon-lib/diagnostics" +) + +func SetupProfileAccess(metricsMux *http.ServeMux, diag *diaglib.DiagnosticClient) { + if metricsMux == nil { + return + } + + //handle all pprof, supported: goroutine, threadcreate, heap, allocs, block, mutex + metricsMux.HandleFunc("/pprof/", func(w http.ResponseWriter, r *http.Request) { + profile := strings.TrimPrefix(r.URL.Path, "/pprof/") + writePprofProfile(w, profile) + }) +} + +func writePprofProfile(w http.ResponseWriter, profile string) { + p := pprof.Lookup(profile) + if p == nil { + http.Error(w, "Unknown profile: "+profile, http.StatusNotFound) + return + } + + w.Header().Set("Content-Type", "aplication/profile") + err := p.WriteTo(w, 0) + if err != nil { + http.Error(w, fmt.Sprintf("Failed to write profile: %v", err), http.StatusInternalServerError) + return + } +} diff --git a/diagnostics/setup.go b/diagnostics/setup.go index 934ec963cc6..2462bd0e50e 100644 --- a/diagnostics/setup.go +++ b/diagnostics/setup.go @@ -146,4 +146,5 @@ func SetupEndpoints(ctx *cli.Context, node *node.ErigonNode, diagMux *http.Serve SetupHeadersAccess(diagMux, diagnostic) SetupBodiesAccess(diagMux, diagnostic) SetupSysInfoAccess(diagMux, diagnostic) + SetupProfileAccess(diagMux, diagnostic) } diff --git a/diagnostics/sysinfo.go b/diagnostics/sysinfo.go index 402eaad688b..571fd0d4ce2 100644 --- a/diagnostics/sysinfo.go +++ b/diagnostics/sysinfo.go @@ -18,9 +18,7 @@ package diagnostics import ( "encoding/json" - "fmt" "net/http" - "runtime/pprof" diaglib "github.com/erigontech/erigon-lib/diagnostics" "github.com/erigontech/erigon-lib/sysutils" @@ -50,19 +48,6 @@ func SetupSysInfoAccess(metricsMux *http.ServeMux, diag *diaglib.DiagnosticClien w.Header().Set("Content-Type", "application/json") writeMemoryInfo(w) }) - - metricsMux.HandleFunc("/heap-profile", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "aplication/profile") - writeHeapProfile(w) - }) -} - -func writeHeapProfile(w http.ResponseWriter) { - err := pprof.Lookup("heap").WriteTo(w, 0) - if err != nil { - http.Error(w, fmt.Sprintf("Failed to write profile: %v", err), http.StatusInternalServerError) - return - } } func writeHardwareInfo(w http.ResponseWriter, diag *diaglib.DiagnosticClient) {