github.com/lyft/flytestdlib@v0.3.12-0.20210213045714-8cdd111ecda1/logger/logger.go (about)

     1  // Defines global context-aware logger.
     2  // The default implementation uses logrus. This package registers "logger" config section on init(). The structure of the
     3  // config section is expected to be un-marshal-able to Config struct.
     4  package logger
     5  
     6  import (
     7  	"context"
     8  	"io"
     9  
    10  	"github.com/lyft/flytestdlib/contextutils"
    11  
    12  	"fmt"
    13  	"runtime"
    14  	"strings"
    15  
    16  	"github.com/sirupsen/logrus"
    17  )
    18  
    19  const (
    20  	indentLevelKey contextutils.Key = "LoggerIndentLevel"
    21  	sourceCodeKey  string           = "src"
    22  )
    23  
    24  var noopLogger = NoopLogger{}
    25  
    26  func onConfigUpdated(cfg Config) {
    27  	logrus.SetLevel(logrus.Level(cfg.Level))
    28  
    29  	switch cfg.Formatter.Type {
    30  	case FormatterText:
    31  		if _, isText := logrus.StandardLogger().Formatter.(*logrus.JSONFormatter); !isText {
    32  			logrus.SetFormatter(&logrus.TextFormatter{
    33  				FieldMap: logrus.FieldMap{
    34  					logrus.FieldKeyTime: "ts",
    35  				},
    36  			})
    37  		}
    38  	default:
    39  		if _, isJSON := logrus.StandardLogger().Formatter.(*logrus.JSONFormatter); !isJSON {
    40  			logrus.SetFormatter(&logrus.JSONFormatter{
    41  				DataKey: jsonDataKey,
    42  				FieldMap: logrus.FieldMap{
    43  					logrus.FieldKeyTime: "ts",
    44  				},
    45  			})
    46  		}
    47  	}
    48  }
    49  
    50  func getSourceLocation() string {
    51  	// The reason we pass 3 here: 0 means this function (getSourceLocation), 1 means the getLogger function (only caller
    52  	// to getSourceLocation, 2 means the logging function (e.g. Debugln), and 3 means the caller for the logging function.
    53  	_, file, line, ok := runtime.Caller(3)
    54  	if !ok {
    55  		file = "???"
    56  		line = 1
    57  	} else {
    58  		slash := strings.LastIndex(file, "/")
    59  		if slash >= 0 {
    60  			file = file[slash+1:]
    61  		}
    62  	}
    63  
    64  	return fmt.Sprintf("%v:%v", file, line)
    65  }
    66  
    67  func getLogger(ctx context.Context) logrus.FieldLogger {
    68  	cfg := GetConfig()
    69  	if cfg.Mute {
    70  		return noopLogger
    71  	}
    72  
    73  	entry := logrus.WithFields(logrus.Fields(contextutils.GetLogFields(ctx)))
    74  	if cfg.IncludeSourceCode {
    75  		entry = entry.WithField(sourceCodeKey, getSourceLocation())
    76  	}
    77  
    78  	entry.Level = logrus.Level(cfg.Level)
    79  
    80  	return entry
    81  }
    82  
    83  // Returns a standard io.PipeWriter that logs using the same logger configurations in this package.
    84  func GetLogWriter(ctx context.Context) *io.PipeWriter {
    85  	logger := getLogger(ctx)
    86  	return logger.(*logrus.Entry).Writer()
    87  }
    88  
    89  func WithIndent(ctx context.Context, additionalIndent string) context.Context {
    90  	indentLevel := getIndent(ctx) + additionalIndent
    91  	return context.WithValue(ctx, indentLevelKey, indentLevel)
    92  }
    93  
    94  func getIndent(ctx context.Context) string {
    95  	if existing := ctx.Value(indentLevelKey); existing != nil {
    96  		return existing.(string)
    97  	}
    98  
    99  	return ""
   100  }
   101  
   102  // Gets a value indicating whether logs at this level will be written to the logger. This is particularly useful to avoid
   103  // computing log messages unnecessarily.
   104  func IsLoggable(_ context.Context, level Level) bool {
   105  	return GetConfig().Level >= level
   106  }
   107  
   108  // Debug logs a message at level Debug on the standard logger.
   109  func Debug(ctx context.Context, args ...interface{}) {
   110  	getLogger(ctx).Debug(args...)
   111  }
   112  
   113  // Print logs a message at level Info on the standard logger.
   114  func Print(ctx context.Context, args ...interface{}) {
   115  	getLogger(ctx).Print(args...)
   116  }
   117  
   118  // Info logs a message at level Info on the standard logger.
   119  func Info(ctx context.Context, args ...interface{}) {
   120  	getLogger(ctx).Info(args...)
   121  }
   122  
   123  // Warn logs a message at level Warn on the standard logger.
   124  func Warn(ctx context.Context, args ...interface{}) {
   125  	getLogger(ctx).Warn(args...)
   126  }
   127  
   128  // Warning logs a message at level Warn on the standard logger.
   129  func Warning(ctx context.Context, args ...interface{}) {
   130  	getLogger(ctx).Warning(args...)
   131  }
   132  
   133  // Error logs a message at level Error on the standard logger.
   134  func Error(ctx context.Context, args ...interface{}) {
   135  	getLogger(ctx).Error(args...)
   136  }
   137  
   138  // Panic logs a message at level Panic on the standard logger.
   139  func Panic(ctx context.Context, args ...interface{}) {
   140  	getLogger(ctx).Panic(args...)
   141  }
   142  
   143  // Fatal logs a message at level Fatal on the standard logger.
   144  func Fatal(ctx context.Context, args ...interface{}) {
   145  	getLogger(ctx).Fatal(args...)
   146  }
   147  
   148  // Debugf logs a message at level Debug on the standard logger.
   149  func Debugf(ctx context.Context, format string, args ...interface{}) {
   150  	getLogger(ctx).Debugf(format, args...)
   151  }
   152  
   153  // Printf logs a message at level Info on the standard logger.
   154  func Printf(ctx context.Context, format string, args ...interface{}) {
   155  	getLogger(ctx).Printf(format, args...)
   156  }
   157  
   158  // Infof logs a message at level Info on the standard logger.
   159  func Infof(ctx context.Context, format string, args ...interface{}) {
   160  	getLogger(ctx).Infof(format, args...)
   161  }
   162  
   163  // InfofNoCtx logs a formatted message without context.
   164  func InfofNoCtx(format string, args ...interface{}) {
   165  	getLogger(context.TODO()).Infof(format, args...)
   166  }
   167  
   168  // Warnf logs a message at level Warn on the standard logger.
   169  func Warnf(ctx context.Context, format string, args ...interface{}) {
   170  	getLogger(ctx).Warnf(format, args...)
   171  }
   172  
   173  // Warningf logs a message at level Warn on the standard logger.
   174  func Warningf(ctx context.Context, format string, args ...interface{}) {
   175  	getLogger(ctx).Warningf(format, args...)
   176  }
   177  
   178  // Errorf logs a message at level Error on the standard logger.
   179  func Errorf(ctx context.Context, format string, args ...interface{}) {
   180  	getLogger(ctx).Errorf(format, args...)
   181  }
   182  
   183  // Panicf logs a message at level Panic on the standard logger.
   184  func Panicf(ctx context.Context, format string, args ...interface{}) {
   185  	getLogger(ctx).Panicf(format, args...)
   186  }
   187  
   188  // Fatalf logs a message at level Fatal on the standard logger.
   189  func Fatalf(ctx context.Context, format string, args ...interface{}) {
   190  	getLogger(ctx).Fatalf(format, args...)
   191  }
   192  
   193  // Debugln logs a message at level Debug on the standard logger.
   194  func Debugln(ctx context.Context, args ...interface{}) {
   195  	getLogger(ctx).Debugln(args...)
   196  }
   197  
   198  // Println logs a message at level Info on the standard logger.
   199  func Println(ctx context.Context, args ...interface{}) {
   200  	getLogger(ctx).Println(args...)
   201  }
   202  
   203  // Infoln logs a message at level Info on the standard logger.
   204  func Infoln(ctx context.Context, args ...interface{}) {
   205  	getLogger(ctx).Infoln(args...)
   206  }
   207  
   208  // Warnln logs a message at level Warn on the standard logger.
   209  func Warnln(ctx context.Context, args ...interface{}) {
   210  	getLogger(ctx).Warnln(args...)
   211  }
   212  
   213  // Warningln logs a message at level Warn on the standard logger.
   214  func Warningln(ctx context.Context, args ...interface{}) {
   215  	getLogger(ctx).Warningln(args...)
   216  }
   217  
   218  // Errorln logs a message at level Error on the standard logger.
   219  func Errorln(ctx context.Context, args ...interface{}) {
   220  	getLogger(ctx).Errorln(args...)
   221  }
   222  
   223  // Panicln logs a message at level Panic on the standard logger.
   224  func Panicln(ctx context.Context, args ...interface{}) {
   225  	getLogger(ctx).Panicln(args...)
   226  }
   227  
   228  // Fatalln logs a message at level Fatal on the standard logger.
   229  func Fatalln(ctx context.Context, args ...interface{}) {
   230  	getLogger(ctx).Fatalln(args...)
   231  }
   232  
   233  type NoopLogger struct {
   234  }
   235  
   236  func (NoopLogger) WithField(key string, value interface{}) *logrus.Entry {
   237  	return nil
   238  }
   239  
   240  func (NoopLogger) WithFields(fields logrus.Fields) *logrus.Entry {
   241  	return nil
   242  }
   243  
   244  func (NoopLogger) WithError(err error) *logrus.Entry {
   245  	return nil
   246  }
   247  
   248  func (NoopLogger) Debugf(format string, args ...interface{}) {
   249  }
   250  
   251  func (NoopLogger) Infof(format string, args ...interface{}) {
   252  }
   253  
   254  func (NoopLogger) Warnf(format string, args ...interface{}) {
   255  }
   256  
   257  func (NoopLogger) Warningf(format string, args ...interface{}) {
   258  }
   259  
   260  func (NoopLogger) Errorf(format string, args ...interface{}) {
   261  }
   262  
   263  func (NoopLogger) Debug(args ...interface{}) {
   264  }
   265  
   266  func (NoopLogger) Info(args ...interface{}) {
   267  }
   268  
   269  func (NoopLogger) Warn(args ...interface{}) {
   270  }
   271  
   272  func (NoopLogger) Warning(args ...interface{}) {
   273  }
   274  
   275  func (NoopLogger) Error(args ...interface{}) {
   276  }
   277  
   278  func (NoopLogger) Debugln(args ...interface{}) {
   279  }
   280  
   281  func (NoopLogger) Infoln(args ...interface{}) {
   282  }
   283  
   284  func (NoopLogger) Warnln(args ...interface{}) {
   285  }
   286  
   287  func (NoopLogger) Warningln(args ...interface{}) {
   288  }
   289  
   290  func (NoopLogger) Errorln(args ...interface{}) {
   291  }
   292  
   293  func (NoopLogger) Print(...interface{}) {
   294  }
   295  
   296  func (NoopLogger) Printf(string, ...interface{}) {
   297  }
   298  
   299  func (NoopLogger) Println(...interface{}) {
   300  }
   301  
   302  func (NoopLogger) Fatal(...interface{}) {
   303  }
   304  
   305  func (NoopLogger) Fatalf(string, ...interface{}) {
   306  }
   307  
   308  func (NoopLogger) Fatalln(...interface{}) {
   309  }
   310  
   311  func (NoopLogger) Panic(...interface{}) {
   312  }
   313  
   314  func (NoopLogger) Panicf(string, ...interface{}) {
   315  }
   316  
   317  func (NoopLogger) Panicln(...interface{}) {
   318  }