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" _ "github.com/mattn/go-sqlite3" ) var ( configFile = flag.String("config", "config.yaml", "path to the YAML configuration file") enablePprof = flag.Bool("pprof", false, "expose pprof endpoints at /debug/pprof") ) 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, flag.Args(), *enablePprof) } // 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 }