package simplelog import ( "fmt" "io" "os" "runtime" "time" ) const ( B uint64 = 1 << (10 * iota) K M G T P ) // 自定义日志 type LogLevel struct { s string flag LevelFlag } func (l LogLevel) String() string { return l.s } type LevelFlag int const ( FlagInfo LevelFlag = 0x1 FlagWarn LevelFlag = 0x2 FlagError LevelFlag = 0x4 FlagDebug LevelFlag = 0x8 ) var ( INFO = LogLevel{"INFO", FlagInfo} WARN = LogLevel{"WARN", FlagWarn} ERROR = LogLevel{"ERROR", FlagError} DEBUG = LogLevel{"DEBUG", FlagDebug} ) // Logger 日志类 type Logger struct { fn string w io.Writer index int splitSize uint64 timeFormat string loggerFormat string flag LevelFlag } func (l *Logger) time() string { now := time.Now() return now.Format(l.timeFormat) } func (l *Logger) PrintLog(level LogLevel, log string) { // 根据 flag 位 限制日志级别 if l.flag&level.flag != level.flag { return } for { if len(l.fn) == 0 { break } else { file := l.w.(*os.File) info, _ := file.Stat() currentSize := uint64(info.Size()) if l.splitSize == 0 || currentSize < l.splitSize { break } else { _ = file.Close() for { file, err := os.OpenFile(fmt.Sprintf("%s.%d", l.fn, l.index), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) l.index++ if err != nil { continue } else { l.w = file break } } } } } pc, _, _, ok := runtime.Caller(2) var f *runtime.Func if ok { f = runtime.FuncForPC(pc) _, _ = fmt.Fprintf(l.w, l.loggerFormat, l.time(), level, pc, f.Name(), log) } else { _, _ = fmt.Fprintf(l.w, l.loggerFormat, l.time(), level, "--", "Unknown", log) } } // Debug 调试输出 func (l *Logger) Debug(log string) { l.PrintLog(DEBUG, log) } // Info 消息输出 func (l *Logger) Info(log string) { l.PrintLog(INFO, log) } // Warn 消息输出 func (l *Logger) Warn(log string) { l.PrintLog(WARN, log) } // Error 消息输出 func (l *Logger) Error(log string) { if l.flag&FlagError != FlagError { return } pc, file, line, ok := runtime.Caller(1) l.PrintLog(ERROR, log) if ok { _, _ = fmt.Fprintf(l.w, "=> %d %s\tline: %d\n", pc, file, line) } else { _, _ = fmt.Fprintf(l.w, "=> Unknown Unknown : Unknown\n") } } // 函数式 选项模式 type Option struct { Writer io.Writer TimeFormat string LogFormat string LevelFlag LevelFlag LogFile string SplitSize uint64 } type OptionFunc func(*Option) func WithWriter(writer io.Writer) OptionFunc { return func(option *Option) { if len(option.LogFile) == 0 { option.Writer = writer } } } func WithTimeFormat(timeFormat string) OptionFunc { return func(option *Option) { option.TimeFormat = timeFormat } } func WithLogFormat(logFormat string) OptionFunc { return func(option *Option) { option.LogFormat = logFormat } } func WithLogFlag(flag LevelFlag) OptionFunc { return func(option *Option) { option.LevelFlag = flag } } func WithLogFile(filePath string) OptionFunc { return func(option *Option) { if len(filePath) > 0 { option.LogFile = filePath file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { panic(err) } option.Writer = file } } } func WithSplitSize(size uint64) OptionFunc { return func(option *Option) { option.SplitSize = size } } // 默认参数 var defaultOption = &Option{ Writer: os.Stdout, TimeFormat: "2006-01-02 15:04:05.99", LogFormat: "%-22s %-5s %v --- [%20s] : %s\n", LevelFlag: FlagInfo | FlagWarn | FlagError | FlagDebug, LogFile: "", SplitSize: 0, } // NewOption 构造 Option 参数 func NewOption(opts ...OptionFunc) (opt *Option) { opt = defaultOption for _, o := range opts { o(opt) } return } // NewLog 构造函数 func NewLog(opts ...OptionFunc) *Logger { opt := NewOption(opts...) return &Logger{ w: opt.Writer, timeFormat: opt.TimeFormat, loggerFormat: opt.LogFormat, flag: opt.LevelFlag, fn: opt.LogFile, splitSize: opt.SplitSize, } }