diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-27 13:06:20 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-27 13:06:20 +0200 |
| commit | 6ec883a7fd40a14f2882076bd1a377bbbd0438ad (patch) | |
| tree | 2d199226b29ada6dbe74b2ce278b000c296a1b3a /main.go | |
| parent | 522512197de372aa9b9c5584711619a76a5546d8 (diff) | |
Add local Pyroscope server and Go continuous profiling
Add a docker-compose service running the Grafana Pyroscope backend on
port 4040 with a persistent data volume, and instrument the Go app via
github.com/grafana/pyroscope-go. The app pushes CPU, memory, and
goroutine profiles every 10s when pyroscope.enabled is set in
config.yaml. Config is extended with application_name and server_address
(defaults to http://localhost:4040). Document usage in the README.
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 36 |
1 files changed, 36 insertions, 0 deletions
@@ -3,7 +3,9 @@ package main import ( "database/sql" "flag" + "log/slog" + "github.com/grafana/pyroscope-go" "github.com/martinlehoux/biking_home/cli" "github.com/martinlehoux/biking_home/config" "github.com/martinlehoux/kagamigo/kcore" @@ -18,8 +20,42 @@ func main() { flag.Parse() appConfig, err := config.Load(*configFile) kcore.Expect(err, "failed to load configuration") + stopProfiler, err := startPyroscope(appConfig.Pyroscope) + if err != nil { + kcore.Expect(err, "failed to start pyroscope") + } + if stopProfiler != nil { + defer stopProfiler() + } db, err := sql.Open("sqlite3", appConfig.Database.Path) kcore.Expect(err, "failed to open database") defer db.Close() cli.Run(db, *configFile, appConfig) } + +// startPyroscope starts the continuous profiler when enabled in the config and +// returns a stop function to flush and detach the profiler on shutdown, or nil +// when pyroscope is disabled. +func startPyroscope(appConfig config.PyroscopeConfig) (func(), error) { + if !appConfig.Enabled { + return nil, nil + } + profiler, err := pyroscope.Start(pyroscope.Config{ + ApplicationName: appConfig.ApplicationName, + ServerAddress: appConfig.ServerAddress, + Logger: pyroscope.StandardLogger, + ProfileTypes: []pyroscope.ProfileType{ + pyroscope.ProfileCPU, + pyroscope.ProfileAllocSpace, + pyroscope.ProfileAllocObjects, + pyroscope.ProfileInuseSpace, + pyroscope.ProfileInuseObjects, + pyroscope.ProfileGoroutines, + }, + }) + if err != nil { + return nil, err + } + slog.Info("pyroscope enabled", "server", appConfig.ServerAddress, "application", appConfig.ApplicationName) + return func() { _ = profiler.Stop() }, nil +} |
