github.com/grailbio/base@v0.0.11/log/log.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package log provides simple level logging. Log output is
     6  // implemented by an outputter, which by default outputs to Go's
     7  // logging package. Alternative implementations (e.g., vlog, glog)
     8  // can provide their own outputter implementation so that logging
     9  // output is unified.
    10  //
    11  // The package can be used as a replacement for Go's standard logging
    12  // package; the behavior of its toplevel functions are identical with
    13  // the default configuration.
    14  //
    15  // If the application wishes to configure logging levels by standard
    16  // flags, it should call log.AddFlags before flag.Parse.
    17  // log.AddFlags.
    18  //
    19  // Note that this package is intended to bridge Go's standard log
    20  // package with Vanadium's (vlog). As we transition away from vlog,
    21  // we can simplify this package by removing the Outputter interface.
    22  package log
    23  
    24  import (
    25  	"fmt"
    26  	"os"
    27  )
    28  
    29  // An Outputter provides a destination for leveled log output.
    30  type Outputter interface {
    31  	// Level returns the level at which the outputter is accepting
    32  	// messages.
    33  	Level() Level
    34  
    35  	// Output writes the provided message to the outputter at the
    36  	// provided calldepth and level. The message is dropped by
    37  	// the outputter if it is not logging at the desired level.
    38  	Output(calldepth int, level Level, s string) error
    39  }
    40  
    41  var out Outputter = gologOutputter{}
    42  
    43  // SetOutputter provides a new outputter for use in the log package.
    44  // SetOutputter should not be called concurrently with any log
    45  // output, and is thus suitable to be called only upon program
    46  // initialization. SetOutputter returns the old outputter.
    47  func SetOutputter(newOut Outputter) Outputter {
    48  	old := out
    49  	out = newOut
    50  	return old
    51  }
    52  
    53  // GetOutputter returns the current outputter used by the log package.
    54  func GetOutputter() Outputter {
    55  	return out
    56  }
    57  
    58  // At returns whether the logger is currently logging at the provided level.
    59  func At(level Level) bool {
    60  	return level <= out.Level()
    61  }
    62  
    63  // Output outputs a log message to the current outputter at the provided
    64  // level and call depth.
    65  func Output(calldepth int, level Level, s string) error {
    66  	return out.Output(calldepth+1, level, s)
    67  }
    68  
    69  // A Level is a log verbosity level. Increasing levels decrease in
    70  // priority and (usually) increase in verbosity: if the outputter is
    71  // logging at level L, then all messages with level M <= L are
    72  // outputted.
    73  type Level int
    74  
    75  const (
    76  	// Off never outputs messages.
    77  	Off = Level(-3)
    78  	// Error outputs error messages.
    79  	Error = Level(-2)
    80  	// Info outputs informational messages. This is the standard
    81  	// logging level.
    82  	Info = Level(0)
    83  	// Debug outputs messages intended for debugging and development,
    84  	// not for regular users.
    85  	Debug = Level(1)
    86  )
    87  
    88  // String returns the string representation of the level l.
    89  func (l Level) String() string {
    90  	switch l {
    91  	case Off:
    92  		return "off"
    93  	case Error:
    94  		return "error"
    95  	case Info:
    96  		return "info"
    97  	case Debug:
    98  		return "debug"
    99  	default:
   100  		if l < 0 {
   101  			panic("invalid log level")
   102  		}
   103  		return fmt.Sprintf("debug%d", l)
   104  	}
   105  }
   106  
   107  // Print formats a message in the manner of fmt.Sprint and outputs it
   108  // at level l to the current outputter.
   109  func (l Level) Print(v ...interface{}) {
   110  	if At(l) {
   111  		_ = out.Output(2, l, fmt.Sprint(v...))
   112  	}
   113  }
   114  
   115  // Printkln formats a message in the manner of fmt.Sprintln and outputs
   116  // it at level l to the current outputter.
   117  func (l Level) Println(v ...interface{}) {
   118  	if At(l) {
   119  		_ = out.Output(2, l, fmt.Sprintln(v...))
   120  	}
   121  }
   122  
   123  // Printf formats a message in the manner of fmt.Sprintf and outputs
   124  // it at level l to the current outputter.
   125  func (l Level) Printf(format string, v ...interface{}) {
   126  	if At(l) {
   127  		_ = out.Output(2, l, fmt.Sprintf(format, v...))
   128  	}
   129  }
   130  
   131  // Print formats a message in the manner of fmt.Sprint
   132  // and outputs it at the Info level to the current outputter.
   133  func Print(v ...interface{}) {
   134  	if At(Info) {
   135  		_ = out.Output(2, Info, fmt.Sprint(v...))
   136  	}
   137  }
   138  
   139  // Printf formats a message in the manner of fmt.Sprintf
   140  // and outputs it at the Info level to the current outputter.
   141  func Printf(format string, v ...interface{}) {
   142  	if At(Info) {
   143  		_ = out.Output(2, Info, fmt.Sprintf(format, v...))
   144  	}
   145  }
   146  
   147  // Errorf formats a message in the manner of fmt.Sprintf
   148  // and outputs it at the Error level to the current outputter.
   149  func Errorf(format string, v ...interface{}) {
   150  	_ = out.Output(2, Error, fmt.Sprintf(format, v...))
   151  }
   152  
   153  // Fatal formats a message in the manner of fmt.Sprint, outputs it at
   154  // the error level to the current outputter and then calls
   155  // os.Exit(1).
   156  func Fatal(v ...interface{}) {
   157  	_ = out.Output(2, Error, fmt.Sprint(v...))
   158  	os.Exit(1)
   159  }
   160  
   161  // Fatalf formats a message in the manner of fmt.Sprintf, outputs it at
   162  // the error level to the current outputter and then calls
   163  // os.Exit(1).
   164  func Fatalf(format string, v ...interface{}) {
   165  	_ = out.Output(2, Error, fmt.Sprintf(format, v...))
   166  	os.Exit(1)
   167  }
   168  
   169  // Panic formats a message in the manner of fmt.Sprint, outputs it
   170  // at the error level to the current outputter and then panics.
   171  func Panic(v ...interface{}) {
   172  	s := fmt.Sprint(v...)
   173  	_ = out.Output(2, Error, s)
   174  	panic(s)
   175  }
   176  
   177  // Panicf formats a message in the manner of fmt.Sprintf, outputs it
   178  // at the error level to the current outputter and then panics.
   179  func Panicf(format string, v ...interface{}) {
   180  	s := fmt.Sprintf(format, v...)
   181  	_ = out.Output(2, Error, s)
   182  	panic(s)
   183  }
   184  
   185  // Outputf is formats a message using fmt.Sprintf and outputs it
   186  // to the provided logger at the provided level.
   187  func Outputf(out Outputter, level Level, format string, v ...interface{}) {
   188  	_ = out.Output(2, level, fmt.Sprintf(format, v...))
   189  }