forked from toolshed/abra
		
	
		
			
				
	
	
		
			183 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    Copyright The containerd Authors.
 | |
| 
 | |
|    Licensed under the Apache License, Version 2.0 (the "License");
 | |
|    you may not use this file except in compliance with the License.
 | |
|    You may obtain a copy of the License at
 | |
| 
 | |
|        http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
|    Unless required by applicable law or agreed to in writing, software
 | |
|    distributed under the License is distributed on an "AS IS" BASIS,
 | |
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|    See the License for the specific language governing permissions and
 | |
|    limitations under the License.
 | |
| */
 | |
| 
 | |
| // Package log provides types and functions related to logging, passing
 | |
| // loggers through a context, and attaching context to the logger.
 | |
| //
 | |
| // # Transitional types
 | |
| //
 | |
| // This package contains various types that are aliases for types in [logrus].
 | |
| // These aliases are intended for transitioning away from hard-coding logrus
 | |
| // as logging implementation. Consumers of this package are encouraged to use
 | |
| // the type-aliases from this package instead of directly using their logrus
 | |
| // equivalent.
 | |
| //
 | |
| // The intent is to replace these aliases with locally defined types and
 | |
| // interfaces once all consumers are no longer directly importing logrus
 | |
| // types.
 | |
| //
 | |
| // IMPORTANT: due to the transitional purpose of this package, it is not
 | |
| // guaranteed for the full logrus API to be provided in the future. As
 | |
| // outlined, these aliases are provided as a step to transition away from
 | |
| // a specific implementation which, as a result, exposes the full logrus API.
 | |
| // While no decisions have been made on the ultimate design and interface
 | |
| // provided by this package, we do not expect carrying "less common" features.
 | |
| package log
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // G is a shorthand for [GetLogger].
 | |
| //
 | |
| // We may want to define this locally to a package to get package tagged log
 | |
| // messages.
 | |
| var G = GetLogger
 | |
| 
 | |
| // L is an alias for the standard logger.
 | |
| var L = &Entry{
 | |
| 	Logger: logrus.StandardLogger(),
 | |
| 	// Default is three fields plus a little extra room.
 | |
| 	Data: make(Fields, 6),
 | |
| }
 | |
| 
 | |
| type loggerKey struct{}
 | |
| 
 | |
| // Fields type to pass to "WithFields".
 | |
| type Fields = map[string]any
 | |
| 
 | |
| // Entry is a logging entry. It contains all the fields passed with
 | |
| // [Entry.WithFields]. It's finally logged when Trace, Debug, Info, Warn,
 | |
| // Error, Fatal or Panic is called on it. These objects can be reused and
 | |
| // passed around as much as you wish to avoid field duplication.
 | |
| //
 | |
| // Entry is a transitional type, and currently an alias for [logrus.Entry].
 | |
| type Entry = logrus.Entry
 | |
| 
 | |
| // RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using
 | |
| // zeros to ensure the formatted time is always the same number of
 | |
| // characters.
 | |
| const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
 | |
| 
 | |
| // Level is a logging level.
 | |
| type Level = logrus.Level
 | |
| 
 | |
| // Supported log levels.
 | |
| const (
 | |
| 	// TraceLevel level. Designates finer-grained informational events
 | |
| 	// than [DebugLevel].
 | |
| 	TraceLevel Level = logrus.TraceLevel
 | |
| 
 | |
| 	// DebugLevel level. Usually only enabled when debugging. Very verbose
 | |
| 	// logging.
 | |
| 	DebugLevel Level = logrus.DebugLevel
 | |
| 
 | |
| 	// InfoLevel level. General operational entries about what's going on
 | |
| 	// inside the application.
 | |
| 	InfoLevel Level = logrus.InfoLevel
 | |
| 
 | |
| 	// WarnLevel level. Non-critical entries that deserve eyes.
 | |
| 	WarnLevel Level = logrus.WarnLevel
 | |
| 
 | |
| 	// ErrorLevel level. Logs errors that should definitely be noted.
 | |
| 	// Commonly used for hooks to send errors to an error tracking service.
 | |
| 	ErrorLevel Level = logrus.ErrorLevel
 | |
| 
 | |
| 	// FatalLevel level. Logs and then calls "logger.Exit(1)". It exits
 | |
| 	// even if the logging level is set to Panic.
 | |
| 	FatalLevel Level = logrus.FatalLevel
 | |
| 
 | |
| 	// PanicLevel level. This is the highest level of severity. Logs and
 | |
| 	// then calls panic with the message passed to Debug, Info, ...
 | |
| 	PanicLevel Level = logrus.PanicLevel
 | |
| )
 | |
| 
 | |
| // SetLevel sets log level globally. It returns an error if the given
 | |
| // level is not supported.
 | |
| //
 | |
| // level can be one of:
 | |
| //
 | |
| //   - "trace" ([TraceLevel])
 | |
| //   - "debug" ([DebugLevel])
 | |
| //   - "info" ([InfoLevel])
 | |
| //   - "warn" ([WarnLevel])
 | |
| //   - "error" ([ErrorLevel])
 | |
| //   - "fatal" ([FatalLevel])
 | |
| //   - "panic" ([PanicLevel])
 | |
| func SetLevel(level string) error {
 | |
| 	lvl, err := logrus.ParseLevel(level)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	L.Logger.SetLevel(lvl)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // GetLevel returns the current log level.
 | |
| func GetLevel() Level {
 | |
| 	return L.Logger.GetLevel()
 | |
| }
 | |
| 
 | |
| // OutputFormat specifies a log output format.
 | |
| type OutputFormat string
 | |
| 
 | |
| // Supported log output formats.
 | |
| const (
 | |
| 	// TextFormat represents the text logging format.
 | |
| 	TextFormat OutputFormat = "text"
 | |
| 
 | |
| 	// JSONFormat represents the JSON logging format.
 | |
| 	JSONFormat OutputFormat = "json"
 | |
| )
 | |
| 
 | |
| // SetFormat sets the log output format ([TextFormat] or [JSONFormat]).
 | |
| func SetFormat(format OutputFormat) error {
 | |
| 	switch format {
 | |
| 	case TextFormat:
 | |
| 		L.Logger.SetFormatter(&logrus.TextFormatter{
 | |
| 			TimestampFormat: RFC3339NanoFixed,
 | |
| 			FullTimestamp:   true,
 | |
| 		})
 | |
| 		return nil
 | |
| 	case JSONFormat:
 | |
| 		L.Logger.SetFormatter(&logrus.JSONFormatter{
 | |
| 			TimestampFormat: RFC3339NanoFixed,
 | |
| 		})
 | |
| 		return nil
 | |
| 	default:
 | |
| 		return fmt.Errorf("unknown log format: %s", format)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WithLogger returns a new context with the provided logger. Use in
 | |
| // combination with logger.WithField(s) for great effect.
 | |
| func WithLogger(ctx context.Context, logger *Entry) context.Context {
 | |
| 	return context.WithValue(ctx, loggerKey{}, logger.WithContext(ctx))
 | |
| }
 | |
| 
 | |
| // GetLogger retrieves the current logger from the context. If no logger is
 | |
| // available, the default logger is returned.
 | |
| func GetLogger(ctx context.Context) *Entry {
 | |
| 	if logger := ctx.Value(loggerKey{}); logger != nil {
 | |
| 		return logger.(*Entry)
 | |
| 	}
 | |
| 	return L.WithContext(ctx)
 | |
| }
 |