diff --git a/.changelog/10358.txt b/.changelog/10358.txt new file mode 100644 index 0000000000..dccaf038f2 --- /dev/null +++ b/.changelog/10358.txt @@ -0,0 +1,3 @@ +```release-note:bug +monitor: fix monitor to produce json format logs when requested +``` diff --git a/command/monitor/monitor.go b/command/monitor/monitor.go index a9aa06e09f..bd98012969 100644 --- a/command/monitor/monitor.go +++ b/command/monitor/monitor.go @@ -68,11 +68,12 @@ func (c *cmd) Run(args []string) int { c.UI.Error(fmt.Sprintf("Error starting JSON monitor: %s", err)) return 1 } - } - logCh, err = client.Agent().Monitor(c.logLevel, eventDoneCh, nil) - if err != nil { - c.UI.Error(fmt.Sprintf("Error starting monitor: %s", err)) - return 1 + } else { + logCh, err = client.Agent().Monitor(c.logLevel, eventDoneCh, nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error starting monitor: %s", err)) + return 1 + } } go func() { diff --git a/command/monitor/monitor_test.go b/command/monitor/monitor_test.go index 51e48da1ba..167d50c44e 100644 --- a/command/monitor/monitor_test.go +++ b/command/monitor/monitor_test.go @@ -1,6 +1,8 @@ package monitor import ( + "encoding/json" + "strings" "sync" "testing" "time" @@ -120,3 +122,66 @@ func TestMonitorCommand_LogJSONValidFlag(t *testing.T) { t.Fatal("timed out waiting for exit") } } + +func TestMonitorCommand_LogJSONValidFormat(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := agent.StartTestAgent(t, agent.TestAgent{}) + defer a.Shutdown() + + shutdownCh := make(chan struct{}) + + ui := cli.NewMockUi() + c := New(ui, shutdownCh) + args := []string{"-http-addr=" + a.HTTPAddr(), "-log-json"} + + // Buffer it so we don't deadlock when blocking send on shutdownCh triggers + // Run to return before we can select on it. + exitCode := make(chan int, 1) + + // Run the monitor in another go routine. If this doesn't exit on our "signal" + // then the whole test will hang and we'll panic (to not blow up if people run + // the suite without -timeout) + var wg sync.WaitGroup + wg.Add(1) + go func() { + wg.Done() // Signal that this goroutine is at least running now + exitCode <- c.Run(args) + }() + + // Wait for that routine to at least be running + wg.Wait() + + // Read the logs and try to json marshall it + go func() { + time.Sleep(1 * time.Second) + outputs := ui.OutputWriter.String() + for count, output := range strings.Split(outputs, "\n") { + if output != "" && count > 0 { + jsonLog := new(map[string]interface{}) + err := json.Unmarshal([]byte(output), jsonLog) + if err != nil { + exitCode <- -1 + } + if len(*jsonLog) <= 0 { + exitCode <- 1 + } + } + } + shutdownCh <- struct{}{} + + }() + + select { + case ret := <-exitCode: + if ret != 0 { + t.Fatal("command returned with non-zero code") + } + // OK! + case <-time.After(5 * time.Second): + t.Fatal("timed out waiting for exit") + } +}