From 65d25c56c99be68cb01e862d21f8fd6bcb390164 Mon Sep 17 00:00:00 2001 From: Kyle Sanderson Date: Tue, 27 Aug 2024 02:00:30 -0700 Subject: [PATCH] feat(diagnostics): add pprof profiling (#1627) * feat(tracing): enable tracing * of course the squash didn't work. * gah. always nice when there's 40 csets. * might as well. * refactor: tracing to diagnostics * feat: add note about the magic methods from pprof --------- Co-authored-by: ze0s --- cmd/autobrr/main.go | 3 +++ internal/config/config.go | 27 +++++++++++++++++++++++++++ internal/diagnostics/profiling.go | 30 ++++++++++++++++++++++++++++++ internal/domain/config.go | 3 +++ 4 files changed, 63 insertions(+) create mode 100644 internal/diagnostics/profiling.go diff --git a/cmd/autobrr/main.go b/cmd/autobrr/main.go index 8958f9b..64db8fe 100644 --- a/cmd/autobrr/main.go +++ b/cmd/autobrr/main.go @@ -14,6 +14,7 @@ import ( "github.com/autobrr/autobrr/internal/auth" "github.com/autobrr/autobrr/internal/config" "github.com/autobrr/autobrr/internal/database" + "github.com/autobrr/autobrr/internal/diagnostics" "github.com/autobrr/autobrr/internal/download_client" "github.com/autobrr/autobrr/internal/events" "github.com/autobrr/autobrr/internal/feed" @@ -64,6 +65,8 @@ func main() { // init dynamic config cfg.DynamicReload(log) + diagnostics.SetupProfiling(cfg.Config.ProfilingEnabled, cfg.Config.ProfilingHost, cfg.Config.ProfilingPort) + // setup server-sent-events serverEvents := sse.New() serverEvents.CreateStreamWithOpts("logs", sse.StreamOpts{MaxEntries: 1000, AutoReplay: true}) diff --git a/internal/config/config.go b/internal/config/config.go index 486a40f..2dd1d08 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -85,6 +85,15 @@ checkForUpdates = true # Session secret # sessionSecret = "{{ .sessionSecret }}" + +# Golang pprof profiling and tracing +# +#profiling = false +# +#profilingHost = "127.0.0.1" +# +# Default: 6060 +#profilingPort = 6060 ` func (c *AppConfig) writeConfig(configPath string, configFile string) error { @@ -210,6 +219,9 @@ func (c *AppConfig) defaults() { PostgresPass: "", PostgresSSLMode: "disable", PostgresExtraParams: "", + ProfilingEnabled: false, + ProfilingHost: "127.0.0.1", + ProfilingPort: 6060, } } @@ -302,6 +314,21 @@ func (c *AppConfig) loadFromEnv() { if v := os.Getenv(prefix + "POSTGRES_EXTRA_PARAMS"); v != "" { c.Config.PostgresExtraParams = v } + + if v := os.Getenv(prefix + "PROFILING"); v != "" { + c.Config.ProfilingEnabled = strings.EqualFold(strings.ToLower(v), "true") + } + + if v := os.Getenv(prefix + "PROFILING_HOST"); v != "" { + c.Config.ProfilingHost = v + } + + if v := os.Getenv(prefix + "PROFILING_PORT"); v != "" { + i, _ := strconv.ParseInt(v, 10, 32) + if i > 0 { + c.Config.ProfilingPort = int(i) + } + } } func validDatabaseType(v string) bool { diff --git a/internal/diagnostics/profiling.go b/internal/diagnostics/profiling.go new file mode 100644 index 0000000..57b99f5 --- /dev/null +++ b/internal/diagnostics/profiling.go @@ -0,0 +1,30 @@ +// Copyright (c) 2021 - 2024, Ludvig Lundgren and the autobrr contributors. +// SPDX-License-Identifier: GPL-2.0-or-later + +package diagnostics + +import ( + "fmt" + "net/http" + _ "net/http/pprof" + + "github.com/rs/zerolog/log" +) + +// SetupProfiling pprof profiling +func SetupProfiling(enabled bool, host string, port int) { + if enabled { + go func() { + // pprof has an init method which adds the following endpoints + // http.HandleFunc(prefix+"/debug/pprof/", Index) + // http.HandleFunc(prefix+"/debug/pprof/cmdline", Cmdline) + // http.HandleFunc(prefix+"/debug/pprof/profile", Profile) + // http.HandleFunc(prefix+"/debug/pprof/symbol", Symbol) + // http.HandleFunc(prefix+"/debug/pprof/trace", Trace) + err := http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil) + if err != nil { + log.Printf("Error starting profiling server: %v", err) + } + }() + } +} diff --git a/internal/domain/config.go b/internal/domain/config.go index 06d0376..9658590 100644 --- a/internal/domain/config.go +++ b/internal/domain/config.go @@ -24,6 +24,9 @@ type Config struct { PostgresPass string `toml:"postgresPass"` PostgresSSLMode string `toml:"postgresSSLMode"` PostgresExtraParams string `toml:"postgresExtraParams"` + ProfilingEnabled bool `toml:"profiling"` + ProfilingHost string `toml:"profilingHost"` + ProfilingPort int `toml:"profilingPort"` } type ConfigUpdate struct {