...

Source file src/github.com/containerd/log/context.go

Documentation: github.com/containerd/log

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  // Package log provides types and functions related to logging, passing
    18  // loggers through a context, and attaching context to the logger.
    19  //
    20  // # Transitional types
    21  //
    22  // This package contains various types that are aliases for types in [logrus].
    23  // These aliases are intended for transitioning away from hard-coding logrus
    24  // as logging implementation. Consumers of this package are encouraged to use
    25  // the type-aliases from this package instead of directly using their logrus
    26  // equivalent.
    27  //
    28  // The intent is to replace these aliases with locally defined types and
    29  // interfaces once all consumers are no longer directly importing logrus
    30  // types.
    31  //
    32  // IMPORTANT: due to the transitional purpose of this package, it is not
    33  // guaranteed for the full logrus API to be provided in the future. As
    34  // outlined, these aliases are provided as a step to transition away from
    35  // a specific implementation which, as a result, exposes the full logrus API.
    36  // While no decisions have been made on the ultimate design and interface
    37  // provided by this package, we do not expect carrying "less common" features.
    38  package log
    39  
    40  import (
    41  	"context"
    42  	"fmt"
    43  
    44  	"github.com/sirupsen/logrus"
    45  )
    46  
    47  // G is a shorthand for [GetLogger].
    48  //
    49  // We may want to define this locally to a package to get package tagged log
    50  // messages.
    51  var G = GetLogger
    52  
    53  // L is an alias for the standard logger.
    54  var L = &Entry{
    55  	Logger: logrus.StandardLogger(),
    56  	// Default is three fields plus a little extra room.
    57  	Data: make(Fields, 6),
    58  }
    59  
    60  type loggerKey struct{}
    61  
    62  // Fields type to pass to "WithFields".
    63  type Fields = map[string]any
    64  
    65  // Entry is a logging entry. It contains all the fields passed with
    66  // [Entry.WithFields]. It's finally logged when Trace, Debug, Info, Warn,
    67  // Error, Fatal or Panic is called on it. These objects can be reused and
    68  // passed around as much as you wish to avoid field duplication.
    69  //
    70  // Entry is a transitional type, and currently an alias for [logrus.Entry].
    71  type Entry = logrus.Entry
    72  
    73  // RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using
    74  // zeros to ensure the formatted time is always the same number of
    75  // characters.
    76  const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
    77  
    78  // Level is a logging level.
    79  type Level = logrus.Level
    80  
    81  // Supported log levels.
    82  const (
    83  	// TraceLevel level. Designates finer-grained informational events
    84  	// than [DebugLevel].
    85  	TraceLevel Level = logrus.TraceLevel
    86  
    87  	// DebugLevel level. Usually only enabled when debugging. Very verbose
    88  	// logging.
    89  	DebugLevel Level = logrus.DebugLevel
    90  
    91  	// InfoLevel level. General operational entries about what's going on
    92  	// inside the application.
    93  	InfoLevel Level = logrus.InfoLevel
    94  
    95  	// WarnLevel level. Non-critical entries that deserve eyes.
    96  	WarnLevel Level = logrus.WarnLevel
    97  
    98  	// ErrorLevel level. Logs errors that should definitely be noted.
    99  	// Commonly used for hooks to send errors to an error tracking service.
   100  	ErrorLevel Level = logrus.ErrorLevel
   101  
   102  	// FatalLevel level. Logs and then calls "logger.Exit(1)". It exits
   103  	// even if the logging level is set to Panic.
   104  	FatalLevel Level = logrus.FatalLevel
   105  
   106  	// PanicLevel level. This is the highest level of severity. Logs and
   107  	// then calls panic with the message passed to Debug, Info, ...
   108  	PanicLevel Level = logrus.PanicLevel
   109  )
   110  
   111  // SetLevel sets log level globally. It returns an error if the given
   112  // level is not supported.
   113  //
   114  // level can be one of:
   115  //
   116  //   - "trace" ([TraceLevel])
   117  //   - "debug" ([DebugLevel])
   118  //   - "info" ([InfoLevel])
   119  //   - "warn" ([WarnLevel])
   120  //   - "error" ([ErrorLevel])
   121  //   - "fatal" ([FatalLevel])
   122  //   - "panic" ([PanicLevel])
   123  func SetLevel(level string) error {
   124  	lvl, err := logrus.ParseLevel(level)
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	L.Logger.SetLevel(lvl)
   130  	return nil
   131  }
   132  
   133  // GetLevel returns the current log level.
   134  func GetLevel() Level {
   135  	return L.Logger.GetLevel()
   136  }
   137  
   138  // OutputFormat specifies a log output format.
   139  type OutputFormat string
   140  
   141  // Supported log output formats.
   142  const (
   143  	// TextFormat represents the text logging format.
   144  	TextFormat OutputFormat = "text"
   145  
   146  	// JSONFormat represents the JSON logging format.
   147  	JSONFormat OutputFormat = "json"
   148  )
   149  
   150  // SetFormat sets the log output format ([TextFormat] or [JSONFormat]).
   151  func SetFormat(format OutputFormat) error {
   152  	switch format {
   153  	case TextFormat:
   154  		L.Logger.SetFormatter(&logrus.TextFormatter{
   155  			TimestampFormat: RFC3339NanoFixed,
   156  			FullTimestamp:   true,
   157  		})
   158  		return nil
   159  	case JSONFormat:
   160  		L.Logger.SetFormatter(&logrus.JSONFormatter{
   161  			TimestampFormat: RFC3339NanoFixed,
   162  		})
   163  		return nil
   164  	default:
   165  		return fmt.Errorf("unknown log format: %s", format)
   166  	}
   167  }
   168  
   169  // WithLogger returns a new context with the provided logger. Use in
   170  // combination with logger.WithField(s) for great effect.
   171  func WithLogger(ctx context.Context, logger *Entry) context.Context {
   172  	return context.WithValue(ctx, loggerKey{}, logger.WithContext(ctx))
   173  }
   174  
   175  // GetLogger retrieves the current logger from the context. If no logger is
   176  // available, the default logger is returned.
   177  func GetLogger(ctx context.Context) *Entry {
   178  	if logger := ctx.Value(loggerKey{}); logger != nil {
   179  		return logger.(*Entry)
   180  	}
   181  	return L.WithContext(ctx)
   182  }
   183  

View as plain text