github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/ngaut/log/log.go (about)

     1  //high level log wrapper, so it can output different log based on level
     2  package log
     3  
     4  import (
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"runtime"
    10  	"sync"
    11  	"time"
    12  )
    13  
    14  const (
    15  	Ldate         = log.Ldate
    16  	Llongfile     = log.Llongfile
    17  	Lmicroseconds = log.Lmicroseconds
    18  	Lshortfile    = log.Lshortfile
    19  	LstdFlags     = log.LstdFlags
    20  	Ltime         = log.Ltime
    21  )
    22  
    23  type (
    24  	LogLevel int
    25  	LogType  int
    26  )
    27  
    28  const (
    29  	LOG_FATAL   = LogType(0x1)
    30  	LOG_ERROR   = LogType(0x2)
    31  	LOG_WARNING = LogType(0x4)
    32  	LOG_INFO    = LogType(0x8)
    33  	LOG_DEBUG   = LogType(0x10)
    34  )
    35  
    36  const (
    37  	LOG_LEVEL_NONE  = LogLevel(0x0)
    38  	LOG_LEVEL_FATAL = LOG_LEVEL_NONE | LogLevel(LOG_FATAL)
    39  	LOG_LEVEL_ERROR = LOG_LEVEL_FATAL | LogLevel(LOG_ERROR)
    40  	LOG_LEVEL_WARN  = LOG_LEVEL_ERROR | LogLevel(LOG_WARNING)
    41  	LOG_LEVEL_INFO  = LOG_LEVEL_WARN | LogLevel(LOG_INFO)
    42  	LOG_LEVEL_DEBUG = LOG_LEVEL_INFO | LogLevel(LOG_DEBUG)
    43  	LOG_LEVEL_ALL   = LOG_LEVEL_DEBUG
    44  )
    45  
    46  const FORMAT_TIME_DAY string = "20060102"
    47  const FORMAT_TIME_HOUR string = "2006010215"
    48  
    49  var _log *logger = New()
    50  
    51  func init() {
    52  	SetLevel(LOG_LEVEL_ERROR)
    53  	SetFlags(Ldate | Ltime | Lshortfile)
    54  	SetHighlighting(runtime.GOOS != "windows")
    55  }
    56  
    57  func Logger() *log.Logger {
    58  	return _log._log
    59  }
    60  
    61  func SetLevel(level LogLevel) {
    62  	_log.SetLevel(level)
    63  }
    64  func GetLogLevel() LogLevel {
    65  	return _log.level
    66  }
    67  
    68  func SetOutput(out io.Writer) {
    69  	_log.SetOutput(out)
    70  }
    71  
    72  func SetOutputByName(path string) error {
    73  	return _log.SetOutputByName(path)
    74  }
    75  
    76  func SetFlags(flags int) {
    77  	_log._log.SetFlags(flags)
    78  }
    79  
    80  func Info(v ...interface{}) {
    81  	_log.Info(v...)
    82  }
    83  
    84  func Infof(format string, v ...interface{}) {
    85  	_log.Infof(format, v...)
    86  }
    87  
    88  func Debug(v ...interface{}) {
    89  	_log.Debug(v...)
    90  }
    91  
    92  func Debugf(format string, v ...interface{}) {
    93  	_log.Debugf(format, v...)
    94  }
    95  
    96  func Warn(v ...interface{}) {
    97  	_log.Warning(v...)
    98  }
    99  
   100  func Warnf(format string, v ...interface{}) {
   101  	_log.Warningf(format, v...)
   102  }
   103  
   104  func Warning(v ...interface{}) {
   105  	_log.Warning(v...)
   106  }
   107  
   108  func Warningf(format string, v ...interface{}) {
   109  	_log.Warningf(format, v...)
   110  }
   111  
   112  func Error(v ...interface{}) {
   113  	_log.Error(v...)
   114  }
   115  
   116  func Errorf(format string, v ...interface{}) {
   117  	_log.Errorf(format, v...)
   118  }
   119  
   120  func Fatal(v ...interface{}) {
   121  	_log.Fatal(v...)
   122  }
   123  
   124  func Fatalf(format string, v ...interface{}) {
   125  	_log.Fatalf(format, v...)
   126  }
   127  
   128  func SetLevelByString(level string) {
   129  	_log.SetLevelByString(level)
   130  }
   131  
   132  func SetHighlighting(highlighting bool) {
   133  	_log.SetHighlighting(highlighting)
   134  }
   135  
   136  func SetRotateByDay() {
   137  	_log.SetRotateByDay()
   138  }
   139  
   140  func SetRotateByHour() {
   141  	_log.SetRotateByHour()
   142  }
   143  
   144  type logger struct {
   145  	_log         *log.Logger
   146  	level        LogLevel
   147  	highlighting bool
   148  
   149  	dailyRolling bool
   150  	hourRolling  bool
   151  
   152  	fileName  string
   153  	logSuffix string
   154  	fd        *os.File
   155  
   156  	lock sync.Mutex
   157  }
   158  
   159  func (l *logger) SetHighlighting(highlighting bool) {
   160  	l.highlighting = highlighting
   161  }
   162  
   163  func (l *logger) SetLevel(level LogLevel) {
   164  	l.level = level
   165  }
   166  
   167  func (l *logger) SetLevelByString(level string) {
   168  	l.level = StringToLogLevel(level)
   169  }
   170  
   171  func (l *logger) SetRotateByDay() {
   172  	l.dailyRolling = true
   173  	l.logSuffix = genDayTime(time.Now())
   174  }
   175  
   176  func (l *logger) SetRotateByHour() {
   177  	l.hourRolling = true
   178  	l.logSuffix = genHourTime(time.Now())
   179  }
   180  
   181  func (l *logger) rotate() error {
   182  	l.lock.Lock()
   183  	defer l.lock.Unlock()
   184  
   185  	var suffix string
   186  	if l.dailyRolling {
   187  		suffix = genDayTime(time.Now())
   188  	} else if l.hourRolling {
   189  		suffix = genHourTime(time.Now())
   190  	} else {
   191  		return nil
   192  	}
   193  
   194  	// Notice: if suffix is not equal to l.LogSuffix, then rotate
   195  	if suffix != l.logSuffix {
   196  		err := l.doRotate(suffix)
   197  		if err != nil {
   198  			return err
   199  		}
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  func (l *logger) doRotate(suffix string) error {
   206  	// Notice: Not check error, is this ok?
   207  	l.fd.Close()
   208  
   209  	lastFileName := l.fileName + "." + l.logSuffix
   210  	err := os.Rename(l.fileName, lastFileName)
   211  	if err != nil {
   212  		return err
   213  	}
   214  
   215  	err = l.SetOutputByName(l.fileName)
   216  	if err != nil {
   217  		return err
   218  	}
   219  
   220  	l.logSuffix = suffix
   221  
   222  	return nil
   223  }
   224  
   225  func (l *logger) SetOutput(out io.Writer) {
   226  	l._log = log.New(out, l._log.Prefix(), l._log.Flags())
   227  }
   228  
   229  func (l *logger) SetOutputByName(path string) error {
   230  	f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
   231  	if err != nil {
   232  		log.Fatal(err)
   233  	}
   234  
   235  	l.SetOutput(f)
   236  
   237  	l.fileName = path
   238  	l.fd = f
   239  
   240  	return err
   241  }
   242  
   243  func (l *logger) log(t LogType, v ...interface{}) {
   244  	if l.level|LogLevel(t) != l.level {
   245  		return
   246  	}
   247  
   248  	err := l.rotate()
   249  	if err != nil {
   250  		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
   251  		return
   252  	}
   253  
   254  	v1 := make([]interface{}, len(v)+2)
   255  	logStr, logColor := LogTypeToString(t)
   256  	if l.highlighting {
   257  		v1[0] = "\033" + logColor + "m[" + logStr + "]"
   258  		copy(v1[1:], v)
   259  		v1[len(v)+1] = "\033[0m"
   260  	} else {
   261  		v1[0] = "[" + logStr + "]"
   262  		copy(v1[1:], v)
   263  		v1[len(v)+1] = ""
   264  	}
   265  
   266  	s := fmt.Sprintln(v1...)
   267  	l._log.Output(4, s)
   268  }
   269  
   270  func (l *logger) logf(t LogType, format string, v ...interface{}) {
   271  	if l.level|LogLevel(t) != l.level {
   272  		return
   273  	}
   274  
   275  	err := l.rotate()
   276  	if err != nil {
   277  		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
   278  		return
   279  	}
   280  
   281  	logStr, logColor := LogTypeToString(t)
   282  	var s string
   283  	if l.highlighting {
   284  		s = "\033" + logColor + "m[" + logStr + "] " + fmt.Sprintf(format, v...) + "\033[0m"
   285  	} else {
   286  		s = "[" + logStr + "] " + fmt.Sprintf(format, v...)
   287  	}
   288  	l._log.Output(4, s)
   289  }
   290  
   291  func (l *logger) Fatal(v ...interface{}) {
   292  	l.log(LOG_FATAL, v...)
   293  	os.Exit(-1)
   294  }
   295  
   296  func (l *logger) Fatalf(format string, v ...interface{}) {
   297  	l.logf(LOG_FATAL, format, v...)
   298  	os.Exit(-1)
   299  }
   300  
   301  func (l *logger) Error(v ...interface{}) {
   302  	l.log(LOG_ERROR, v...)
   303  }
   304  
   305  func (l *logger) Errorf(format string, v ...interface{}) {
   306  	l.logf(LOG_ERROR, format, v...)
   307  }
   308  
   309  func (l *logger) Warning(v ...interface{}) {
   310  	l.log(LOG_WARNING, v...)
   311  }
   312  
   313  func (l *logger) Warningf(format string, v ...interface{}) {
   314  	l.logf(LOG_WARNING, format, v...)
   315  }
   316  
   317  func (l *logger) Debug(v ...interface{}) {
   318  	l.log(LOG_DEBUG, v...)
   319  }
   320  
   321  func (l *logger) Debugf(format string, v ...interface{}) {
   322  	l.logf(LOG_DEBUG, format, v...)
   323  }
   324  
   325  func (l *logger) Info(v ...interface{}) {
   326  	l.log(LOG_INFO, v...)
   327  }
   328  
   329  func (l *logger) Infof(format string, v ...interface{}) {
   330  	l.logf(LOG_INFO, format, v...)
   331  }
   332  
   333  func StringToLogLevel(level string) LogLevel {
   334  	switch level {
   335  	case "fatal":
   336  		return LOG_LEVEL_FATAL
   337  	case "error":
   338  		return LOG_LEVEL_ERROR
   339  	case "warn":
   340  		return LOG_LEVEL_WARN
   341  	case "warning":
   342  		return LOG_LEVEL_WARN
   343  	case "debug":
   344  		return LOG_LEVEL_DEBUG
   345  	case "info":
   346  		return LOG_LEVEL_INFO
   347  	}
   348  	return LOG_LEVEL_ALL
   349  }
   350  
   351  func LogTypeToString(t LogType) (string, string) {
   352  	switch t {
   353  	case LOG_FATAL:
   354  		return "fatal", "[0;31"
   355  	case LOG_ERROR:
   356  		return "error", "[0;31"
   357  	case LOG_WARNING:
   358  		return "warning", "[0;33"
   359  	case LOG_DEBUG:
   360  		return "debug", "[0;36"
   361  	case LOG_INFO:
   362  		return "info", "[0;37"
   363  	}
   364  	return "unknown", "[0;37"
   365  }
   366  
   367  func genDayTime(t time.Time) string {
   368  	return t.Format(FORMAT_TIME_DAY)
   369  }
   370  
   371  func genHourTime(t time.Time) string {
   372  	return t.Format(FORMAT_TIME_HOUR)
   373  }
   374  
   375  func New() *logger {
   376  	return Newlogger(os.Stdout, "")
   377  }
   378  
   379  func Newlogger(w io.Writer, prefix string) *logger {
   380  	return &logger{_log: log.New(w, prefix, LstdFlags), level: LOG_LEVEL_ALL, highlighting: true}
   381  }