139 lines
2.3 KiB
Go
139 lines
2.3 KiB
Go
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)
|
|
SOS = Level(15)
|
|
)
|
|
|
|
type SOSer interface {
|
|
Send(string) error
|
|
}
|
|
|
|
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(SOS)+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
|
|
var ansoser SOSer = nil
|
|
|
|
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 SetSOSer(another SOSer) {
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
ansoser = another
|
|
}
|
|
|
|
func SetLevel(l Level) {
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
level = l
|
|
}
|
|
|
|
func logf(l Level, format string, args []interface{}) {
|
|
format = fmt.Sprintf("%v: %v: %s\n", time.Now().Format("01-02T15:04:05"), l.String(), strings.TrimSpace(format))
|
|
cLevel := level
|
|
cAnsoser := ansoser
|
|
if l >= cLevel {
|
|
fmt.Fprintf(os.Stderr, format, args...)
|
|
}
|
|
fmt.Fprintf(logger, format, args...)
|
|
if l == SOS && cAnsoser != nil {
|
|
if err := cAnsoser.Send(fmt.Sprintf(format, args...)); err != nil {
|
|
Errorf("failed to SOS: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func SOSf(format string, args ...interface{}) {
|
|
logf(SOS, 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"
|
|
case SOS:
|
|
return "SOS"
|
|
default:
|
|
return "?"
|
|
}
|
|
}
|