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)
 | 
						|
}
 |