Skip to content

Commit

Permalink
cmd: split newlines in logrus stderr output to new entry
Browse files Browse the repository at this point in the history
Currently the logrus hook runs formatter once for each entry, which causes newlines to be escaped see sirupsen/logrus#608
Because of this multiline messages end up looking like

```go
logrus.Info(`some message
same mesage multiline 1`)
logrus.Info("next meesage")
```

```
LEVEL some message
same message multiline 1
LEVEL next messsage
```

With this change the hook will format each entry's message split on newlines so that,

```go
logrus.Info(`some message
same mesage multiline 1`)
logrus.Info("next meesage")
```

```
LEVEL some message
LEVEL same message multiline 1
LEVEL next messsage
```

This will help 2 cases,
- openshift@af9b49c like informational messages that are require multiple lines to be more user-friendly.
- meesages from cluster operators on install-complete failure see openshift#4242
  • Loading branch information
abhinavdahiya committed Oct 19, 2020
1 parent cf57c06 commit de81d35
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
37 changes: 32 additions & 5 deletions cmd/openshift-install/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"io"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand All @@ -15,6 +16,8 @@ type fileHook struct {
file io.Writer
formatter logrus.Formatter
level logrus.Level

truncateAtNewLine bool
}

func newFileHook(file io.Writer, level logrus.Level, formatter logrus.Formatter) *fileHook {
Expand All @@ -25,6 +28,12 @@ func newFileHook(file io.Writer, level logrus.Level, formatter logrus.Formatter)
}
}

func newFileHookWithNewlineTruncate(file io.Writer, level logrus.Level, formatter logrus.Formatter) *fileHook {
f := newFileHook(file, level, formatter)
f.truncateAtNewLine = true
return f
}

func (h fileHook) Levels() []logrus.Level {
var levels []logrus.Level
for _, level := range logrus.AllLevels {
Expand All @@ -37,13 +46,31 @@ func (h fileHook) Levels() []logrus.Level {
}

func (h *fileHook) Fire(entry *logrus.Entry) error {
line, err := h.formatter.Format(entry)
if err != nil {
return err
// logrus reuses the same entry for each invocation of hooks.
// so we need to make sure we leave them message field as we received.
orig := entry.Message
defer func() { entry.Message = orig }()

msgs := []string{orig}
if h.truncateAtNewLine {
msgs = strings.Split(orig, "\n")
}

for _, msg := range msgs {
// this makes it easier to call format on entry
// easy without creating a new one for each split message.
entry.Message = msg
line, err := h.formatter.Format(entry)
if err != nil {
return err
}

if _, err := h.file.Write(line); err != nil {
return err
}
}

_, err = h.file.Write(line)
return err
return nil
}

func setupFileHook(baseDir string) func() {
Expand Down
3 changes: 2 additions & 1 deletion cmd/openshift-install/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func runRootCmd(cmd *cobra.Command, args []string) {
level = logrus.InfoLevel
}

logrus.AddHook(newFileHook(os.Stderr, level, &logrus.TextFormatter{
logrus.AddHook(newFileHookWithNewlineTruncate(os.Stderr, level, &logrus.TextFormatter{
// Setting ForceColors is necessary because logrus.TextFormatter determines
// whether or not to enable colors by looking at the output of the logger.
// In this case, the output is ioutil.Discard, which is not a terminal.
Expand All @@ -104,6 +104,7 @@ func runRootCmd(cmd *cobra.Command, args []string) {
ForceColors: terminal.IsTerminal(int(os.Stderr.Fd())),
DisableTimestamp: true,
DisableLevelTruncation: true,
DisableQuote: true,
}))

if err != nil {
Expand Down

0 comments on commit de81d35

Please sign in to comment.