package logrus

import (
	
	
	
	
	
	
)

// LogFunction For big messages, it can be more efficient to pass a function
// and only call it if the log level is actually enables rather than
// generating the log message and then checking if the level is enabled
type LogFunction func() []interface{}

type Logger struct {
	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
	// file, or leave it default which is `os.Stderr`. You can also set this to
	// something more adventurous, such as logging to Kafka.
	Out io.Writer
	// Hooks for the logger instance. These allow firing events based on logging
	// levels and log entries. For example, to send errors to an error tracking
	// service, log to StatsD or dump the core on fatal errors.
	Hooks LevelHooks
	// All log entries pass through the formatter before logged to Out. The
	// included formatters are `TextFormatter` and `JSONFormatter` for which
	// TextFormatter is the default. In development (when a TTY is attached) it
	// logs with colors, but to a file it wouldn't. You can easily implement your
	// own that implements the `Formatter` interface, see the `README` or included
	// formatters for examples.
	Formatter Formatter

	// Flag for whether to log caller info (off by default)
	ReportCaller bool

	// The logging level the logger should log at. This is typically (and defaults
	// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
	// logged.
	Level Level
	// Used to sync writing to the log. Locking is enabled by Default
	mu MutexWrap
	// Reusable empty entry
	entryPool sync.Pool
	// Function to exit the application, defaults to `os.Exit()`
	ExitFunc exitFunc
}

type exitFunc func(int)

type MutexWrap struct {
	lock     sync.Mutex
	disabled bool
}

func ( *MutexWrap) () {
	if !.disabled {
		.lock.Lock()
	}
}

func ( *MutexWrap) () {
	if !.disabled {
		.lock.Unlock()
	}
}

func ( *MutexWrap) () {
	.disabled = true
}

// Creates a new logger. Configuration should be set by changing `Formatter`,
// `Out` and `Hooks` directly on the default logger instance. You can also just
// instantiate your own:
//
//    var log = &logrus.Logger{
//      Out: os.Stderr,
//      Formatter: new(logrus.TextFormatter),
//      Hooks: make(logrus.LevelHooks),
//      Level: logrus.DebugLevel,
//    }
//
// It's recommended to make this a global instance called `log`.
func () *Logger {
	return &Logger{
		Out:          os.Stderr,
		Formatter:    new(TextFormatter),
		Hooks:        make(LevelHooks),
		Level:        InfoLevel,
		ExitFunc:     os.Exit,
		ReportCaller: false,
	}
}

func ( *Logger) () *Entry {
	,  := .entryPool.Get().(*Entry)
	if  {
		return 
	}
	return NewEntry()
}

func ( *Logger) ( *Entry) {
	.Data = map[string]interface{}{}
	.entryPool.Put()
}

// WithField allocates a new entry and adds a field to it.
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
// this new returned entry.
// If you want multiple fields, use `WithFields`.
func ( *Logger) ( string,  interface{}) *Entry {
	 := .newEntry()
	defer .releaseEntry()
	return .WithField(, )
}

// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func ( *Logger) ( Fields) *Entry {
	 := .newEntry()
	defer .releaseEntry()
	return .WithFields()
}

// Add an error as single field to the log entry.  All it does is call
// `WithError` for the given `error`.
func ( *Logger) ( error) *Entry {
	 := .newEntry()
	defer .releaseEntry()
	return .WithError()
}

// Add a context to the log entry.
func ( *Logger) ( context.Context) *Entry {
	 := .newEntry()
	defer .releaseEntry()
	return .WithContext()
}

// Overrides the time of the log entry.
func ( *Logger) ( time.Time) *Entry {
	 := .newEntry()
	defer .releaseEntry()
	return .WithTime()
}

func ( *Logger) ( Level,  string,  ...interface{}) {
	if .IsLevelEnabled() {
		 := .newEntry()
		.Logf(, , ...)
		.releaseEntry()
	}
}

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

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

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

func ( *Logger) ( string,  ...interface{}) {
	 := .newEntry()
	.Printf(, ...)
	.releaseEntry()
}

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

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

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

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

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

func ( *Logger) ( Level,  ...interface{}) {
	if .IsLevelEnabled() {
		 := .newEntry()
		.Log(, ...)
		.releaseEntry()
	}
}

func ( *Logger) ( Level,  LogFunction) {
	if .IsLevelEnabled() {
		 := .newEntry()
		.Log(, ()...)
		.releaseEntry()
	}
}

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

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

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

func ( *Logger) ( ...interface{}) {
	 := .newEntry()
	.Print(...)
	.releaseEntry()
}

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

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

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

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

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

func ( *Logger) ( LogFunction) {
	.LogFn(TraceLevel, )
}

func ( *Logger) ( LogFunction) {
	.LogFn(DebugLevel, )
}

func ( *Logger) ( LogFunction) {
	.LogFn(InfoLevel, )
}

func ( *Logger) ( LogFunction) {
	 := .newEntry()
	.Print(()...)
	.releaseEntry()
}

func ( *Logger) ( LogFunction) {
	.LogFn(WarnLevel, )
}

func ( *Logger) ( LogFunction) {
	.WarnFn()
}

func ( *Logger) ( LogFunction) {
	.LogFn(ErrorLevel, )
}

func ( *Logger) ( LogFunction) {
	.LogFn(FatalLevel, )
	.Exit(1)
}

func ( *Logger) ( LogFunction) {
	.LogFn(PanicLevel, )
}

func ( *Logger) ( Level,  ...interface{}) {
	if .IsLevelEnabled() {
		 := .newEntry()
		.Logln(, ...)
		.releaseEntry()
	}
}

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

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

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

func ( *Logger) ( ...interface{}) {
	 := .newEntry()
	.Println(...)
	.releaseEntry()
}

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

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

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

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

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

func ( *Logger) ( int) {
	runHandlers()
	if .ExitFunc == nil {
		.ExitFunc = os.Exit
	}
	.ExitFunc()
}

//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func ( *Logger) () {
	.mu.Disable()
}

func ( *Logger) () Level {
	return Level(atomic.LoadUint32((*uint32)(&.Level)))
}

// SetLevel sets the logger level.
func ( *Logger) ( Level) {
	atomic.StoreUint32((*uint32)(&.Level), uint32())
}

// GetLevel returns the logger level.
func ( *Logger) () Level {
	return .level()
}

// AddHook adds a hook to the logger hooks.
func ( *Logger) ( Hook) {
	.mu.Lock()
	defer .mu.Unlock()
	.Hooks.Add()
}

// IsLevelEnabled checks if the log level of the logger is greater than the level param
func ( *Logger) ( Level) bool {
	return .level() >= 
}

// SetFormatter sets the logger formatter.
func ( *Logger) ( Formatter) {
	.mu.Lock()
	defer .mu.Unlock()
	.Formatter = 
}

// SetOutput sets the logger output.
func ( *Logger) ( io.Writer) {
	.mu.Lock()
	defer .mu.Unlock()
	.Out = 
}

func ( *Logger) ( bool) {
	.mu.Lock()
	defer .mu.Unlock()
	.ReportCaller = 
}

// ReplaceHooks replaces the logger hooks and returns the old ones
func ( *Logger) ( LevelHooks) LevelHooks {
	.mu.Lock()
	 := .Hooks
	.Hooks = 
	.mu.Unlock()
	return 
}