mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-30 19:54:28 +01:00
latest agent version requires logrus v1.4.2 shortlog: 839c75f Release 1.4.2 744fc4c fix build break for plan9 f2849a8 add full cross compilation in travis (#963) 1bc909a Add a checkTerminal for nacl to support running on play.golang.org 1a601d2 remove go 1.10 from ci build matrix 5521996 Update x/sys/unix to fix AIX support c1b6154 Fix solaris build 8bdbc7b Release 1.4.1 6c615e1 remove field if val is empty string for func and file field in text formatter ede5b63 Make isTerminal un-exported 3e06420 Move files to main directory 38bc297 return new entry for Entry.WithContext 7d700cd Test more platforms c49ef1d Move terminal package 5d8c3bf Updated travis.yml 41ee4dd Moved moved unix-related parts into terminal 7de3dd8 Removed golang.org/x/crypto refs 10ff0d0 Got rid of IsTerminal call to reduce external dependencies c076594 Add Go 1.12 to Travis CI build matrix 02141df Add CHANGELOG for v1.4.0 68e41f6 Add WithContext cf1b9fd fix sync.Once usage instead of adding a mutex lock b9d4514 fix ReportCaller race condition 99a5172 Add and example for CallerPrettyfier 5c2b39a Remove debug trace ffec2f2 Add a CallerPrettyfier callback to the text formatter 5e9b246 Add a CallerPrettyfier callback to the json formatter 4f5fd63 Fix infinite recursion on unknown Level.String() c4e4882 prevent string formatting in Entry.Logf when log level is not enabled 774bb8e Fix error formatting based on best practices from Code Review Comments 4ea4861 Add a DeferExitHandler function 68a2b57 Add nested-logrus-formatter to README.md f61e48b logger: fix wrong callback method 0f544bf Add a unit test to ensure hook are called in their registration order a99ca47 Add an example hook which adds default fields 78fb385 Remove unused variables in TextFormatter eef6b76 Update Changelog for 1.3.0 bd9534b Test Log e8fd0ba Remove sensitivity to file line changes ff695da Implement TextUnmarshaller interface for Level type a6668e7 Add Generic Log functions with level via argument 9abefb9 do not clear error formatting informative field d962013 respect ForceColor and environment variables over OS check 08e8d65 Skip func pointer type value in fields 0c5e33c Travis: fix checkout dir to help contributors run Travis on their fork f1b98e4 ignore expected color on windows e902658 Disable colored output on windows entirely eab2c44 fix hook example c7183bf fix missing parameter 2cafb78 fix race condition caused by writing to entry.Data, using the same technique as JSONFormatter bcd833d v1.2.0 changelog d10c2f9 fix panic in text formatter 5a78c38 make file name comparison os independant d2654b7 add file and line number in output when report caller is enabled fa01b53 move test functions and test utils functions in their own package ec57031 store a runtime.Frame in Entry instead of the caller function name 975c406 Use a sync.Once to init the reportCaller data 5fcd19e add a SetReportCaller on Logger object 0c52582 Add GELF to third party formatters 5c1f2cd Make logrus.Level implement encoding.TextUnmarshaler bb98c6c Fix the version of windows coloring library dependency ed3ffa0 PR#844: Added Trace to TestLogLevelEnabled() (requested by @dgsb) b54cafe Addresses @stevvooe's backward compatibility concerns. ef9d84e Added trace log level. c7a33dc Add Trace level logging 4981d81 Added TRACE level logging. 9c7692c disable colors on hook example f2ab87f Add an example for tracing global variable with hook ff92509 Attempt to fix build break on aix a13c5db Fix typo in comment 4346c76 Remove unnecessary wrapper function on `os.Exit` 99bc300 Add a method Exit on Logger that calls `os.Exit` or alternate exit function. ad15b42 Update changelog for v1.1.1 release 3f90cee Rationalize os specific build constraints 2be6202 Add option to panic in `test.NewNullLogger` to allow testing of calls to `Fatal*` 7b467df Skip func type value in fields. a67f783 Update changelog for v1.1.0 release 73bc94e Add custom sorting function in text formatter 5a88d3c Add missing module dependency for windows build 629982b DisableColors in two tests to fix AppEngine configuration 0a8fc8d Add AppEngine test configurations to travis to a void regression f1ce1ba Fix copypasta 90501cf Fix AppEngine builds 98c898c Fix gopherjs build constraint name eed7c22 Fix travis build for go 1.11 with modules 66895ce Fix module name and remove unused dependencies 88eb166 Fix spelling in Entry.Buffer comment f75951b Add go module support 4bcb47b commit to trigger appveyor build 8b12043 Fix example build on windows 7556e24 Use syslog instead of airbrake as syslog example e58aa84 bump go toolchain version in travis 98d0f31 Add previously forgotten v1.0.6 description in changelog 90bf2e7 feat(LogLevel): taking in account code review from David Bariod 13d10d8 return old hooks from RelplaceHooks 7a0120e logger.ReplaceHooks b5e6fae Cleanup on unit test on isColored cadf2ce Add unit test for TextFormatter.isColored eb968b6 Fix for CLICOLOR_FORCE handling 8a6a17c Fixed missing brace after wrong merge d950ecd Remove unnecessary text_formatter file da39da2 Keep terminal check naming convention 37d651c Add CLICOLOR support 179037f Ensure a new entry data fields are empty d316277 Add logger benchmark 54db2bb limit the build/test matrix to the two latest stable version 6999e59 properly fix the hooks race test 725f3be Adds WithTime to Logger and Entry types, as well as a pure module-level function. 52b92f5 Allows overriding Entry.Time. fc9bbf2 [#241] Allow to set writer during logger usage. eed1c0f Fix GopherJS build tags 2ce6c0c Support for Entry data under nested JSON dictionary. 6b28c2c error message 5d60369 Fixed prefixFieldClashes for TextFormatter and added coverage 4225d69 feat: new methods to check enabled log level 070c81d Revert the change introduced in #707 and do the proper fix. Fixes #729 098a5a7 Move the hook services list to a wiki page caed59e Fix Logger.WithField doscription aa6766a PERF: use buffer pool in json formatter b1e82be Update go versions in travis configuration. 8369e2f Fix a race condition in TestLoggingWithHooksRace 507c822 add mysql hook e63a8df added Anexia CloudLog to list of hooks 5513c60 Improve documentation for Fatal* class functions 2f58bc8 Unified terminal initialization code handling 9bc59a5 Fixed initTerminal() was run for non-terminals cf5eba7 Simplified file structure c9a46a1 Added terminal check on Windows 7d2a521 Extended conditions to include non-native builds f142d81 Improved building of non-windows code bb487e0 Added support for text coloring on Windows 10 19b9c9e delete dead link b537da5 Fix run-on sentence 723dd3c changed prettyprinting to use spaces as opposed to /t c155da1 changelog: add 1.0.5 91b159d Add Kafka REST Proxy hook to README c840e59 add gopherjs build tag 1893e9a Fixed: comment f4118d2 reamde: add logrus-clickhouse-hook efab7f3 Have prefixFieldClashes respect the JSON FieldMap be56909 Make fireHooks() method receive a copy of Entry structure to avoid race conditions 178041e Fix typo in README.md 828a649 rename fieldLogger to entry eeb6535 Lock mutex before formatting to avoid race efbfdb5 Add failing test for using a FieldLogger with hooks inside goroutines 0cf9f0b Made text consistent with other hooks 516f6c1 Add Application Insights hook to README 977e033 Fix deadlock on panics at Entry.log 92aece5 TextFormatter behaviour aligned with stdlib log (fixes #167) eb15690 remove .gitignore changes and update AddHook 20cc8e2 remove .gitignore changes 0c03a05 mirror and wrap Logger instance methods in exported.go d682213 changelog: 1.0.4 b9eceae fix example bf1fb70 Add FieldMap support to TestFormatter 73a1342 Fix typo in README.md 10d6a5b removed useless line from readme 639325f added pretty print option for json logs 9700beb Update README.md 1858a85 Adds `logbeat` hook to README c44d524 Fix typo in docstring 4844e58 Add promrus to list of hooks. 7d3ddc6 Split terminal check to add build tags to support App Engine. e3d1776 MD formatting 9ce1c9e add github path to log message in readme b1db1b9 regex assertion rather than literal, for github path 3cb9e18 test updates bc6d984 add caller logic to DisableTimestamp case 1f59c9a Add DisableLevelTruncation description to README 88dd8df responses to code review d8fd234 add syntax hilighting to new example blocks 2e7c40e README formatting tweak 802fba1 add note on caller-reporting overhead to README 306956c tweak timing tests to handle slower VMs and older GoLang 65f3af3 simplify hasCaller check a5c845c responses to review comments 4575b7a revert slight added complexity in NewEntry() 05a8f4d fix test description 348bace doc updates, and relabel ReportMethod 1e21450 push compilation even higher, to reduce to one call 8161d93 performance: precompile regex before iterating 473c344 Add README notes and CHANGELOG entries 93af604 First cut at adding calling method e5b6713 Added testing for DisableLevelTruncation 7a1f601 Added ability to disable level text truncation. Fixes #406 Signed-off-by: Julio Montes <julio.montes@intel.com>
408 lines
10 KiB
Go
408 lines
10 KiB
Go
package logrus
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
bufferPool *sync.Pool
|
|
|
|
// qualified package name, cached at first use
|
|
logrusPackage string
|
|
|
|
// Positions in the call stack when tracing to report the calling method
|
|
minimumCallerDepth int
|
|
|
|
// Used for caller information initialisation
|
|
callerInitOnce sync.Once
|
|
)
|
|
|
|
const (
|
|
maximumCallerDepth int = 25
|
|
knownLogrusFrames int = 4
|
|
)
|
|
|
|
func init() {
|
|
bufferPool = &sync.Pool{
|
|
New: func() interface{} {
|
|
return new(bytes.Buffer)
|
|
},
|
|
}
|
|
|
|
// start at the bottom of the stack before the package-name cache is primed
|
|
minimumCallerDepth = 1
|
|
}
|
|
|
|
// Defines the key when adding errors using WithError.
|
|
var ErrorKey = "error"
|
|
|
|
// An entry is the final or intermediate Logrus logging entry. It contains all
|
|
// the fields passed with WithField{,s}. 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.
|
|
type Entry struct {
|
|
Logger *Logger
|
|
|
|
// Contains all the fields set by the user.
|
|
Data Fields
|
|
|
|
// Time at which the log entry was created
|
|
Time time.Time
|
|
|
|
// Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
|
|
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
|
|
Level Level
|
|
|
|
// Calling method, with package name
|
|
Caller *runtime.Frame
|
|
|
|
// Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
|
|
Message string
|
|
|
|
// When formatter is called in entry.log(), a Buffer may be set to entry
|
|
Buffer *bytes.Buffer
|
|
|
|
// Contains the context set by the user. Useful for hook processing etc.
|
|
Context context.Context
|
|
|
|
// err may contain a field formatting error
|
|
err string
|
|
}
|
|
|
|
func NewEntry(logger *Logger) *Entry {
|
|
return &Entry{
|
|
Logger: logger,
|
|
// Default is three fields, plus one optional. Give a little extra room.
|
|
Data: make(Fields, 6),
|
|
}
|
|
}
|
|
|
|
// Returns the string representation from the reader and ultimately the
|
|
// formatter.
|
|
func (entry *Entry) String() (string, error) {
|
|
serialized, err := entry.Logger.Formatter.Format(entry)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
str := string(serialized)
|
|
return str, nil
|
|
}
|
|
|
|
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
|
|
func (entry *Entry) WithError(err error) *Entry {
|
|
return entry.WithField(ErrorKey, err)
|
|
}
|
|
|
|
// Add a context to the Entry.
|
|
func (entry *Entry) WithContext(ctx context.Context) *Entry {
|
|
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: entry.Time, err: entry.err, Context: ctx}
|
|
}
|
|
|
|
// Add a single field to the Entry.
|
|
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
|
return entry.WithFields(Fields{key: value})
|
|
}
|
|
|
|
// Add a map of fields to the Entry.
|
|
func (entry *Entry) WithFields(fields Fields) *Entry {
|
|
data := make(Fields, len(entry.Data)+len(fields))
|
|
for k, v := range entry.Data {
|
|
data[k] = v
|
|
}
|
|
fieldErr := entry.err
|
|
for k, v := range fields {
|
|
isErrField := false
|
|
if t := reflect.TypeOf(v); t != nil {
|
|
switch t.Kind() {
|
|
case reflect.Func:
|
|
isErrField = true
|
|
case reflect.Ptr:
|
|
isErrField = t.Elem().Kind() == reflect.Func
|
|
}
|
|
}
|
|
if isErrField {
|
|
tmp := fmt.Sprintf("can not add field %q", k)
|
|
if fieldErr != "" {
|
|
fieldErr = entry.err + ", " + tmp
|
|
} else {
|
|
fieldErr = tmp
|
|
}
|
|
} else {
|
|
data[k] = v
|
|
}
|
|
}
|
|
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
|
|
}
|
|
|
|
// Overrides the time of the Entry.
|
|
func (entry *Entry) WithTime(t time.Time) *Entry {
|
|
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context}
|
|
}
|
|
|
|
// getPackageName reduces a fully qualified function name to the package name
|
|
// There really ought to be to be a better way...
|
|
func getPackageName(f string) string {
|
|
for {
|
|
lastPeriod := strings.LastIndex(f, ".")
|
|
lastSlash := strings.LastIndex(f, "/")
|
|
if lastPeriod > lastSlash {
|
|
f = f[:lastPeriod]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return f
|
|
}
|
|
|
|
// getCaller retrieves the name of the first non-logrus calling function
|
|
func getCaller() *runtime.Frame {
|
|
|
|
// cache this package's fully-qualified name
|
|
callerInitOnce.Do(func() {
|
|
pcs := make([]uintptr, 2)
|
|
_ = runtime.Callers(0, pcs)
|
|
logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name())
|
|
|
|
// now that we have the cache, we can skip a minimum count of known-logrus functions
|
|
// XXX this is dubious, the number of frames may vary
|
|
minimumCallerDepth = knownLogrusFrames
|
|
})
|
|
|
|
// Restrict the lookback frames to avoid runaway lookups
|
|
pcs := make([]uintptr, maximumCallerDepth)
|
|
depth := runtime.Callers(minimumCallerDepth, pcs)
|
|
frames := runtime.CallersFrames(pcs[:depth])
|
|
|
|
for f, again := frames.Next(); again; f, again = frames.Next() {
|
|
pkg := getPackageName(f.Function)
|
|
|
|
// If the caller isn't part of this package, we're done
|
|
if pkg != logrusPackage {
|
|
return &f
|
|
}
|
|
}
|
|
|
|
// if we got here, we failed to find the caller's context
|
|
return nil
|
|
}
|
|
|
|
func (entry Entry) HasCaller() (has bool) {
|
|
return entry.Logger != nil &&
|
|
entry.Logger.ReportCaller &&
|
|
entry.Caller != nil
|
|
}
|
|
|
|
// This function is not declared with a pointer value because otherwise
|
|
// race conditions will occur when using multiple goroutines
|
|
func (entry Entry) log(level Level, msg string) {
|
|
var buffer *bytes.Buffer
|
|
|
|
// Default to now, but allow users to override if they want.
|
|
//
|
|
// We don't have to worry about polluting future calls to Entry#log()
|
|
// with this assignment because this function is declared with a
|
|
// non-pointer receiver.
|
|
if entry.Time.IsZero() {
|
|
entry.Time = time.Now()
|
|
}
|
|
|
|
entry.Level = level
|
|
entry.Message = msg
|
|
if entry.Logger.ReportCaller {
|
|
entry.Caller = getCaller()
|
|
}
|
|
|
|
entry.fireHooks()
|
|
|
|
buffer = bufferPool.Get().(*bytes.Buffer)
|
|
buffer.Reset()
|
|
defer bufferPool.Put(buffer)
|
|
entry.Buffer = buffer
|
|
|
|
entry.write()
|
|
|
|
entry.Buffer = nil
|
|
|
|
// To avoid Entry#log() returning a value that only would make sense for
|
|
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
|
// directly here.
|
|
if level <= PanicLevel {
|
|
panic(&entry)
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) fireHooks() {
|
|
entry.Logger.mu.Lock()
|
|
defer entry.Logger.mu.Unlock()
|
|
err := entry.Logger.Hooks.Fire(entry.Level, entry)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) write() {
|
|
entry.Logger.mu.Lock()
|
|
defer entry.Logger.mu.Unlock()
|
|
serialized, err := entry.Logger.Formatter.Format(entry)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
|
} else {
|
|
_, err = entry.Logger.Out.Write(serialized)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) Log(level Level, args ...interface{}) {
|
|
if entry.Logger.IsLevelEnabled(level) {
|
|
entry.log(level, fmt.Sprint(args...))
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) Trace(args ...interface{}) {
|
|
entry.Log(TraceLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Debug(args ...interface{}) {
|
|
entry.Log(DebugLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Print(args ...interface{}) {
|
|
entry.Info(args...)
|
|
}
|
|
|
|
func (entry *Entry) Info(args ...interface{}) {
|
|
entry.Log(InfoLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Warn(args ...interface{}) {
|
|
entry.Log(WarnLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Warning(args ...interface{}) {
|
|
entry.Warn(args...)
|
|
}
|
|
|
|
func (entry *Entry) Error(args ...interface{}) {
|
|
entry.Log(ErrorLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Fatal(args ...interface{}) {
|
|
entry.Log(FatalLevel, args...)
|
|
entry.Logger.Exit(1)
|
|
}
|
|
|
|
func (entry *Entry) Panic(args ...interface{}) {
|
|
entry.Log(PanicLevel, args...)
|
|
panic(fmt.Sprint(args...))
|
|
}
|
|
|
|
// Entry Printf family functions
|
|
|
|
func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
|
|
if entry.Logger.IsLevelEnabled(level) {
|
|
entry.Log(level, fmt.Sprintf(format, args...))
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) Tracef(format string, args ...interface{}) {
|
|
entry.Logf(TraceLevel, format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
|
entry.Logf(DebugLevel, format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Infof(format string, args ...interface{}) {
|
|
entry.Logf(InfoLevel, format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Printf(format string, args ...interface{}) {
|
|
entry.Infof(format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
|
entry.Logf(WarnLevel, format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
|
entry.Warnf(format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
|
entry.Logf(ErrorLevel, format, args...)
|
|
}
|
|
|
|
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
|
entry.Logf(FatalLevel, format, args...)
|
|
entry.Logger.Exit(1)
|
|
}
|
|
|
|
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
|
entry.Logf(PanicLevel, format, args...)
|
|
}
|
|
|
|
// Entry Println family functions
|
|
|
|
func (entry *Entry) Logln(level Level, args ...interface{}) {
|
|
if entry.Logger.IsLevelEnabled(level) {
|
|
entry.Log(level, entry.sprintlnn(args...))
|
|
}
|
|
}
|
|
|
|
func (entry *Entry) Traceln(args ...interface{}) {
|
|
entry.Logln(TraceLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Debugln(args ...interface{}) {
|
|
entry.Logln(DebugLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Infoln(args ...interface{}) {
|
|
entry.Logln(InfoLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Println(args ...interface{}) {
|
|
entry.Infoln(args...)
|
|
}
|
|
|
|
func (entry *Entry) Warnln(args ...interface{}) {
|
|
entry.Logln(WarnLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Warningln(args ...interface{}) {
|
|
entry.Warnln(args...)
|
|
}
|
|
|
|
func (entry *Entry) Errorln(args ...interface{}) {
|
|
entry.Logln(ErrorLevel, args...)
|
|
}
|
|
|
|
func (entry *Entry) Fatalln(args ...interface{}) {
|
|
entry.Logln(FatalLevel, args...)
|
|
entry.Logger.Exit(1)
|
|
}
|
|
|
|
func (entry *Entry) Panicln(args ...interface{}) {
|
|
entry.Logln(PanicLevel, args...)
|
|
}
|
|
|
|
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
|
// fmt.Sprintln where spaces are always added between operands, regardless of
|
|
// their type. Instead of vendoring the Sprintln implementation to spare a
|
|
// string allocation, we do the simplest thing.
|
|
func (entry *Entry) sprintlnn(args ...interface{}) string {
|
|
msg := fmt.Sprintln(args...)
|
|
return msg[:len(msg)-1]
|
|
}
|