From d2096b251d532c4285532a5440e0e9c683ce48cc Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Tue, 22 Dec 2020 15:15:24 -0500 Subject: [PATCH] Add log gathering to debug command. (#10609) --- changelog/10609.txt | 3 +++ command/debug.go | 39 +++++++++++++++++++++++++++++++++++++-- command/debug_test.go | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 changelog/10609.txt diff --git a/changelog/10609.txt b/changelog/10609.txt new file mode 100644 index 000000000..77ca658c1 --- /dev/null +++ b/changelog/10609.txt @@ -0,0 +1,3 @@ +```release-note:improvement +command/debug: Now collects logs (at level `trace`) as a periodic output. +``` \ No newline at end of file diff --git a/command/debug.go b/command/debug.go index 655583957..df8e0ac68 100644 --- a/command/debug.go +++ b/command/debug.go @@ -169,7 +169,7 @@ func (c *DebugCommand) Flags() *FlagSets { Usage: "Target to capture, defaulting to all if none specified. " + "This can be specified multiple times to capture multiple targets. " + "Available targets are: config, host, metrics, pprof, " + - "replication-status, server-status.", + "replication-status, server-status, log.", }) return set @@ -477,7 +477,7 @@ func (c *DebugCommand) preflight(rawArgs []string) (string, error) { } func (c *DebugCommand) defaultTargets() []string { - return []string{"config", "host", "metrics", "pprof", "replication-status", "server-status"} + return []string{"config", "host", "metrics", "pprof", "replication-status", "server-status", "log"} } func (c *DebugCommand) captureStaticTargets() error { @@ -513,6 +513,7 @@ func (c *DebugCommand) capturePollingTargets() error { var g run.Group ctx, cancelFunc := context.WithTimeout(context.Background(), c.flagDuration+debugDurationGrace) + defer cancelFunc() // This run group watches for interrupt or duration g.Add(func() error { @@ -576,6 +577,15 @@ func (c *DebugCommand) capturePollingTargets() error { }) } + if strutil.StrListContains(c.flagTargets, "log") { + g.Add(func() error { + _ = c.writeLogs(ctx) + return nil + }, func(error) { + cancelFunc() + }) + } + // We shouldn't bump across errors since none is returned by the interrupts, // but we error check for sanity here. if err := g.Run(); err != nil { @@ -981,3 +991,28 @@ func (c *DebugCommand) captureError(target string, err error) { }) c.errLock.Unlock() } + +func (c *DebugCommand) writeLogs(ctx context.Context) error { + out, err := os.Create(filepath.Join(c.flagOutput, "vault.log")) + if err != nil { + return err + } + defer out.Close() + + logCh, err := c.cachedClient.Sys().Monitor(ctx, "trace") + if err != nil { + return err + } + + for { + select { + case log := <-logCh: + _, err = out.WriteString(log) + if err != nil { + return err + } + case <-ctx.Done(): + return nil + } + } +} diff --git a/command/debug_test.go b/command/debug_test.go index c4a4df6c2..55520aeda 100644 --- a/command/debug_test.go +++ b/command/debug_test.go @@ -685,6 +685,7 @@ func TestDebugCommand_PartialPermissions(t *testing.T) { case fh.Name == filepath.Join(basePath, "index.json"): case fh.Name == filepath.Join(basePath, "replication_status.json"): case fh.Name == filepath.Join(basePath, "server_status.json"): + case fh.Name == filepath.Join(basePath, "vault.log"): default: return fmt.Errorf("unexpected file: %s", fh.Name) }