github.com/woremacx/kocha@v0.7.1-0.20150731103243-a5889322afc9/log/logger.go (about)

     1  package log
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"os"
     7  	"sort"
     8  	"sync"
     9  	"sync/atomic"
    10  
    11  	"github.com/mattn/go-colorable"
    12  	"github.com/mattn/go-isatty"
    13  )
    14  
    15  // Logger is the interface that logger.
    16  type Logger interface {
    17  	// Debug calls Logger.Output to print to the logger with DEBUG level.
    18  	// Arguments are handled in the manner of fmt.Print.
    19  	// If the current log level is upper than DEBUG, it won't be the output.
    20  	Debug(v ...interface{})
    21  
    22  	// Debugf calls Logger.Output to print to the logger with DEBUG level.
    23  	// Arguments are handled in the manner of fmt.Printf.
    24  	// If the current log level is upper than DEBUG, it won't be the output.
    25  	Debugf(format string, v ...interface{})
    26  
    27  	// Debugln calls Logger.Output to print to the logger with DEBUG level.
    28  	// Arguments are handled in the manner of fmt.Println.
    29  	// If the current log level is upper than DEBUG, it won't be the output.
    30  	Debugln(v ...interface{})
    31  
    32  	// Info calls Logger.Output to print to the logger with INFO level.
    33  	// Arguments are handled in the manner of fmt.Print.
    34  	// If the current log level is upper than INFO, it won't be the output.
    35  	Info(v ...interface{})
    36  
    37  	// Infof calls Logger.Output to print to the logger with INFO level.
    38  	// Arguments are handled in the manner of fmt.Printf.
    39  	// If the current log level is upper than INFO, it won't be the output.
    40  	Infof(format string, v ...interface{})
    41  
    42  	// Infoln calls Logger.Output to print to the logger with INFO level.
    43  	// Arguments are handled in the manner of fmt.Println.
    44  	// If the current log level is upper than INFO, it won't be the output.
    45  	Infoln(v ...interface{})
    46  
    47  	// Warn calls Logger.Output to print to the logger with WARN level.
    48  	// Arguments are handled in the manner of fmt.Print.
    49  	// If the current log level is upper than WARN, it won't be the output.
    50  	Warn(v ...interface{})
    51  
    52  	// Warnf calls Logger.Output to print to the logger with WARN level.
    53  	// Arguments are handled in the manner of fmt.Printf.
    54  	// If the current log level is upper than WARN, it won't be the output.
    55  	Warnf(format string, v ...interface{})
    56  
    57  	// Warnln calls Logger.Output to print to the logger with WARN level.
    58  	// Arguments are handled in the manner of fmt.Println.
    59  	// If the current log level is upper than WARN, it won't be the output.
    60  	Warnln(v ...interface{})
    61  
    62  	// Error calls Logger.Output to print to the logger with ERROR level.
    63  	// Arguments are handled in the manner of fmt.Print.
    64  	// If the current log level is upper than ERROR, it won't be the output.
    65  	Error(v ...interface{})
    66  
    67  	// Errorf calls Logger.Output to print to the logger with ERROR level.
    68  	// Arguments are handled in the manner of fmt.Printf.
    69  	// If the current log level is upper than ERROR, it won't be the output.
    70  	Errorf(format string, v ...interface{})
    71  
    72  	// Errorln calls Logger.Output to print to the logger with ERROR level.
    73  	// Arguments are handled in the manner of fmt.Println.
    74  	// If the current log level is upper than ERROR, it won't be the output.
    75  	Errorln(v ...interface{})
    76  
    77  	// Fatal calls Logger.Output to print to the logger with FATAL level.
    78  	// Arguments are handled in the manner of fmt.Print.
    79  	// Also calls os.Exit(1) after the output.
    80  	Fatal(v ...interface{})
    81  
    82  	// Fatalf calls Logger.Output to print to the logger with FATAL level.
    83  	// Arguments are handled in the manner of fmt.Printf.
    84  	// Also calls os.Exit(1) after the output.
    85  	Fatalf(format string, v ...interface{})
    86  
    87  	// Fatalln calls Logger.Output to print to the logger with FATAL level.
    88  	// Arguments are handled in the manner of fmt.Println.
    89  	// Also calls os.Exit(1) after the output.
    90  	Fatalln(v ...interface{})
    91  
    92  	// Panic calls Logger.Output to print to the logger with PANIC level.
    93  	// Arguments are handled in the manner of fmt.Print.
    94  	// Also calls panic() after the output.
    95  	Panic(v ...interface{})
    96  
    97  	// Panicf calls Logger.Output to print to the logger with PANIC level.
    98  	// Arguments are handled in the manner of fmt.Printf.
    99  	// Also calls panic() after the output.
   100  	Panicf(format string, v ...interface{})
   101  
   102  	// Panicln calls Logger.Output to print to the logger with PANIC level.
   103  	// Arguments are handled in the manner of fmt.Println.
   104  	// Also calls panic() after the output.
   105  	Panicln(v ...interface{})
   106  
   107  	// Print calls Logger.Output to print to the logger with NONE level.
   108  	// Arguments are handled in the manner of fmt.Print.
   109  	Print(v ...interface{})
   110  
   111  	// Printf calls Logger.Output to print to the logger with NONE level.
   112  	// Arguments are handled in the manner of fmt.Printf.
   113  	Printf(format string, v ...interface{})
   114  
   115  	// Println calls Logger.Output to print to the logger with NONE level.
   116  	// Arguments are handled in the manner of fmt.Println.
   117  	Println(v ...interface{})
   118  
   119  	// Output writes the output for a logging event with the given level.
   120  	// The given message will be format by Formatter. Also a newline is appended
   121  	// to the message before the output.
   122  	Output(level Level, message string)
   123  
   124  	// With returns a new Logger with fields.
   125  	With(fields Fields) Logger
   126  
   127  	// Level returns the current log level.
   128  	Level() Level
   129  
   130  	// SetLevel sets the log level.
   131  	SetLevel(level Level)
   132  }
   133  
   134  // New creates a new Logger.
   135  func New(out io.Writer, formatter Formatter, level Level) Logger {
   136  	l := &logger{
   137  		out:         out,
   138  		formatter:   formatter,
   139  		formatFuncs: plainFormats,
   140  		level:       level,
   141  	}
   142  	if w, ok := out.(*os.File); ok && isatty.IsTerminal(w.Fd()) {
   143  		switch w {
   144  		case os.Stdout:
   145  			l.out = colorable.NewColorableStdout()
   146  			l.formatFuncs = coloredFormats
   147  		case os.Stderr:
   148  			l.out = colorable.NewColorableStderr()
   149  			l.formatFuncs = coloredFormats
   150  		}
   151  	}
   152  	return l
   153  }
   154  
   155  // logger implements the Logger interface.
   156  type logger struct {
   157  	out         io.Writer
   158  	formatter   Formatter
   159  	formatFuncs [7]formatFunc
   160  	level       Level
   161  	fields      Fields
   162  	buf         bytes.Buffer
   163  	mu          sync.Mutex
   164  }
   165  
   166  func (l *logger) Debug(v ...interface{}) {
   167  	if l.Level() <= DEBUG {
   168  		newEntryLogger(l).Debug(v...)
   169  	}
   170  }
   171  
   172  func (l *logger) Debugf(format string, v ...interface{}) {
   173  	if l.Level() <= DEBUG {
   174  		newEntryLogger(l).Debugf(format, v...)
   175  	}
   176  }
   177  
   178  func (l *logger) Debugln(v ...interface{}) {
   179  	if l.Level() <= DEBUG {
   180  		newEntryLogger(l).Debugln(v...)
   181  	}
   182  }
   183  
   184  func (l *logger) Info(v ...interface{}) {
   185  	if l.Level() <= INFO {
   186  		newEntryLogger(l).Info(v...)
   187  	}
   188  }
   189  
   190  func (l *logger) Infof(format string, v ...interface{}) {
   191  	if l.Level() <= INFO {
   192  		newEntryLogger(l).Infof(format, v...)
   193  	}
   194  }
   195  
   196  func (l *logger) Infoln(v ...interface{}) {
   197  	if l.Level() <= INFO {
   198  		newEntryLogger(l).Infoln(v...)
   199  	}
   200  }
   201  
   202  func (l *logger) Warn(v ...interface{}) {
   203  	if l.Level() <= WARN {
   204  		newEntryLogger(l).Warn(v...)
   205  	}
   206  }
   207  
   208  func (l *logger) Warnf(format string, v ...interface{}) {
   209  	if l.Level() <= WARN {
   210  		newEntryLogger(l).Warnf(format, v...)
   211  	}
   212  }
   213  
   214  func (l *logger) Warnln(v ...interface{}) {
   215  	if l.Level() <= WARN {
   216  		newEntryLogger(l).Warnln(v...)
   217  	}
   218  }
   219  
   220  func (l *logger) Error(v ...interface{}) {
   221  	if l.Level() <= ERROR {
   222  		newEntryLogger(l).Error(v...)
   223  	}
   224  }
   225  
   226  func (l *logger) Errorf(format string, v ...interface{}) {
   227  	if l.Level() <= ERROR {
   228  		newEntryLogger(l).Errorf(format, v...)
   229  	}
   230  }
   231  
   232  func (l *logger) Errorln(v ...interface{}) {
   233  	if l.Level() <= ERROR {
   234  		newEntryLogger(l).Errorln(v...)
   235  	}
   236  }
   237  
   238  func (l *logger) Fatal(v ...interface{}) {
   239  	newEntryLogger(l).Fatal(v...)
   240  }
   241  
   242  func (l *logger) Fatalf(format string, v ...interface{}) {
   243  	newEntryLogger(l).Fatalf(format, v...)
   244  }
   245  
   246  func (l *logger) Fatalln(v ...interface{}) {
   247  	newEntryLogger(l).Fatalln(v...)
   248  }
   249  
   250  func (l *logger) Panic(v ...interface{}) {
   251  	newEntryLogger(l).Panic(v...)
   252  }
   253  
   254  func (l *logger) Panicf(format string, v ...interface{}) {
   255  	newEntryLogger(l).Panicf(format, v...)
   256  }
   257  
   258  func (l *logger) Panicln(v ...interface{}) {
   259  	newEntryLogger(l).Panicln(v...)
   260  }
   261  
   262  func (l *logger) Print(v ...interface{}) {
   263  	newEntryLogger(l).Print(v...)
   264  }
   265  
   266  func (l *logger) Printf(format string, v ...interface{}) {
   267  	newEntryLogger(l).Printf(format, v...)
   268  }
   269  
   270  func (l *logger) Println(v ...interface{}) {
   271  	newEntryLogger(l).Println(v...)
   272  }
   273  
   274  func (l *logger) Output(level Level, message string) {
   275  	newEntryLogger(l).Output(level, message)
   276  }
   277  
   278  func (l *logger) With(fields Fields) Logger {
   279  	return newEntryLogger(l).With(fields)
   280  }
   281  
   282  func (l *logger) Level() Level {
   283  	return Level(atomic.LoadUint32((*uint32)(&l.level)))
   284  }
   285  
   286  func (l *logger) SetLevel(level Level) {
   287  	atomic.StoreUint32((*uint32)(&l.level), uint32(level))
   288  }
   289  
   290  // Level represents a log level.
   291  type Level uint32
   292  
   293  // The log levels.
   294  const (
   295  	NONE Level = iota
   296  	DEBUG
   297  	INFO
   298  	WARN
   299  	ERROR
   300  	FATAL
   301  	PANIC
   302  )
   303  
   304  type formatFunc func(f Formatter, w io.Writer, entry *Entry) error
   305  
   306  func makeFormat(esc string) formatFunc {
   307  	return func(f Formatter, w io.Writer, entry *Entry) error {
   308  		io.WriteString(w, esc)
   309  		err := f.Format(w, entry)
   310  		io.WriteString(w, "\x1b[0m")
   311  		return err
   312  	}
   313  }
   314  
   315  var coloredFormats = [...]formatFunc{
   316  	Formatter.Format,       // NONE
   317  	Formatter.Format,       // DEBUG
   318  	Formatter.Format,       // INFO
   319  	makeFormat("\x1b[33m"), // WARN
   320  	makeFormat("\x1b[31m"), // ERROR
   321  	makeFormat("\x1b[31m"), // FATAL
   322  	makeFormat("\x1b[31m"), // PANIC
   323  }
   324  
   325  var plainFormats = [...]formatFunc{
   326  	Formatter.Format, // NONE
   327  	Formatter.Format, // DEBUG
   328  	Formatter.Format, // INFO
   329  	Formatter.Format, // WARN
   330  	Formatter.Format, // ERROR
   331  	Formatter.Format, // FATAL
   332  	Formatter.Format, // PANIC
   333  }
   334  
   335  // Fields represents the key-value pairs in a log Entry.
   336  type Fields map[string]interface{}
   337  
   338  // Get returns a value associated with the given key.
   339  func (f Fields) Get(key string) interface{} {
   340  	return f[key]
   341  }
   342  
   343  // OrderedKeys returns the keys of f that sorted in increasing order.
   344  // This is used if you need the consistent map iteration order.
   345  // See also http://golang.org/doc/go1.3#map
   346  func (f Fields) OrderedKeys() (keys []string) {
   347  	for k := range f {
   348  		keys = append(keys, k)
   349  	}
   350  	sort.Strings(keys)
   351  	return keys
   352  }