github.com/openshift/installer@v1.4.17/cmd/openshift-install/command/log.go (about)

     1  package command
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/pkg/errors"
    10  	"github.com/sirupsen/logrus"
    11  
    12  	"github.com/openshift/installer/pkg/version"
    13  )
    14  
    15  var (
    16  	// RootOpts holds the log directory and log level configuration.
    17  	RootOpts struct {
    18  		Dir      string
    19  		LogLevel string
    20  	}
    21  )
    22  
    23  type fileHook struct {
    24  	file      io.Writer
    25  	formatter logrus.Formatter
    26  	level     logrus.Level
    27  
    28  	truncateAtNewLine bool
    29  }
    30  
    31  func newFileHook(file io.Writer, level logrus.Level, formatter logrus.Formatter) *fileHook {
    32  	return &fileHook{
    33  		file:      file,
    34  		formatter: formatter,
    35  		level:     level,
    36  	}
    37  }
    38  
    39  // NewFileHookWithNewlineTruncate returns a new FileHook with truncated new lines.
    40  func NewFileHookWithNewlineTruncate(file io.Writer, level logrus.Level, formatter logrus.Formatter) *fileHook {
    41  	f := newFileHook(file, level, formatter)
    42  	f.truncateAtNewLine = true
    43  	return f
    44  }
    45  
    46  func (h fileHook) Levels() []logrus.Level {
    47  	var levels []logrus.Level
    48  	for _, level := range logrus.AllLevels {
    49  		if level <= h.level {
    50  			levels = append(levels, level)
    51  		}
    52  	}
    53  
    54  	return levels
    55  }
    56  
    57  func (h *fileHook) Fire(entry *logrus.Entry) error {
    58  	// logrus reuses the same entry for each invocation of hooks.
    59  	// so we need to make sure we leave them message field as we received.
    60  	orig := entry.Message
    61  	defer func() { entry.Message = orig }()
    62  
    63  	msgs := []string{orig}
    64  	if h.truncateAtNewLine {
    65  		msgs = strings.Split(orig, "\n")
    66  	}
    67  
    68  	for _, msg := range msgs {
    69  		// this makes it easier to call format on entry
    70  		// easy without creating a new one for each split message.
    71  		entry.Message = msg
    72  		line, err := h.formatter.Format(entry)
    73  		if err != nil {
    74  			return err
    75  		}
    76  
    77  		if _, err := h.file.Write(line); err != nil {
    78  			return err
    79  		}
    80  	}
    81  
    82  	return nil
    83  }
    84  
    85  // SetupFileHook creates the base log directory and configures logrus options.
    86  func SetupFileHook(baseDir string) func() {
    87  	if err := os.MkdirAll(baseDir, 0755); err != nil {
    88  		logrus.Fatal(errors.Wrap(err, "failed to create base directory for logs"))
    89  	}
    90  
    91  	logfile, err := os.OpenFile(filepath.Join(baseDir, ".openshift_install.log"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
    92  	if err != nil {
    93  		logrus.Fatal(errors.Wrap(err, "failed to open log file"))
    94  	}
    95  
    96  	originalHooks := logrus.LevelHooks{}
    97  	for k, v := range logrus.StandardLogger().Hooks {
    98  		originalHooks[k] = v
    99  	}
   100  	logrus.AddHook(newFileHook(logfile, logrus.TraceLevel, &logrus.TextFormatter{
   101  		DisableColors:          true,
   102  		DisableTimestamp:       false,
   103  		FullTimestamp:          true,
   104  		DisableLevelTruncation: false,
   105  	}))
   106  
   107  	versionString, err := version.String()
   108  	if err != nil {
   109  		logrus.Fatal(err)
   110  	}
   111  	logrus.Debugf(versionString)
   112  	if version.Commit != "" {
   113  		logrus.Debugf("Built from commit %s", version.Commit)
   114  	}
   115  
   116  	return func() {
   117  		logfile.Close()
   118  		logrus.StandardLogger().ReplaceHooks(originalHooks)
   119  	}
   120  }