package logtr import ( "encoding/json" "errors" "fmt" "io" "os" "strings" "sync" "time" ) type Level int const ( VERBOSE = Level(7) DEBUG = Level(8) INFO = Level(9) ERROR = Level(10) ) func (l Level) MarshalJSON() ([]byte, error) { return json.Marshal(l.String()) } func (l *Level) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } s = strings.TrimSpace(s) s = strings.ToUpper(s) if len(s) > 3 { s = s[:3] } for i := 0; i < int(ERROR)+5; i++ { l2 := Level(i) if l2.String() == s { *l = l2 return nil } } return errors.New("unknown log level: " + s) } var logger io.Writer = os.Stderr var loggerPath string = "" var lock = &sync.Mutex{} var level Level = INFO func SetLogpath(p string) { lock.Lock() defer lock.Unlock() if p == loggerPath { return } f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { panic(err) } logger = f loggerPath = p } func SetLevel(l Level) { level = l } func logf(l Level, format string, args []interface{}) { format = fmt.Sprintf("%v: %v: %s\n", time.Now().Format("15:04:05"), l.String(), strings.TrimSpace(format)) lock.Lock() defer lock.Unlock() if level <= l { fmt.Fprintf(os.Stderr, format, args...) } fmt.Fprintf(logger, format, args...) } func Infof(format string, args ...interface{}) { logf(INFO, format, args) } func Printf(format string, args ...interface{}) { Infof(format, args...) } func Debugf(format string, args ...interface{}) { logf(DEBUG, format, args) } func Verbosef(format string, args ...interface{}) { logf(VERBOSE, format, args) } func Errorf(format string, args ...interface{}) { logf(ERROR, format, args) } func (l Level) String() string { switch l { case ERROR: return "ERR" case INFO: return "INF" case DEBUG: return "DEB" case VERBOSE: return "VER" default: return "?" } }