diff --git a/gokit.go b/gokit.go index b324864..0bb2ecf 100644 --- a/gokit.go +++ b/gokit.go @@ -1,23 +1,29 @@ package logkit import ( + "flag" "fmt" "io" "path" "runtime" + "strconv" + "strings" "time" ) var ( - inited bool - logWriter io.Writer - logLevel = LevelInfo - logLevelName string - logName string - logPath string - channel Channel - alsoStdout bool - withCaller Caller + inited bool + auto bool + logWriter io.Writer + flushInterval time.Duration + fileSplitSize uint64 + logLevel = LevelInfo + logLevelName string + logName string + logPath string + channel Channel + alsoStdout bool + withCaller Caller levelToNames = map[Level]string{ LevelFatal: "FATAL", @@ -42,8 +48,35 @@ const ( LevelFatal ) +func (l *Level) String() string { + return levelToNames[*l] +} + +// Get is part of the flag.Value interface. +func (l *Level) Get() interface{} { + return *l +} + +func (l *Level) Set(value string) error { + for i, name := range levelToNames { + if strings.ToUpper(value) == name { + *l = i + } + } + if *l == Default { + v, err := strconv.Atoi(value) + if err != nil { + return err + } + *l = Level(v) + } + if *l == Default { + *l = LevelDebug + } + return nil +} + type Channel byte -type Caller byte const ( FIlE Channel = iota @@ -51,6 +84,29 @@ const ( KAFKA ) +func (c *Channel) String() string { + switch *c { + case FIlE: + return "file" + case SYSLOG: + return "syslog" + } + return "file" +} +func (c *Channel) Set(value string) error { + switch value { + case "file": + *c = FIlE + case "syslog": + *c = SYSLOG + default: + *c = FIlE + } + return nil +} + +type Caller byte + const ( _ Caller = iota NONE @@ -59,6 +115,33 @@ const ( BasePath ) +func (c *Caller) String() string { + switch *c { + case NONE: + return "none" + case FullPATHFunc: + return "full" + case BasePathFunc: + return "file_func" + case BasePath: + return "file" + } + return "file" +} +func (c *Caller) Set(value string) error { + switch value { + case "file": + *c = BasePath + case "file_func": + *c = BasePathFunc + case "full": + *c = FullPATHFunc + default: + *c = BasePathFunc + } + return nil +} + type Writer interface { //Write 写日志 Write(msg []byte) (int, error) @@ -66,36 +149,50 @@ type Writer interface { Close() error } +func GetWriter() io.Closer { + return logWriter.(io.Closer) +} + func Exit() { + if logWriter == nil { + return + } logWriter.(io.Closer).Close() } -func Init(_channel Channel, name string, level Level, _alsoStdout bool, _withCaller Caller) (writer io.Writer, err error ){ +func init() { + flag.Var(&logLevel, "log.level", "log level, default `INFO`, it can be `DEBUG, INFO, WARN, ERROR, FATAL`") + flag.Var(&channel, "log.channel", "write to , it can be `file syslog`") + flag.Var(&withCaller, "log.withCaller", "call context, by default filename and func name, it can be `file, file_func, full`") + + flag.BoolVar(&alsoStdout, "log.alsoStdout", false, "log out to stand error as well, default `false`") + flag.StringVar(&logName, "log.name", "log", "log name, by default log will out to `/data/logs/{name}.log`") + flag.BoolVar(&auto, "log.autoInit", true, "log will be init automatic") + flag.DurationVar(&flushInterval, "log.interval", time.Second*5, "duration time on flush to disk") + flag.Uint64Var(&fileSplitSize, "log.split", uint64(1204*1024*1800), "log fail split on bytes") +} + +func Init() (writer io.Writer, err error) { if inited { return nil, fmt.Errorf("logkit has been inited") } - if name != "" { - logName = name - } else { + if logName == "" { return nil, fmt.Errorf("log name must not be empty") } - if logWriter == nil && channel == FIlE { if logPath == "" { logPath = "/data/logs/" + logName + ".log" } - logWriter = NewFileLogger(logPath, logName, time.Second*5, 1204*1024*1800, 4*1024) + logWriter, err = NewFileLogger(logPath, logName, flushInterval, fileSplitSize, 4*1024) + if err != nil { + return + } } if logWriter == nil && channel == SYSLOG { - logWriter, _ = NewSyslogWriter("", "", level, logName) + logWriter, _ = NewSyslogWriter("", "", logLevel, logName) } inited = true - - logLevel = level - channel = _channel - alsoStdout = _alsoStdout - withCaller = _withCaller return logWriter, nil } @@ -118,16 +215,16 @@ func format(level Level, msg string) string { pc, file, line, _ = runtime.Caller(3) switch withCaller { case FullPATHFunc: - context = fmt.Sprintf("%s:%03d::%s", file, line, path.Base(runtime.FuncForPC(pc).Name())) + context = fmt.Sprintf("%s:%03d::%30s", file, line, path.Base(runtime.FuncForPC(pc).Name())) case BasePathFunc: - context = fmt.Sprintf("%s:%03d::%s", path.Base(file), line, path.Base(runtime.FuncForPC(pc).Name())) + context = fmt.Sprintf("%s:%03d::%30s", path.Base(file), line, path.Base(runtime.FuncForPC(pc).Name())) case BasePath: - context = fmt.Sprintf("%s:%03d", path.Base(file), line) + context = fmt.Sprintf("%s:%03d", path.Base(file), line) default: - context = fmt.Sprintf("%s:%03d", path.Base(file), line) + context = fmt.Sprintf("%s:%03d", path.Base(file), line) } - return fmt.Sprintf("%s\t[%4s]\t%-20.64s\t%s\n", time.Now().Format("2006-01-02 15:04:05.999"), getLevelName(level), context, msg) + return fmt.Sprintf("%s\t[%4s]\t%s\t%s\n", time.Now().Format("2006-01-02 15:04:05.999"), getLevelName(level), context, msg) } else { return fmt.Sprintf("%s\t[%4s]\t%s\n", time.Now().Format("2006-01-02 15:04:05.999"), getLevelName(level), msg) }