github.hscsec.cn/openshift/source-to-image@v1.2.0/pkg/util/log/log.go (about)

     1  package log
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"strings"
     9  	"sync"
    10  
    11  	"k8s.io/klog"
    12  )
    13  
    14  // Logger is a simple interface that is roughly equivalent to klog.
    15  type Logger interface {
    16  	Is(level int32) bool
    17  	V(level int32) VerboseLogger
    18  	Infof(format string, args ...interface{})
    19  	Info(args ...interface{})
    20  	Warningf(format string, args ...interface{})
    21  	Warning(args ...interface{})
    22  	Errorf(format string, args ...interface{})
    23  	Error(args ...interface{})
    24  	Fatalf(format string, args ...interface{})
    25  	Fatal(args ...interface{})
    26  }
    27  
    28  // VerboseLogger is roughly equivalent to klog's Verbose.
    29  type VerboseLogger interface {
    30  	Infof(format string, args ...interface{})
    31  	Info(args ...interface{})
    32  }
    33  
    34  // ToFile creates a logger that will log any items at level or below to file, and defer
    35  // any other output to klog (no matter what the level is).
    36  func ToFile(x io.Writer, level int32) Logger {
    37  	return &FileLogger{
    38  		&sync.Mutex{},
    39  		bufio.NewWriter(x),
    40  		level,
    41  	}
    42  }
    43  
    44  var (
    45  	// None implements the Logger interface but does nothing with the log output.
    46  	None Logger = discard{}
    47  	// StderrLog implements the Logger interface for stderr.
    48  	StderrLog = ToFile(os.Stderr, 2)
    49  )
    50  
    51  // discard is a Logger that outputs nothing.
    52  type discard struct{}
    53  
    54  // Is returns whether the current logging level is greater than or equal to the parameter.
    55  func (discard) Is(level int32) bool {
    56  	return false
    57  }
    58  
    59  // V will returns a logger which will discard output if the specified level is greater than the current logging level.
    60  func (discarding discard) V(level int32) VerboseLogger {
    61  	return discarding
    62  }
    63  
    64  // Infof records an info log entry.
    65  func (discard) Infof(string, ...interface{}) {
    66  }
    67  
    68  // Info records an info log entry.
    69  func (discard) Info(...interface{}) {
    70  }
    71  
    72  // Errorf records an error log entry.
    73  func (discard) Errorf(string, ...interface{}) {
    74  }
    75  
    76  // Error records an error log entry.
    77  func (discard) Error(...interface{}) {
    78  }
    79  
    80  // Warningf records an warning log entry.
    81  func (discard) Warningf(string, ...interface{}) {
    82  }
    83  
    84  // Warning records an warning log entry.
    85  func (discard) Warning(...interface{}) {
    86  }
    87  
    88  // Fatalf records a fatal log entry.
    89  func (discard) Fatalf(string, ...interface{}) {
    90  }
    91  
    92  // Fatal records a fatal log entry.
    93  func (discard) Fatal(...interface{}) {
    94  }
    95  
    96  // FileLogger logs the provided messages at level or below to the writer, or delegates
    97  // to klog.
    98  type FileLogger struct {
    99  	mutex *sync.Mutex
   100  	w     *bufio.Writer
   101  	level int32
   102  }
   103  
   104  // Is returns whether the current logging level is greater than or equal to the parameter.
   105  func (f *FileLogger) Is(level int32) bool {
   106  	return level <= f.level
   107  }
   108  
   109  // V will returns a logger which will discard output if the specified level is greater than the current logging level.
   110  func (f *FileLogger) V(level int32) VerboseLogger {
   111  	// Is the loglevel set verbose enough to accept the forthcoming log statement
   112  	if klog.V(klog.Level(level)) {
   113  		return f
   114  	}
   115  	// Otherwise discard
   116  	return None
   117  }
   118  
   119  type severity int32
   120  
   121  const (
   122  	infoLog severity = iota
   123  	warningLog
   124  	errorLog
   125  	fatalLog
   126  )
   127  
   128  // Elevated logger methods output a detailed prefix for each logging statement.
   129  // At present, we delegate to klog to accomplish this.
   130  type elevated func(int, ...interface{})
   131  
   132  type severityDetail struct {
   133  	prefix     string
   134  	delegateFn elevated
   135  }
   136  
   137  var severities = []severityDetail{
   138  	infoLog:    {"", klog.InfoDepth},
   139  	warningLog: {"WARNING: ", klog.WarningDepth},
   140  	errorLog:   {"ERROR: ", klog.ErrorDepth},
   141  	fatalLog:   {"FATAL: ", klog.FatalDepth},
   142  }
   143  
   144  func (f *FileLogger) writeln(sev severity, line string) {
   145  	severity := severities[sev]
   146  
   147  	// If the loglevel has been elevated above this file logger's verbosity (generally set to 2)
   148  	// then delegate ALL messages to elevated logger in order to leverage its file/line/timestamp
   149  	// prefix information.
   150  	if klog.V(klog.Level(f.level + 1)) {
   151  		severity.delegateFn(3, line)
   152  	} else {
   153  		// buf.io is not threadsafe, so serialize access to the stream
   154  		f.mutex.Lock()
   155  		defer f.mutex.Unlock()
   156  		f.w.WriteString(severity.prefix)
   157  		f.w.WriteString(line)
   158  		if !strings.HasSuffix(line, "\n") {
   159  			f.w.WriteByte('\n')
   160  		}
   161  		f.w.Flush()
   162  	}
   163  }
   164  
   165  func (f *FileLogger) outputf(sev severity, format string, args ...interface{}) {
   166  	f.writeln(sev, fmt.Sprintf(format, args...))
   167  }
   168  
   169  func (f *FileLogger) output(sev severity, args ...interface{}) {
   170  	f.writeln(sev, fmt.Sprint(args...))
   171  }
   172  
   173  // Infof records an info log entry.
   174  func (f *FileLogger) Infof(format string, args ...interface{}) {
   175  	f.outputf(infoLog, format, args...)
   176  }
   177  
   178  // Info records an info log entry.
   179  func (f *FileLogger) Info(args ...interface{}) {
   180  	f.output(infoLog, args...)
   181  }
   182  
   183  // Warningf records an warning log entry.
   184  func (f *FileLogger) Warningf(format string, args ...interface{}) {
   185  	f.outputf(warningLog, format, args...)
   186  }
   187  
   188  // Warning records an warning log entry.
   189  func (f *FileLogger) Warning(args ...interface{}) {
   190  	f.output(warningLog, args...)
   191  }
   192  
   193  // Errorf records an error log entry.
   194  func (f *FileLogger) Errorf(format string, args ...interface{}) {
   195  	f.outputf(errorLog, format, args...)
   196  }
   197  
   198  // Error records an error log entry.
   199  func (f *FileLogger) Error(args ...interface{}) {
   200  	f.output(errorLog, args...)
   201  }
   202  
   203  // Fatalf records a fatal log entry and terminates the program.
   204  func (f *FileLogger) Fatalf(format string, args ...interface{}) {
   205  	defer os.Exit(1)
   206  	f.outputf(fatalLog, format, args...)
   207  }
   208  
   209  // Fatal records a fatal log entry and terminates the program.
   210  func (f *FileLogger) Fatal(args ...interface{}) {
   211  	defer os.Exit(1)
   212  	f.output(fatalLog, args...)
   213  }