From 7d6387e78e47ec91a26a365840d4cc296d2b4329 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sat, 1 Mar 2014 21:32:04 +0400 Subject: [PATCH] Add debugging facilities. --- aptly/version.go | 3 ++ cmd/cmd.go | 9 ++++ cmd/context.go | 70 +++++++++++++++++++++++++ system/t02_config/ConfigInFileTest_gold | 5 ++ system/t03_help/MainHelpTest_gold | 4 ++ system/t03_help/MainTest_gold | 4 ++ 6 files changed, 95 insertions(+) diff --git a/aptly/version.go b/aptly/version.go index f616749e..b18a94cb 100644 --- a/aptly/version.go +++ b/aptly/version.go @@ -2,3 +2,6 @@ package aptly // Version of aptly const Version = "0.4~dev" + +// Enable debugging features? +const EnableDebug = true diff --git a/cmd/cmd.go b/cmd/cmd.go index 9ddce99e..aaaf2bad 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/gonuts/commander" "github.com/gonuts/flag" + "github.com/smira/aptly/aptly" "github.com/smira/aptly/debian" "os" + "time" ) // ListPackagesRefList shows list of packages in PackageRefList @@ -63,5 +65,12 @@ back as Debian repositories.`, cmd.Flag.Bool("dep-follow-all-variants", false, "when processing dependencies, follow a & b if depdency is 'a|b'") cmd.Flag.String("architectures", "", "list of architectures to consider during (comma-separated), default to all available") cmd.Flag.String("config", "", "location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)") + + if aptly.EnableDebug { + cmd.Flag.String("cpuprofile", "", "write cpu profile to file") + cmd.Flag.String("memprofile", "", "write memory profile to this file") + cmd.Flag.String("memstats", "", "write memory stats periodically to this file") + cmd.Flag.Duration("meminterval", 100*time.Millisecond, "memory stats dump interval") + } return cmd } diff --git a/cmd/context.go b/cmd/context.go index fce73fff..3e3f4b70 100644 --- a/cmd/context.go +++ b/cmd/context.go @@ -10,8 +10,12 @@ import ( "github.com/smira/aptly/files" "github.com/smira/aptly/http" "github.com/smira/aptly/utils" + "os" "path/filepath" + "runtime" + "runtime/pprof" "strings" + "time" ) // Common context shared by all commands @@ -23,6 +27,10 @@ var context struct { publishedStorage aptly.PublishedStorage dependencyOptions int architecturesList []string + // Debug features + fileCPUProfile *os.File + fileMemProfile *os.File + fileMemStats *os.File } // InitContext initializes context with default settings @@ -62,11 +70,73 @@ func InitContext(cmd *commander.Command) error { context.packagePool = files.NewPackagePool(utils.Config.RootDir) context.publishedStorage = files.NewPublishedStorage(utils.Config.RootDir) + if aptly.EnableDebug { + cpuprofile := cmd.Flag.Lookup("cpuprofile").Value.String() + if cpuprofile != "" { + context.fileCPUProfile, err = os.Create(cpuprofile) + if err != nil { + return err + } + pprof.StartCPUProfile(context.fileCPUProfile) + } + + memprofile := cmd.Flag.Lookup("memprofile").Value.String() + if memprofile != "" { + context.fileMemProfile, err = os.Create(memprofile) + if err != nil { + return err + } + } + + memstats := cmd.Flag.Lookup("memstats").Value.String() + if memstats != "" { + interval := cmd.Flag.Lookup("meminterval").Value.Get().(time.Duration) + + context.fileMemStats, err = os.Create(memstats) + if err != nil { + return err + } + + context.fileMemStats.WriteString("Time\tAlloc\tTotalAlloc\tSys\tLookups\tMallocst\tFrees\tLastGC\tNumGC\n") + + go func() { + var stats runtime.MemStats + for { + runtime.ReadMemStats(&stats) + if context.fileMemStats != nil { + context.fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%dex\t%d\n", + time.Now().UnixNano(), stats.Alloc, stats.TotalAlloc, stats.Sys, stats.Lookups, stats.Mallocs, + stats.Frees, stats.LastGC, stats.NumGC)) + time.Sleep(interval) + } else { + break + } + } + }() + } + } + return nil } // ShutdownContext shuts context down func ShutdownContext() { + if aptly.EnableDebug { + if context.fileMemProfile != nil { + pprof.WriteHeapProfile(context.fileMemProfile) + context.fileMemProfile.Close() + context.fileMemProfile = nil + } + if context.fileCPUProfile != nil { + pprof.StopCPUProfile() + context.fileCPUProfile.Close() + context.fileCPUProfile = nil + } + if context.fileMemProfile != nil { + context.fileMemProfile.Close() + context.fileMemProfile = nil + } + } context.database.Close() context.downloader.Shutdown() context.progress.Shutdown() diff --git a/system/t02_config/ConfigInFileTest_gold b/system/t02_config/ConfigInFileTest_gold index e366b77e..e8266759 100644 --- a/system/t02_config/ConfigInFileTest_gold +++ b/system/t02_config/ConfigInFileTest_gold @@ -17,7 +17,12 @@ Use "aptly help " for more information about a command. Options: -architectures="": list of architectures to consider during (comma-separated), default to all available -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) + -cpuprofile="": write cpu profile to file -dep-follow-all-variants=false: when processing dependencies, follow a & b if depdency is 'a|b' -dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-suggests=false: when processing dependencies, follow Suggests + -meminterval=100ms: memory stats dump interval + -memprofile="": write memory profile to this file + -memstats="": write memory stats periodically to this file + diff --git a/system/t03_help/MainHelpTest_gold b/system/t03_help/MainHelpTest_gold index 12772441..edbe7b31 100644 --- a/system/t03_help/MainHelpTest_gold +++ b/system/t03_help/MainHelpTest_gold @@ -6,8 +6,12 @@ back as Debian repositories. Options: -architectures="": list of architectures to consider during (comma-separated), default to all available -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) + -cpuprofile="": write cpu profile to file -dep-follow-all-variants=false: when processing dependencies, follow a & b if depdency is 'a|b' -dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-suggests=false: when processing dependencies, follow Suggests + -meminterval=100ms: memory stats dump interval + -memprofile="": write memory profile to this file + -memstats="": write memory stats periodically to this file diff --git a/system/t03_help/MainTest_gold b/system/t03_help/MainTest_gold index e366b77e..7dd843ce 100644 --- a/system/t03_help/MainTest_gold +++ b/system/t03_help/MainTest_gold @@ -17,7 +17,11 @@ Use "aptly help " for more information about a command. Options: -architectures="": list of architectures to consider during (comma-separated), default to all available -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) + -cpuprofile="": write cpu profile to file -dep-follow-all-variants=false: when processing dependencies, follow a & b if depdency is 'a|b' -dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-suggests=false: when processing dependencies, follow Suggests + -meminterval=100ms: memory stats dump interval + -memprofile="": write memory profile to this file + -memstats="": write memory stats periodically to this file