Default Log implementions
commit
00fcb49366
@ -0,0 +1,94 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// std is a default logger for console
|
||||
var std = New(os.Stdout).EnableColorizedLevel(true).SkipCaller(3)
|
||||
|
||||
// Get log level
|
||||
func GetLevel() int {
|
||||
return std.GetLevel()
|
||||
}
|
||||
|
||||
// Set log level
|
||||
func SetLevel(level int) {
|
||||
std.SetLevel(level)
|
||||
}
|
||||
|
||||
// Set a name to indicate a process
|
||||
func SetName(name string) {
|
||||
std.SetName(name)
|
||||
}
|
||||
|
||||
// Set time layout for log line
|
||||
func SetTimeLayout(layout string) {
|
||||
std.SetTimeLayout(layout)
|
||||
}
|
||||
|
||||
// EnableGoroutineId output goroutinue id
|
||||
func EnableGoroutineId(enable bool) {
|
||||
std.EnableGoroutineId(enable)
|
||||
}
|
||||
|
||||
// EnableLongFileFormat output long file name
|
||||
func EnableLongFileFormat(enable bool) {
|
||||
std.EnableLongFileFormat(enable)
|
||||
}
|
||||
|
||||
// EnableColorizedLevel output colorized level
|
||||
func EnableColorizedLevel(enable bool) {
|
||||
std.EnableColorizedLevel(enable)
|
||||
}
|
||||
|
||||
// Set a writer
|
||||
func SetWriter(w io.Writer) {
|
||||
std.SetWriter(w)
|
||||
}
|
||||
|
||||
// Indicate whether output debug message
|
||||
func IsDebugEnabled() bool {
|
||||
return std.IsDebugEnabled()
|
||||
}
|
||||
|
||||
// Indicate whether output info message
|
||||
func IsInfoEnabled() bool {
|
||||
return std.IsInfoEnabled()
|
||||
}
|
||||
|
||||
// Indicate whether output warning message
|
||||
func IsWarnEnabled() bool {
|
||||
return std.IsWarnEnabled()
|
||||
}
|
||||
|
||||
// Indicate whether output error message
|
||||
func IsErrorEnabled() bool {
|
||||
return std.IsErrorEnabled()
|
||||
}
|
||||
|
||||
// Output an debug message
|
||||
func Debug(msg string, args ...interface{}) {
|
||||
std.Debug(msg, args...)
|
||||
}
|
||||
|
||||
// Output an info message
|
||||
func Info(msg string, args ...interface{}) {
|
||||
std.Info(msg, args...)
|
||||
}
|
||||
|
||||
// Output a warning message
|
||||
func Warn(msg string, args ...interface{}) {
|
||||
std.Warn(msg, args...)
|
||||
}
|
||||
|
||||
// Output an error message
|
||||
func Error(msg string, args ...interface{}) {
|
||||
std.Error(msg, args)
|
||||
}
|
||||
|
||||
// Output a fatal message with full stack
|
||||
func Fatal(msg string, args ...interface{}) {
|
||||
std.Fatal(msg, args)
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/subchen/gstack/gls"
|
||||
)
|
||||
|
||||
// Log Level
|
||||
const (
|
||||
DEBUG = iota
|
||||
INFO
|
||||
WARN
|
||||
ERROR
|
||||
FATAL
|
||||
)
|
||||
|
||||
var (
|
||||
levelStr = []string{
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"WARN",
|
||||
"ERROR",
|
||||
"FATAL",
|
||||
}
|
||||
levelStrWithColor = []string{
|
||||
"\033[34mDEBUG\033[0m",
|
||||
"\033[32mINFO\033[0m",
|
||||
"\033[33mWARN\033[0m",
|
||||
"\033[31mERROR\033[0m",
|
||||
"\033[35mFATAL\033[0m",
|
||||
}
|
||||
)
|
||||
|
||||
func New(out io.Writer) *Logger {
|
||||
return &Logger{
|
||||
out: out,
|
||||
level: INFO,
|
||||
pid: os.Getpid(),
|
||||
name: "",
|
||||
timeLayout: "2006-01-02 15:04:05.000",
|
||||
goroutineId: false,
|
||||
longFileFormat: false,
|
||||
colorizedLevel: false,
|
||||
callerSkip: 2,
|
||||
}
|
||||
}
|
||||
|
||||
type Logger struct {
|
||||
mu sync.Mutex
|
||||
out io.Writer
|
||||
level int
|
||||
pid int
|
||||
name string
|
||||
timeLayout string
|
||||
goroutineId bool
|
||||
longFileFormat bool
|
||||
colorizedLevel bool
|
||||
callerSkip int
|
||||
}
|
||||
|
||||
func (l *Logger) GetLevel() int {
|
||||
return l.level
|
||||
}
|
||||
|
||||
func (l *Logger) SetLevel(level int) *Logger {
|
||||
l.level = level
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) SetName(name string) *Logger {
|
||||
l.name = name
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) SetTimeLayout(layout string) *Logger {
|
||||
l.timeLayout = layout
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) EnableGoroutineId(enable bool) *Logger {
|
||||
l.goroutineId = enable
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) EnableLongFileFormat(enable bool) *Logger {
|
||||
l.longFileFormat = enable
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) EnableColorizedLevel(enable bool) *Logger {
|
||||
l.colorizedLevel = enable
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) SkipCaller(skip int) *Logger {
|
||||
l.callerSkip = skip
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) SetWriter(w io.Writer) *Logger {
|
||||
l.out = w
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) IsDebugEnabled() bool {
|
||||
return l.level <= DEBUG
|
||||
}
|
||||
|
||||
func (l *Logger) IsInfoEnabled() bool {
|
||||
return l.level <= INFO
|
||||
}
|
||||
|
||||
func (l *Logger) IsWarnEnabled() bool {
|
||||
return l.level <= WARN
|
||||
}
|
||||
|
||||
func (l *Logger) IsErrorEnabled() bool {
|
||||
return l.level <= ERROR
|
||||
}
|
||||
|
||||
func (l *Logger) Debug(msg string, args ...interface{}) {
|
||||
if l.level <= DEBUG {
|
||||
l.log(DEBUG, msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Info(msg string, args ...interface{}) {
|
||||
if l.level <= INFO {
|
||||
l.log(INFO, msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Warn(msg string, args ...interface{}) {
|
||||
if l.level <= WARN {
|
||||
l.log(WARN, msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Error(msg string, args ...interface{}) {
|
||||
if l.level <= ERROR {
|
||||
l.log(ERROR, msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Fatal(msg string, args ...interface{}) {
|
||||
l.log(FATAL, msg, args...)
|
||||
}
|
||||
|
||||
func (l *Logger) log(level int, msg string, args ...interface{}) {
|
||||
_, file, line, ok := runtime.Caller(l.callerSkip)
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 0
|
||||
} else if !l.longFileFormat {
|
||||
if index := strings.LastIndex(file, "/"); index >= 0 {
|
||||
file = file[index+1:]
|
||||
} else if index = strings.LastIndex(file, "\\"); index >= 0 {
|
||||
file = file[index+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// output format: DATE PID [NAME] [GID] LEVEL file:line message
|
||||
// 2001-10-10 12:00:00,000+0800 1234 app 987 INFO main.go:1234 log message ...
|
||||
buf := new(bytes.Buffer)
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(strconv.Itoa(l.pid))
|
||||
buf.WriteByte(' ')
|
||||
if l.name != "" {
|
||||
buf.WriteString(l.name)
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
if l.goroutineId || l.level == DEBUG {
|
||||
buf.WriteString(strconv.FormatUint(gls.GoroutineID(), 10))
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
if l.colorizedLevel {
|
||||
buf.WriteString(levelStrWithColor[level])
|
||||
} else {
|
||||
buf.WriteString(levelStr[level])
|
||||
}
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(file)
|
||||
buf.WriteByte(':')
|
||||
buf.WriteString(strconv.Itoa(line))
|
||||
buf.WriteByte(' ')
|
||||
fmt.Fprintf(buf, msg, args...)
|
||||
buf.WriteByte('\n')
|
||||
|
||||
if level == FATAL {
|
||||
for i := l.callerSkip; ; i++ {
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
fmt.Fprintf(buf, "\tat %s:%d (0x%x)\n", file, line, pc)
|
||||
}
|
||||
}
|
||||
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
timeStr := time.Now().Format(l.timeLayout)
|
||||
|
||||
l.out.Write([]byte(timeStr))
|
||||
l.out.Write(buf.Bytes())
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
stdout := New(os.Stdout)
|
||||
stdout.SetTimeLayout("15:04:05.999")
|
||||
stdout.SetName("main")
|
||||
stdout.SetLevel(DEBUG)
|
||||
stdout.EnableColorizedLevel(true)
|
||||
stdout.EnableGoroutineId(true)
|
||||
for i := 0; i < 3; i++ {
|
||||
go func(i int) {
|
||||
stdout.Debug("i = %d", i)
|
||||
stdout.Info("i = %d", i)
|
||||
}(i)
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
go func(i int) {
|
||||
stdout.Debug("i = %d", i)
|
||||
stdout.Info("i = %d", i)
|
||||
}(i)
|
||||
}
|
||||
|
||||
stdout.Warn("warning")
|
||||
stdout.Error("error")
|
||||
stdout.Fatal("fatal")
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
Loading…
Reference in New Issue