package log import ( _ "errors" "fmt" "github.com/mattn/go-colorable" "log" "os" "path" "strings" "time" ) // levels const ( debugLevel = 0 releaseLevel = 1 errorLevel = 2 fatalLevel = 3 ) const ( printDebugLevel = "[D]" printReleaseLevel = "[R]" printErrorLevel = "[E]" printFatalLevel = "[F]" ) const ( Green = "\033[97;42m" White = "\033[90;47m" Yellow = "\033[90;43m" Red = "\033[97;41m" Blue = "\033[97;44m" Magenta = "\033[97;45m" Cyan = "\033[97;46m" Reset = "\033[0m" ) type Logger struct { console_level int console_Logger *log.Logger file_level int file_Logger *log.Logger file *os.File error_logger *log.Logger file_error *os.File } func createFileLogger(pathName string, flag int, level int) (*log.Logger, *os.File) { if pathName == "" { return nil, nil } // 如果文件夹不存在则创建 os.MkdirAll(pathName, 0777) now := time.Now() var filename string // debug 分时间段写日志文件,以免文件过大 if level == debugLevel { filename = fmt.Sprintf("%d%02d%02d%02d.log", now.Year(), now.Month(), now.Day(), now.Hour()) } else { // 写一个日志文件 filename = fmt.Sprintf("%d%02d%02d.log", now.Year(), now.Month(), now.Day()) } fmt.Printf("createFileLogger pathName=%s fileName=%s level=%d\n", pathName, filename, level) file, err := os.OpenFile(path.Join(pathName, filename), os.O_APPEND|os.O_CREATE, 0644) if err != nil { return nil, nil } return log.New(file, "", flag), file } func getColor(level int) string { switch level { case releaseLevel: return Cyan case errorLevel: return Red case fatalLevel: return Magenta } return Reset } func getLevelByString(strLevel string) int { var level int switch strings.ToLower(strLevel) { case "debug": level = debugLevel case "release": level = releaseLevel case "error": level = errorLevel case "fatal": level = fatalLevel default: return debugLevel } return level } func New(consoleLevel string, fileLevel string, pathname string, flag int) (*Logger, error) { flag = log.Lmsgprefix // level cLevel := getLevelByString(consoleLevel) fLevel := getLevelByString(fileLevel) consoleLogger := log.New(colorable.NewColorableStdout(), "", flag) fileLogger, file := createFileLogger(pathname, flag, fLevel) // new logger := new(Logger) logger.console_level = cLevel logger.file_level = fLevel logger.console_Logger = consoleLogger logger.file_Logger = fileLogger logger.file = file return logger, nil } func NewWithError(consoleLevel string, fileLevel string, pathname string, flag int, errorFile string) (*Logger, error) { flag = log.Lmsgprefix // level cLevel := getLevelByString(consoleLevel) fLevel := getLevelByString(fileLevel) consoleLogger := log.New(colorable.NewColorableStdout(), "", flag) fileLogger, file := createFileLogger(pathname, flag, fLevel) // new logger := new(Logger) logger.console_level = cLevel logger.file_level = fLevel logger.console_Logger = consoleLogger logger.file_Logger = fileLogger logger.file = file errorLogger, errfile := createFileLogger(errorFile, flag, errorLevel) logger.error_logger = errorLogger logger.file_error = errfile return logger, nil } func RecreateFileLog(pathname string, flag int) { flag = log.Lmsgprefix logger, file := createFileLogger(pathname, flag, gLogger.file_level) if gLogger.file != nil { gLogger.file.Close() } gLogger.file_Logger = logger gLogger.file = file //gLogger.file_Logger, gLogger.file = createFileLogger(pathname, flag, gLogger.file_level) } // It's dangerous to call the method on logging func (logger *Logger) Close() { if logger.file != nil { logger.file.Close() } logger.console_Logger = nil logger.file_Logger = nil logger.file = nil } func getTimeHeaser() string { t := time.Now() _, month, day := t.Date() hour, min, sec := t.Clock() return fmt.Sprintf("%02d-%02d %02d:%02d:%02d", month, day, hour, min, sec) } func (logger *Logger) doPrintf(color string, level int, printLevel string, format string, a ...interface{}) { if level >= errorLevel && logger.error_logger != nil { logger.error_logger.Output(3, getTimeHeaser()+fmt.Sprintf(format, a...)) } else { if (level >= logger.console_level) && (logger.console_Logger != nil) { f := fmt.Sprintf("%s %s %v %s %v", getTimeHeaser(), color, printLevel, Reset, format) logger.console_Logger.Output(3, fmt.Sprintf(f, a...)) } format = getTimeHeaser() + printLevel + format if (level >= logger.file_level) && (logger.file_Logger != nil) { logger.file_Logger.Output(3, fmt.Sprintf(format, a...)) } } if level == fatalLevel { os.Exit(1) } } func (logger *Logger) Debug(format string, a ...interface{}) { logger.doPrintf(getColor(debugLevel), debugLevel, printDebugLevel, format, a...) } func (logger *Logger) Release(format string, a ...interface{}) { logger.doPrintf(getColor(releaseLevel), releaseLevel, printReleaseLevel, format, a...) } func (logger *Logger) Error(format string, a ...interface{}) { logger.doPrintf(getColor(errorLevel), errorLevel, printErrorLevel, format, a...) } func (logger *Logger) Fatal(format string, a ...interface{}) { logger.doPrintf(getColor(fatalLevel), fatalLevel, printFatalLevel, format, a...) } func (logger *Logger) Color(color string, format string, a ...interface{}) { logger.doPrintf(color, debugLevel, printDebugLevel, format, a...) } var gLogger, _ = New("debug", "debug", "", log.Lmsgprefix) // It's dangerous to call the method on logging func Export(logger *Logger) { if logger != nil { gLogger = logger } } func Debug(format string, a ...interface{}) { gLogger.Debug(format, a...) } func Color(color, format string, a ...interface{}) { gLogger.Color(color, format, a...) } func Release(format string, a ...interface{}) { gLogger.Release(format, a...) } func Error(format string, a ...interface{}) { gLogger.Error(format, a...) } func Fatal(format string, a ...interface{}) { gLogger.Fatal(format, a...) } func Close() { gLogger.Close() } func GetDebugLogger() *log.Logger { return gLogger.console_Logger }