gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

logger.go (10822B)


      1 package logrus
      2 
      3 import (
      4 	"context"
      5 	"io"
      6 	"os"
      7 	"sync"
      8 	"sync/atomic"
      9 	"time"
     10 )
     11 
     12 // LogFunction For big messages, it can be more efficient to pass a function
     13 // and only call it if the log level is actually enables rather than
     14 // generating the log message and then checking if the level is enabled
     15 type LogFunction func() []interface{}
     16 
     17 type Logger struct {
     18 	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
     19 	// file, or leave it default which is `os.Stderr`. You can also set this to
     20 	// something more adventurous, such as logging to Kafka.
     21 	Out io.Writer
     22 	// Hooks for the logger instance. These allow firing events based on logging
     23 	// levels and log entries. For example, to send errors to an error tracking
     24 	// service, log to StatsD or dump the core on fatal errors.
     25 	Hooks LevelHooks
     26 	// All log entries pass through the formatter before logged to Out. The
     27 	// included formatters are `TextFormatter` and `JSONFormatter` for which
     28 	// TextFormatter is the default. In development (when a TTY is attached) it
     29 	// logs with colors, but to a file it wouldn't. You can easily implement your
     30 	// own that implements the `Formatter` interface, see the `README` or included
     31 	// formatters for examples.
     32 	Formatter Formatter
     33 
     34 	// Flag for whether to log caller info (off by default)
     35 	ReportCaller bool
     36 
     37 	// The logging level the logger should log at. This is typically (and defaults
     38 	// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
     39 	// logged.
     40 	Level Level
     41 	// Used to sync writing to the log. Locking is enabled by Default
     42 	mu MutexWrap
     43 	// Reusable empty entry
     44 	entryPool sync.Pool
     45 	// Function to exit the application, defaults to `os.Exit()`
     46 	ExitFunc exitFunc
     47 	// The buffer pool used to format the log. If it is nil, the default global
     48 	// buffer pool will be used.
     49 	BufferPool BufferPool
     50 }
     51 
     52 type exitFunc func(int)
     53 
     54 type MutexWrap struct {
     55 	lock     sync.Mutex
     56 	disabled bool
     57 }
     58 
     59 func (mw *MutexWrap) Lock() {
     60 	if !mw.disabled {
     61 		mw.lock.Lock()
     62 	}
     63 }
     64 
     65 func (mw *MutexWrap) Unlock() {
     66 	if !mw.disabled {
     67 		mw.lock.Unlock()
     68 	}
     69 }
     70 
     71 func (mw *MutexWrap) Disable() {
     72 	mw.disabled = true
     73 }
     74 
     75 // Creates a new logger. Configuration should be set by changing `Formatter`,
     76 // `Out` and `Hooks` directly on the default logger instance. You can also just
     77 // instantiate your own:
     78 //
     79 //    var log = &logrus.Logger{
     80 //      Out: os.Stderr,
     81 //      Formatter: new(logrus.TextFormatter),
     82 //      Hooks: make(logrus.LevelHooks),
     83 //      Level: logrus.DebugLevel,
     84 //    }
     85 //
     86 // It's recommended to make this a global instance called `log`.
     87 func New() *Logger {
     88 	return &Logger{
     89 		Out:          os.Stderr,
     90 		Formatter:    new(TextFormatter),
     91 		Hooks:        make(LevelHooks),
     92 		Level:        InfoLevel,
     93 		ExitFunc:     os.Exit,
     94 		ReportCaller: false,
     95 	}
     96 }
     97 
     98 func (logger *Logger) newEntry() *Entry {
     99 	entry, ok := logger.entryPool.Get().(*Entry)
    100 	if ok {
    101 		return entry
    102 	}
    103 	return NewEntry(logger)
    104 }
    105 
    106 func (logger *Logger) releaseEntry(entry *Entry) {
    107 	entry.Data = map[string]interface{}{}
    108 	logger.entryPool.Put(entry)
    109 }
    110 
    111 // WithField allocates a new entry and adds a field to it.
    112 // Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
    113 // this new returned entry.
    114 // If you want multiple fields, use `WithFields`.
    115 func (logger *Logger) WithField(key string, value interface{}) *Entry {
    116 	entry := logger.newEntry()
    117 	defer logger.releaseEntry(entry)
    118 	return entry.WithField(key, value)
    119 }
    120 
    121 // Adds a struct of fields to the log entry. All it does is call `WithField` for
    122 // each `Field`.
    123 func (logger *Logger) WithFields(fields Fields) *Entry {
    124 	entry := logger.newEntry()
    125 	defer logger.releaseEntry(entry)
    126 	return entry.WithFields(fields)
    127 }
    128 
    129 // Add an error as single field to the log entry.  All it does is call
    130 // `WithError` for the given `error`.
    131 func (logger *Logger) WithError(err error) *Entry {
    132 	entry := logger.newEntry()
    133 	defer logger.releaseEntry(entry)
    134 	return entry.WithError(err)
    135 }
    136 
    137 // Add a context to the log entry.
    138 func (logger *Logger) WithContext(ctx context.Context) *Entry {
    139 	entry := logger.newEntry()
    140 	defer logger.releaseEntry(entry)
    141 	return entry.WithContext(ctx)
    142 }
    143 
    144 // Overrides the time of the log entry.
    145 func (logger *Logger) WithTime(t time.Time) *Entry {
    146 	entry := logger.newEntry()
    147 	defer logger.releaseEntry(entry)
    148 	return entry.WithTime(t)
    149 }
    150 
    151 func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
    152 	if logger.IsLevelEnabled(level) {
    153 		entry := logger.newEntry()
    154 		entry.Logf(level, format, args...)
    155 		logger.releaseEntry(entry)
    156 	}
    157 }
    158 
    159 func (logger *Logger) Tracef(format string, args ...interface{}) {
    160 	logger.Logf(TraceLevel, format, args...)
    161 }
    162 
    163 func (logger *Logger) Debugf(format string, args ...interface{}) {
    164 	logger.Logf(DebugLevel, format, args...)
    165 }
    166 
    167 func (logger *Logger) Infof(format string, args ...interface{}) {
    168 	logger.Logf(InfoLevel, format, args...)
    169 }
    170 
    171 func (logger *Logger) Printf(format string, args ...interface{}) {
    172 	entry := logger.newEntry()
    173 	entry.Printf(format, args...)
    174 	logger.releaseEntry(entry)
    175 }
    176 
    177 func (logger *Logger) Warnf(format string, args ...interface{}) {
    178 	logger.Logf(WarnLevel, format, args...)
    179 }
    180 
    181 func (logger *Logger) Warningf(format string, args ...interface{}) {
    182 	logger.Warnf(format, args...)
    183 }
    184 
    185 func (logger *Logger) Errorf(format string, args ...interface{}) {
    186 	logger.Logf(ErrorLevel, format, args...)
    187 }
    188 
    189 func (logger *Logger) Fatalf(format string, args ...interface{}) {
    190 	logger.Logf(FatalLevel, format, args...)
    191 	logger.Exit(1)
    192 }
    193 
    194 func (logger *Logger) Panicf(format string, args ...interface{}) {
    195 	logger.Logf(PanicLevel, format, args...)
    196 }
    197 
    198 // Log will log a message at the level given as parameter.
    199 // Warning: using Log at Panic or Fatal level will not respectively Panic nor Exit.
    200 // For this behaviour Logger.Panic or Logger.Fatal should be used instead.
    201 func (logger *Logger) Log(level Level, args ...interface{}) {
    202 	if logger.IsLevelEnabled(level) {
    203 		entry := logger.newEntry()
    204 		entry.Log(level, args...)
    205 		logger.releaseEntry(entry)
    206 	}
    207 }
    208 
    209 func (logger *Logger) LogFn(level Level, fn LogFunction) {
    210 	if logger.IsLevelEnabled(level) {
    211 		entry := logger.newEntry()
    212 		entry.Log(level, fn()...)
    213 		logger.releaseEntry(entry)
    214 	}
    215 }
    216 
    217 func (logger *Logger) Trace(args ...interface{}) {
    218 	logger.Log(TraceLevel, args...)
    219 }
    220 
    221 func (logger *Logger) Debug(args ...interface{}) {
    222 	logger.Log(DebugLevel, args...)
    223 }
    224 
    225 func (logger *Logger) Info(args ...interface{}) {
    226 	logger.Log(InfoLevel, args...)
    227 }
    228 
    229 func (logger *Logger) Print(args ...interface{}) {
    230 	entry := logger.newEntry()
    231 	entry.Print(args...)
    232 	logger.releaseEntry(entry)
    233 }
    234 
    235 func (logger *Logger) Warn(args ...interface{}) {
    236 	logger.Log(WarnLevel, args...)
    237 }
    238 
    239 func (logger *Logger) Warning(args ...interface{}) {
    240 	logger.Warn(args...)
    241 }
    242 
    243 func (logger *Logger) Error(args ...interface{}) {
    244 	logger.Log(ErrorLevel, args...)
    245 }
    246 
    247 func (logger *Logger) Fatal(args ...interface{}) {
    248 	logger.Log(FatalLevel, args...)
    249 	logger.Exit(1)
    250 }
    251 
    252 func (logger *Logger) Panic(args ...interface{}) {
    253 	logger.Log(PanicLevel, args...)
    254 }
    255 
    256 func (logger *Logger) TraceFn(fn LogFunction) {
    257 	logger.LogFn(TraceLevel, fn)
    258 }
    259 
    260 func (logger *Logger) DebugFn(fn LogFunction) {
    261 	logger.LogFn(DebugLevel, fn)
    262 }
    263 
    264 func (logger *Logger) InfoFn(fn LogFunction) {
    265 	logger.LogFn(InfoLevel, fn)
    266 }
    267 
    268 func (logger *Logger) PrintFn(fn LogFunction) {
    269 	entry := logger.newEntry()
    270 	entry.Print(fn()...)
    271 	logger.releaseEntry(entry)
    272 }
    273 
    274 func (logger *Logger) WarnFn(fn LogFunction) {
    275 	logger.LogFn(WarnLevel, fn)
    276 }
    277 
    278 func (logger *Logger) WarningFn(fn LogFunction) {
    279 	logger.WarnFn(fn)
    280 }
    281 
    282 func (logger *Logger) ErrorFn(fn LogFunction) {
    283 	logger.LogFn(ErrorLevel, fn)
    284 }
    285 
    286 func (logger *Logger) FatalFn(fn LogFunction) {
    287 	logger.LogFn(FatalLevel, fn)
    288 	logger.Exit(1)
    289 }
    290 
    291 func (logger *Logger) PanicFn(fn LogFunction) {
    292 	logger.LogFn(PanicLevel, fn)
    293 }
    294 
    295 func (logger *Logger) Logln(level Level, args ...interface{}) {
    296 	if logger.IsLevelEnabled(level) {
    297 		entry := logger.newEntry()
    298 		entry.Logln(level, args...)
    299 		logger.releaseEntry(entry)
    300 	}
    301 }
    302 
    303 func (logger *Logger) Traceln(args ...interface{}) {
    304 	logger.Logln(TraceLevel, args...)
    305 }
    306 
    307 func (logger *Logger) Debugln(args ...interface{}) {
    308 	logger.Logln(DebugLevel, args...)
    309 }
    310 
    311 func (logger *Logger) Infoln(args ...interface{}) {
    312 	logger.Logln(InfoLevel, args...)
    313 }
    314 
    315 func (logger *Logger) Println(args ...interface{}) {
    316 	entry := logger.newEntry()
    317 	entry.Println(args...)
    318 	logger.releaseEntry(entry)
    319 }
    320 
    321 func (logger *Logger) Warnln(args ...interface{}) {
    322 	logger.Logln(WarnLevel, args...)
    323 }
    324 
    325 func (logger *Logger) Warningln(args ...interface{}) {
    326 	logger.Warnln(args...)
    327 }
    328 
    329 func (logger *Logger) Errorln(args ...interface{}) {
    330 	logger.Logln(ErrorLevel, args...)
    331 }
    332 
    333 func (logger *Logger) Fatalln(args ...interface{}) {
    334 	logger.Logln(FatalLevel, args...)
    335 	logger.Exit(1)
    336 }
    337 
    338 func (logger *Logger) Panicln(args ...interface{}) {
    339 	logger.Logln(PanicLevel, args...)
    340 }
    341 
    342 func (logger *Logger) Exit(code int) {
    343 	runHandlers()
    344 	if logger.ExitFunc == nil {
    345 		logger.ExitFunc = os.Exit
    346 	}
    347 	logger.ExitFunc(code)
    348 }
    349 
    350 //When file is opened with appending mode, it's safe to
    351 //write concurrently to a file (within 4k message on Linux).
    352 //In these cases user can choose to disable the lock.
    353 func (logger *Logger) SetNoLock() {
    354 	logger.mu.Disable()
    355 }
    356 
    357 func (logger *Logger) level() Level {
    358 	return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
    359 }
    360 
    361 // SetLevel sets the logger level.
    362 func (logger *Logger) SetLevel(level Level) {
    363 	atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
    364 }
    365 
    366 // GetLevel returns the logger level.
    367 func (logger *Logger) GetLevel() Level {
    368 	return logger.level()
    369 }
    370 
    371 // AddHook adds a hook to the logger hooks.
    372 func (logger *Logger) AddHook(hook Hook) {
    373 	logger.mu.Lock()
    374 	defer logger.mu.Unlock()
    375 	logger.Hooks.Add(hook)
    376 }
    377 
    378 // IsLevelEnabled checks if the log level of the logger is greater than the level param
    379 func (logger *Logger) IsLevelEnabled(level Level) bool {
    380 	return logger.level() >= level
    381 }
    382 
    383 // SetFormatter sets the logger formatter.
    384 func (logger *Logger) SetFormatter(formatter Formatter) {
    385 	logger.mu.Lock()
    386 	defer logger.mu.Unlock()
    387 	logger.Formatter = formatter
    388 }
    389 
    390 // SetOutput sets the logger output.
    391 func (logger *Logger) SetOutput(output io.Writer) {
    392 	logger.mu.Lock()
    393 	defer logger.mu.Unlock()
    394 	logger.Out = output
    395 }
    396 
    397 func (logger *Logger) SetReportCaller(reportCaller bool) {
    398 	logger.mu.Lock()
    399 	defer logger.mu.Unlock()
    400 	logger.ReportCaller = reportCaller
    401 }
    402 
    403 // ReplaceHooks replaces the logger hooks and returns the old ones
    404 func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
    405 	logger.mu.Lock()
    406 	oldHooks := logger.Hooks
    407 	logger.Hooks = hooks
    408 	logger.mu.Unlock()
    409 	return oldHooks
    410 }
    411 
    412 // SetBufferPool sets the logger buffer pool.
    413 func (logger *Logger) SetBufferPool(pool BufferPool) {
    414 	logger.mu.Lock()
    415 	defer logger.mu.Unlock()
    416 	logger.BufferPool = pool
    417 }