package logrus

import (
	
	
	
	
	
	
	
	
	
)

var (

	// 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 () {
	// 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 ( *Logger) *Entry {
	return &Entry{
		Logger: ,
		// Default is three fields, plus one optional.  Give a little extra room.
		Data: make(Fields, 6),
	}
}

func ( *Entry) () *Entry {
	 := make(Fields, len(.Data))
	for ,  := range .Data {
		[] = 
	}
	return &Entry{Logger: .Logger, Data: , Time: .Time, Context: .Context, err: .err}
}

// Returns the bytes representation of this entry from the formatter.
func ( *Entry) () ([]byte, error) {
	return .Logger.Formatter.Format()
}

// Returns the string representation from the reader and ultimately the
// formatter.
func ( *Entry) () (string, error) {
	,  := .Bytes()
	if  != nil {
		return "", 
	}
	 := string()
	return , nil
}

// Add an error as single field (using the key defined in ErrorKey) to the Entry.
func ( *Entry) ( error) *Entry {
	return .WithField(ErrorKey, )
}

// Add a context to the Entry.
func ( *Entry) ( context.Context) *Entry {
	 := make(Fields, len(.Data))
	for ,  := range .Data {
		[] = 
	}
	return &Entry{Logger: .Logger, Data: , Time: .Time, err: .err, Context: }
}

// Add a single field to the Entry.
func ( *Entry) ( string,  interface{}) *Entry {
	return .WithFields(Fields{: })
}

// Add a map of fields to the Entry.
func ( *Entry) ( Fields) *Entry {
	 := make(Fields, len(.Data)+len())
	for ,  := range .Data {
		[] = 
	}
	 := .err
	for ,  := range  {
		 := false
		if  := reflect.TypeOf();  != nil {
			switch {
			case .Kind() == reflect.Func, .Kind() == reflect.Ptr && .Elem().Kind() == reflect.Func:
				 = true
			}
		}
		if  {
			 := fmt.Sprintf("can not add field %q", )
			if  != "" {
				 = .err + ", " + 
			} else {
				 = 
			}
		} else {
			[] = 
		}
	}
	return &Entry{Logger: .Logger, Data: , Time: .Time, err: , Context: .Context}
}

// Overrides the time of the Entry.
func ( *Entry) ( time.Time) *Entry {
	 := make(Fields, len(.Data))
	for ,  := range .Data {
		[] = 
	}
	return &Entry{Logger: .Logger, Data: , Time: , err: .err, Context: .Context}
}

// getPackageName reduces a fully qualified function name to the package name
// There really ought to be to be a better way...
func ( string) string {
	for {
		 := strings.LastIndex(, ".")
		 := strings.LastIndex(, "/")
		if  >  {
			 = [:]
		} else {
			break
		}
	}

	return 
}

// getCaller retrieves the name of the first non-logrus calling function
func () *runtime.Frame {
	// cache this package's fully-qualified name
	callerInitOnce.Do(func() {
		 := make([]uintptr, maximumCallerDepth)
		_ = runtime.Callers(0, )

		// dynamic get the package name and the minimum caller depth
		for  := 0;  < maximumCallerDepth; ++ {
			 := runtime.FuncForPC([]).Name()
			if strings.Contains(, "getCaller") {
				logrusPackage = getPackageName()
				break
			}
		}

		minimumCallerDepth = knownLogrusFrames
	})

	// Restrict the lookback frames to avoid runaway lookups
	 := make([]uintptr, maximumCallerDepth)
	 := runtime.Callers(minimumCallerDepth, )
	 := runtime.CallersFrames([:])

	for ,  := .Next(); ; ,  = .Next() {
		 := getPackageName(.Function)

		// If the caller isn't part of this package, we're done
		if  != logrusPackage {
			return & //nolint:scopelint
		}
	}

	// if we got here, we failed to find the caller's context
	return nil
}

func ( Entry) () ( bool) {
	return .Logger != nil &&
		.Logger.ReportCaller &&
		.Caller != nil
}

func ( *Entry) ( Level,  string) {
	var  *bytes.Buffer

	 := .Dup()

	if .Time.IsZero() {
		.Time = time.Now()
	}

	.Level = 
	.Message = 

	.Logger.mu.Lock()
	 := .Logger.ReportCaller
	.Logger.mu.Unlock()

	if  {
		.Caller = getCaller()
	}

	.fireHooks()

	 = getBuffer()
	defer func() {
		.Buffer = nil
		putBuffer()
	}()
	.Reset()
	.Buffer = 

	.write()

	.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  <= PanicLevel {
		panic()
	}
}

func ( *Entry) () {
	var  LevelHooks
	.Logger.mu.Lock()
	 = make(LevelHooks, len(.Logger.Hooks))
	for ,  := range .Logger.Hooks {
		[] = 
	}
	.Logger.mu.Unlock()

	 := .Fire(.Level, )
	if  != nil {
		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", )
	}
}

func ( *Entry) () {
	,  := .Logger.Formatter.Format()
	if  != nil {
		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", )
		return
	}
	.Logger.mu.Lock()
	defer .Logger.mu.Unlock()
	if ,  := .Logger.Out.Write();  != nil {
		fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", )
	}
}

func ( *Entry) ( Level,  ...interface{}) {
	if .Logger.IsLevelEnabled() {
		.log(, fmt.Sprint(...))
	}
}

func ( *Entry) ( ...interface{}) {
	.Log(TraceLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Log(DebugLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Info(...)
}

func ( *Entry) ( ...interface{}) {
	.Log(InfoLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Log(WarnLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Warn(...)
}

func ( *Entry) ( ...interface{}) {
	.Log(ErrorLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Log(FatalLevel, ...)
	.Logger.Exit(1)
}

func ( *Entry) ( ...interface{}) {
	.Log(PanicLevel, ...)
}

// Entry Printf family functions

func ( *Entry) ( Level,  string,  ...interface{}) {
	if .Logger.IsLevelEnabled() {
		.Log(, fmt.Sprintf(, ...))
	}
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(TraceLevel, , ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(DebugLevel, , ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(InfoLevel, , ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Infof(, ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(WarnLevel, , ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Warnf(, ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(ErrorLevel, , ...)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(FatalLevel, , ...)
	.Logger.Exit(1)
}

func ( *Entry) ( string,  ...interface{}) {
	.Logf(PanicLevel, , ...)
}

// Entry Println family functions

func ( *Entry) ( Level,  ...interface{}) {
	if .Logger.IsLevelEnabled() {
		.Log(, .sprintlnn(...))
	}
}

func ( *Entry) ( ...interface{}) {
	.Logln(TraceLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Logln(DebugLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Logln(InfoLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Infoln(...)
}

func ( *Entry) ( ...interface{}) {
	.Logln(WarnLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Warnln(...)
}

func ( *Entry) ( ...interface{}) {
	.Logln(ErrorLevel, ...)
}

func ( *Entry) ( ...interface{}) {
	.Logln(FatalLevel, ...)
	.Logger.Exit(1)
}

func ( *Entry) ( ...interface{}) {
	.Logln(PanicLevel, ...)
}

// 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) ( ...interface{}) string {
	 := fmt.Sprintln(...)
	return [:len()-1]
}