mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve handler feature for package glog
This commit is contained in:
14
.example/os/glog/glog_CtxKeys.go
Normal file
14
.example/os/glog/glog_CtxKeys.go
Normal file
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g.Log().SetCtxKeys("TraceId", "SpanId", "Test")
|
||||
ctx := context.WithValue(context.Background(), "TraceId", "1234567890")
|
||||
ctx = context.WithValue(ctx, "SpanId", "abcdefg")
|
||||
|
||||
g.Log().Ctx(ctx).Print(1, 2, 3)
|
||||
}
|
||||
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := glog.SetConfigWithMap(g.Map{
|
||||
err := g.Log().SetConfigWithMap(g.Map{
|
||||
"prefix": "[TEST]",
|
||||
})
|
||||
if err != nil {
|
||||
@ -1,14 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for i := 0; i < 10; i++ {
|
||||
glog.Async().Print("async log", i)
|
||||
g.Log().Async().Print("async log", i)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
@ -1,15 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
glog.SetAsync(true)
|
||||
g.Log().SetAsync(true)
|
||||
for i := 0; i < 10; i++ {
|
||||
glog.Async().Print("async log", i)
|
||||
g.Log().Print("async log", i)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
@ -3,13 +3,12 @@ package main
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "/tmp/glog-cat"
|
||||
glog.SetPath(path)
|
||||
glog.Stdout(false).Cat("cat1").Cat("cat2").Println("test")
|
||||
g.Log().SetPath(path)
|
||||
g.Log().Stdout(false).Cat("cat1").Cat("cat2").Println("test")
|
||||
list, err := gfile.ScanDir(path, "*", true)
|
||||
g.Dump(err)
|
||||
g.Dump(list)
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
glog.SetCtxKeys("Trace-Id", "Span-Id", "Test")
|
||||
ctx := context.WithValue(context.Background(), "Trace-Id", "1234567890")
|
||||
ctx = context.WithValue(ctx, "Span-Id", "abcdefg")
|
||||
|
||||
glog.Ctx(ctx).Print(1, 2, 3)
|
||||
}
|
||||
@ -1,19 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"github.com/gogf/gf/os/gtimer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gtimer.SetTimeout(3*time.Second, func() {
|
||||
glog.SetDebug(false)
|
||||
g.Log().SetDebug(false)
|
||||
})
|
||||
for {
|
||||
glog.Debug(gtime.Datetime())
|
||||
g.Log().Debug(gtime.Datetime())
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,24 +3,25 @@ package main
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
// 设置日志等级
|
||||
func main() {
|
||||
l := glog.New()
|
||||
path := "/tmp/glog"
|
||||
l.SetPath(path)
|
||||
l.SetStdoutPrint(false)
|
||||
g.Log().SetPath(path)
|
||||
g.Log().SetStdoutPrint(false)
|
||||
|
||||
// 使用默认文件名称格式
|
||||
l.Println("标准文件名称格式,使用当前时间时期")
|
||||
g.Log().Println("标准文件名称格式,使用当前时间时期")
|
||||
|
||||
// 通过SetFile设置文件名称格式
|
||||
l.SetFile("stdout.log")
|
||||
l.Println("设置日志输出文件名称格式为同一个文件")
|
||||
g.Log().SetFile("stdout.log")
|
||||
g.Log().Println("设置日志输出文件名称格式为同一个文件")
|
||||
|
||||
// 链式操作设置文件名称格式
|
||||
l.File("stderr.log").Println("支持链式操作")
|
||||
l.File("error-{Ymd}.log").Println("文件名称支持带gtime日期格式")
|
||||
l.File("access-{Ymd}.log").Println("文件名称支持带gtime日期格式")
|
||||
g.Log().File("stderr.log").Println("支持链式操作")
|
||||
g.Log().File("error-{Ymd}.log").Println("文件名称支持带gtime日期格式")
|
||||
g.Log().File("access-{Ymd}.log").Println("文件名称支持带gtime日期格式")
|
||||
|
||||
list, err := gfile.ScanDir(path, "*")
|
||||
g.Dump(err)
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := glog.New()
|
||||
l.SetFlags(glog.F_TIME_TIME | glog.F_FILE_SHORT)
|
||||
l.Println("time and short line number")
|
||||
l.SetFlags(glog.F_TIME_MILLI | glog.F_FILE_LONG)
|
||||
l.Println("time with millisecond and long line number")
|
||||
l.SetFlags(glog.F_TIME_STD | glog.F_FILE_LONG)
|
||||
l.Println("standard time format and long line number")
|
||||
g.Log().SetFlags(glog.F_TIME_TIME | glog.F_FILE_SHORT)
|
||||
g.Log().Println("time and short line number")
|
||||
g.Log().SetFlags(glog.F_TIME_MILLI | glog.F_FILE_LONG)
|
||||
g.Log().Println("time with millisecond and long line number")
|
||||
g.Log().SetFlags(glog.F_TIME_STD | glog.F_FILE_LONG)
|
||||
g.Log().Println("standard time format and long line number")
|
||||
}
|
||||
|
||||
@ -2,9 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func MakeError() error {
|
||||
@ -18,8 +18,8 @@ func MakeGError() error {
|
||||
func TestGError() {
|
||||
err1 := MakeError()
|
||||
err2 := MakeGError()
|
||||
glog.Error(err1)
|
||||
glog.Error(err2)
|
||||
g.Log().Error(err1)
|
||||
g.Log().Error(err2)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@ -2,15 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
glog.Debug(g.Map{"uid": 100, "name": "john"})
|
||||
g.Log().Debug(g.Map{"uid": 100, "name": "john"})
|
||||
|
||||
type User struct {
|
||||
Uid int `json:"uid"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
glog.Debug(User{100, "john"})
|
||||
g.Log().Debug(User{100, "john"})
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
// 设置日志等级,过滤掉Info日志信息
|
||||
func main() {
|
||||
l := glog.New()
|
||||
l.Info("info1")
|
||||
l.SetLevel(glog.LEVEL_ALL ^ glog.LEVEL_INFO)
|
||||
l.Info("info2")
|
||||
g.Log().Info("info1")
|
||||
g.Log().SetLevel(glog.LEVEL_ALL ^ glog.LEVEL_INFO)
|
||||
g.Log().Info("info2")
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := glog.New()
|
||||
l.SetLevelPrefix(glog.LEVEL_DEBU, "debug")
|
||||
l.Debug("test")
|
||||
g.Log().SetLevelPrefix(glog.LEVEL_DEBU, "debug")
|
||||
g.Log().Debug("test")
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
glog.Line().Debug("this is the short file name with its line number")
|
||||
glog.Line(true).Debug("lone file name with line number")
|
||||
g.Log().Line().Debug("this is the short file name with its line number")
|
||||
g.Log().Line(true).Debug("lone file name with line number")
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func PrintLog(content string) {
|
||||
glog.Skip(0).Line().Println("line number with skip:", content)
|
||||
glog.Line(true).Println("line number without skip:", content)
|
||||
g.Log().Skip(0).Line().Println("line number with skip:", content)
|
||||
g.Log().Line(true).Println("line number without skip:", content)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@ -3,14 +3,13 @@ package main
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
// 设置日志输出路径
|
||||
func main() {
|
||||
path := "/tmp/glog"
|
||||
glog.SetPath(path)
|
||||
glog.Println("日志内容")
|
||||
g.Log().SetPath(path)
|
||||
g.Log().Println("日志内容")
|
||||
list, err := gfile.ScanDir(path, "*")
|
||||
g.Dump(err)
|
||||
g.Dump(list)
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
)
|
||||
|
||||
// 测试删除日志文件是否会重建日志文件
|
||||
func main() {
|
||||
path := "/Users/john/Temp/test"
|
||||
glog.SetPath(path)
|
||||
g.Log().SetPath(path)
|
||||
for {
|
||||
glog.Println(gtime.Now().String())
|
||||
g.Log().Println(gtime.Now().String())
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := glog.New()
|
||||
l.SetPrefix("[API]")
|
||||
l.Println("hello world")
|
||||
l.Error("error occurred")
|
||||
g.Log().SetPrefix("[API]")
|
||||
g.Log().Println("hello world")
|
||||
g.Log().Error("error occurred")
|
||||
}
|
||||
|
||||
@ -2,15 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g.Log().PrintStack()
|
||||
|
||||
glog.PrintStack()
|
||||
glog.New().PrintStack()
|
||||
|
||||
fmt.Println(glog.GetStack())
|
||||
fmt.Println(glog.New().GetStack())
|
||||
fmt.Println(g.Log().GetStack())
|
||||
}
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"sync"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
wg := sync.WaitGroup{}
|
||||
c := make(chan struct{})
|
||||
var (
|
||||
wg = sync.WaitGroup{}
|
||||
ch = make(chan struct{})
|
||||
)
|
||||
wg.Add(3000)
|
||||
for i := 0; i < 3000; i++ {
|
||||
go func() {
|
||||
<-c
|
||||
glog.Println("abcdefghijklmnopqrstuvwxyz1234567890")
|
||||
<-ch
|
||||
g.Log().Println("abcdefghijklmnopqrstuvwxyz1234567890")
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
close(c)
|
||||
close(ch)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
)
|
||||
@ -16,7 +16,7 @@ func (w *MyWriter) Write(p []byte) (n int, err error) {
|
||||
s := string(p)
|
||||
if gregex.IsMatchString(`\[(PANI|FATA)\]`, s) {
|
||||
fmt.Println("SERIOUS ISSUE OCCURRED!! I'd better tell monitor in first time!")
|
||||
ghttp.PostContent("http://monitor.mydomain.com", s)
|
||||
g.Client().PostContent("http://monitor.mydomain.com", s)
|
||||
}
|
||||
return w.logger.Write(p)
|
||||
}
|
||||
|
||||
42
.example/os/glog/handler/glog_handler_json.go
Normal file
42
.example/os/glog/handler/glog_handler_json.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"os"
|
||||
)
|
||||
|
||||
// JsonOutputsForLogger is for JSON marshaling in sequence.
|
||||
type JsonOutputsForLogger struct {
|
||||
Time string `json:"time"`
|
||||
Level string `json:"level"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// LoggingJsonHandler is a example handler for logging JSON format content.
|
||||
var LoggingJsonHandler glog.Handler = func(ctx context.Context, in *glog.HandlerInput) {
|
||||
jsonForLogger := JsonOutputsForLogger{
|
||||
Time: in.TimeFormat,
|
||||
Level: in.LevelFormat,
|
||||
Content: gstr.Trim(in.String()),
|
||||
}
|
||||
jsonBytes, err := json.Marshal(jsonForLogger)
|
||||
if err != nil {
|
||||
_, _ = os.Stderr.WriteString(err.Error())
|
||||
return
|
||||
}
|
||||
in.Buffer.Write(jsonBytes)
|
||||
in.Buffer.WriteString("\n")
|
||||
in.Next()
|
||||
}
|
||||
|
||||
func main() {
|
||||
g.Log().SetHandlers(LoggingJsonHandler)
|
||||
|
||||
g.Log().Debug("Debugging...")
|
||||
g.Log().Warning("It is warning info")
|
||||
g.Log().Error("Error occurs, please have a check")
|
||||
}
|
||||
@ -10,8 +10,10 @@ import (
|
||||
|
||||
// 内存锁基本使用
|
||||
func main() {
|
||||
key := "lock"
|
||||
wg := sync.WaitGroup{}
|
||||
var (
|
||||
key = "lock"
|
||||
wg = sync.WaitGroup{}
|
||||
)
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
@ -11,12 +11,13 @@ import (
|
||||
|
||||
// 测试Locker是否会产生死锁
|
||||
func main() {
|
||||
l := gmlock.New()
|
||||
wg := sync.WaitGroup{}
|
||||
key := "test"
|
||||
event := make(chan int)
|
||||
number := 100000
|
||||
|
||||
var (
|
||||
l = gmlock.New()
|
||||
wg = sync.WaitGroup{}
|
||||
key = "test"
|
||||
event = make(chan int)
|
||||
number = 100000
|
||||
)
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
@ -1,23 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/os/gmlock"
|
||||
)
|
||||
|
||||
// 内存锁 - 给定过期时间
|
||||
func main() {
|
||||
key := "lock"
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
gmlock.Lock(key, 1000)
|
||||
glog.Println(i)
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/os/gmlock"
|
||||
)
|
||||
|
||||
// 测试是否会产生死锁
|
||||
func main() {
|
||||
mu := gmlock.NewMutex()
|
||||
wg := sync.WaitGroup{}
|
||||
event := make(chan int)
|
||||
number := 100000
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
mu.Lock()
|
||||
//fmt.Println("get lock")
|
||||
mu.Unlock()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
mu.RLock()
|
||||
//fmt.Println("get rlock")
|
||||
mu.RUnlock()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
if mu.TryLock() {
|
||||
//fmt.Println("get lock")
|
||||
mu.Unlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
if mu.TryRLock() {
|
||||
//fmt.Println("get rlock")
|
||||
mu.RUnlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
if mu.TryLock() {
|
||||
// 模拟业务逻辑的随机处理间隔
|
||||
time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
|
||||
mu.Unlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < number; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-event
|
||||
if mu.TryRLock() {
|
||||
// 模拟业务逻辑的随机处理间隔
|
||||
time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
|
||||
mu.RUnlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
// 使用chan作为事件发送测试指令,让所有的goroutine同时执行
|
||||
close(event)
|
||||
wg.Wait()
|
||||
|
||||
fmt.Println("done!")
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
package glog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
@ -77,11 +78,11 @@ func NewWithWriter(writer io.Writer) *Logger {
|
||||
// Clone returns a new logger, which is the clone the current logger.
|
||||
// It's commonly used for chaining operations.
|
||||
func (l *Logger) Clone() *Logger {
|
||||
logger := New()
|
||||
logger.ctx = l.ctx
|
||||
logger.config = l.config
|
||||
logger.parent = l
|
||||
return logger
|
||||
newLogger := New()
|
||||
newLogger.ctx = l.ctx
|
||||
newLogger.config = l.config
|
||||
newLogger.parent = l
|
||||
return newLogger
|
||||
}
|
||||
|
||||
// getFilePath returns the logging file path.
|
||||
@ -115,12 +116,13 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
|
||||
var (
|
||||
now = time.Now()
|
||||
input = &HandlerInput{
|
||||
logger: l,
|
||||
index: -1,
|
||||
Ctx: ctx,
|
||||
Time: now,
|
||||
Color: defaultLevelColor[level],
|
||||
Level: level,
|
||||
Logger: l,
|
||||
Buffer: bytes.NewBuffer(nil),
|
||||
Ctx: ctx,
|
||||
Time: now,
|
||||
Color: defaultLevelColor[level],
|
||||
Level: level,
|
||||
handlerIndex: -1,
|
||||
}
|
||||
)
|
||||
if l.config.HeaderPrint {
|
||||
@ -224,8 +226,8 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// doPrint outputs the logging content according configuration.
|
||||
func (l *Logger) doPrint(ctx context.Context, input *HandlerInput) {
|
||||
// doDefaultPrint outputs the logging content according configuration.
|
||||
func (l *Logger) doDefaultPrint(ctx context.Context, input *HandlerInput) {
|
||||
if l.config.Writer == nil {
|
||||
// Output content to disk file.
|
||||
if l.config.Path != "" {
|
||||
@ -245,7 +247,7 @@ func (l *Logger) doPrint(ctx context.Context, input *HandlerInput) {
|
||||
func (l *Logger) printToWriter(ctx context.Context, input *HandlerInput) {
|
||||
if l.config.Writer != nil {
|
||||
var (
|
||||
buffer = input.getBuffer(l.config.WriterColorEnable)
|
||||
buffer = input.getRealBuffer(l.config.WriterColorEnable)
|
||||
)
|
||||
if _, err := l.config.Writer.Write(buffer.Bytes()); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
@ -257,18 +259,18 @@ func (l *Logger) printToWriter(ctx context.Context, input *HandlerInput) {
|
||||
func (l *Logger) printToStdout(ctx context.Context, input *HandlerInput) {
|
||||
if l.config.StdoutPrint {
|
||||
// This will lose color in Windows os system.
|
||||
// if _, err := os.Stdout.Write(input.getBuffer(true).Bytes()); err != nil {
|
||||
// if _, err := os.Stdout.Write(input.getRealBuffer(true).Bytes()); err != nil {
|
||||
// This will print color in Windows os system.
|
||||
if _, err := fmt.Fprintf(color.Output, input.getBuffer(true).String()); err != nil {
|
||||
if _, err := fmt.Fprintf(color.Output, input.getRealBuffer(true).String()); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printToFile outputs logging content to disk file.
|
||||
func (l *Logger) printToFile(ctx context.Context, t time.Time, input *HandlerInput) {
|
||||
func (l *Logger) printToFile(ctx context.Context, t time.Time, in *HandlerInput) {
|
||||
var (
|
||||
buffer = input.getBuffer(l.config.WriterColorEnable)
|
||||
buffer = in.getRealBuffer(l.config.WriterColorEnable)
|
||||
logFilePath = l.getFilePath(t)
|
||||
memoryLockKey = memoryLockPrefixForPrintingToFile + logFilePath
|
||||
)
|
||||
@ -362,3 +364,8 @@ func (l *Logger) GetStack(skip ...int) string {
|
||||
}
|
||||
return gdebug.StackWithFilters(filters, stackSkip)
|
||||
}
|
||||
|
||||
// GetConfig returns the configuration of current Logger.
|
||||
func (l *Logger) GetConfig() Config {
|
||||
return l.config
|
||||
}
|
||||
|
||||
@ -24,10 +24,10 @@ type Config struct {
|
||||
Writer io.Writer `json:"-"` // Customized io.Writer.
|
||||
Flags int `json:"flags"` // Extra flags for logging output features.
|
||||
Path string `json:"path"` // Logging directory path.
|
||||
File string `json:"file"` // Format for logging file.
|
||||
File string `json:"file"` // Format pattern for logging file.
|
||||
Level int `json:"level"` // Output level.
|
||||
Prefix string `json:"prefix"` // Prefix string for every logging content.
|
||||
StSkip int `json:"stSkip"` // Skip count for stack.
|
||||
StSkip int `json:"stSkip"` // Skipping count for stack.
|
||||
StStatus int `json:"stStatus"` // Stack status(1: enabled - default; 0: disabled)
|
||||
StFilter string `json:"stFilter"` // Stack string filter.
|
||||
CtxKeys []interface{} `json:"ctxKeys"` // Context keys for logging, which is used for value retrieving from context.
|
||||
|
||||
@ -15,51 +15,53 @@ import (
|
||||
// Handler is function handler for custom logging content outputs.
|
||||
type Handler func(ctx context.Context, in *HandlerInput)
|
||||
|
||||
// HandlerInput is the input parameter struct for logging Handler.
|
||||
type HandlerInput struct {
|
||||
logger *Logger // Logger.
|
||||
index int // Middleware handling index for internal usage.
|
||||
Ctx context.Context // Context.
|
||||
Time time.Time // Logging time, which is the time that logging triggers.
|
||||
TimeFormat string // Formatted time string, like "2016-01-09 12:00:00".
|
||||
Color int // Using color, like COLOR_RED, COLOR_BLUE, etc.
|
||||
Level int // Using level, like LEVEL_INFO, LEVEL_ERRO, etc.
|
||||
LevelFormat string // Formatted level string, like "DEBU", "ERRO", etc.
|
||||
CallerFunc string // The source function name that calls logging.
|
||||
CallerPath string // The source file path and its line number that calls logging.
|
||||
CtxStr string // The retrieved context value string from context.
|
||||
Prefix string // Custom prefix string for logging content.
|
||||
Content string // Content is the main logging content that passed by you.
|
||||
IsAsync bool // IsAsync marks it is in asynchronous logging.
|
||||
Logger *Logger // Logger.
|
||||
Ctx context.Context // Context.
|
||||
Buffer *bytes.Buffer // Buffer for logging content outputs.
|
||||
Time time.Time // Logging time, which is the time that logging triggers.
|
||||
TimeFormat string // Formatted time string, like "2016-01-09 12:00:00".
|
||||
Color int // Using color, like COLOR_RED, COLOR_BLUE, etc.
|
||||
Level int // Using level, like LEVEL_INFO, LEVEL_ERRO, etc.
|
||||
LevelFormat string // Formatted level string, like "DEBU", "ERRO", etc.
|
||||
CallerFunc string // The source function name that calls logging.
|
||||
CallerPath string // The source file path and its line number that calls logging.
|
||||
CtxStr string // The retrieved context value string from context.
|
||||
Prefix string // Custom prefix string for logging content.
|
||||
Content string // Content is the main logging content that passed by you.
|
||||
IsAsync bool // IsAsync marks it is in asynchronous logging.
|
||||
handlerIndex int // Middleware handling index for internal usage.
|
||||
}
|
||||
|
||||
// defaultHandler is the default handler for logger.
|
||||
func defaultHandler(ctx context.Context, in *HandlerInput) {
|
||||
in.logger.doPrint(ctx, in)
|
||||
}
|
||||
|
||||
func (i *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, strings ...string) {
|
||||
for _, s := range strings {
|
||||
if buffer.Len() > 0 {
|
||||
buffer.WriteByte(' ')
|
||||
}
|
||||
buffer.WriteString(s)
|
||||
// Next calls the next logging handler in middleware way.
|
||||
func (i *HandlerInput) Next() {
|
||||
if len(i.Logger.config.Handlers)-1 > i.handlerIndex {
|
||||
i.handlerIndex++
|
||||
i.Logger.config.Handlers[i.handlerIndex](i.Ctx, i)
|
||||
} else {
|
||||
defaultHandler(i.Ctx, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer creates and returns a buffer that handled by default logging content handler.
|
||||
func (i *HandlerInput) Buffer() *bytes.Buffer {
|
||||
return i.getBuffer(false)
|
||||
// String returns the logging content formatted by default logging handler.
|
||||
func (i *HandlerInput) String(withColor ...bool) string {
|
||||
formatWithColor := false
|
||||
if len(withColor) > 0 {
|
||||
formatWithColor = withColor[0]
|
||||
}
|
||||
return i.getDefaultBuffer(formatWithColor).String()
|
||||
}
|
||||
|
||||
func (i *HandlerInput) getBuffer(withColor bool) *bytes.Buffer {
|
||||
func (i *HandlerInput) getDefaultBuffer(withColor bool) *bytes.Buffer {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if i.TimeFormat != "" {
|
||||
buffer.WriteString(i.TimeFormat)
|
||||
}
|
||||
if i.LevelFormat != "" {
|
||||
if withColor {
|
||||
i.addStringToBuffer(buffer, i.logger.getColoredStr(
|
||||
i.logger.getColorByLevel(i.Level), i.LevelFormat,
|
||||
i.addStringToBuffer(buffer, i.Logger.getColoredStr(
|
||||
i.Logger.getColorByLevel(i.Level), i.LevelFormat,
|
||||
))
|
||||
} else {
|
||||
i.addStringToBuffer(buffer, i.LevelFormat)
|
||||
@ -84,18 +86,23 @@ func (i *HandlerInput) getBuffer(withColor bool) *bytes.Buffer {
|
||||
return buffer
|
||||
}
|
||||
|
||||
// String retrieves and returns the logging content handled by default handler.
|
||||
func (i *HandlerInput) String() string {
|
||||
return i.Buffer().String()
|
||||
func (i *HandlerInput) getRealBuffer(withColor bool) *bytes.Buffer {
|
||||
if i.Buffer.Len() > 0 {
|
||||
return i.Buffer
|
||||
}
|
||||
return i.getDefaultBuffer(withColor)
|
||||
}
|
||||
|
||||
// Next calls the next logging handler in middleware way.
|
||||
func (i *HandlerInput) Next() {
|
||||
if len(i.logger.config.Handlers)-1 > i.index {
|
||||
i.index++
|
||||
i.logger.config.Handlers[i.index](i.Ctx, i)
|
||||
} else {
|
||||
// The last handler is the default handler.
|
||||
defaultHandler(i.Ctx, i)
|
||||
// defaultHandler is the default handler for logger.
|
||||
func defaultHandler(ctx context.Context, in *HandlerInput) {
|
||||
in.Logger.doDefaultPrint(ctx, in)
|
||||
}
|
||||
|
||||
func (i *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, strings ...string) {
|
||||
for _, s := range strings {
|
||||
if buffer.Len() > 0 {
|
||||
buffer.WriteByte(' ')
|
||||
}
|
||||
buffer.WriteString(s)
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ import (
|
||||
var arrayForHandlerTest1 = garray.NewStrArray()
|
||||
|
||||
func customHandler1(ctx context.Context, input *glog.HandlerInput) {
|
||||
arrayForHandlerTest1.Append(input.String())
|
||||
arrayForHandlerTest1.Append(input.String(false))
|
||||
input.Next()
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ func TestLogger_SetHandlers1(t *testing.T) {
|
||||
var arrayForHandlerTest2 = garray.NewStrArray()
|
||||
|
||||
func customHandler2(ctx context.Context, input *glog.HandlerInput) {
|
||||
arrayForHandlerTest2.Append(input.String())
|
||||
arrayForHandlerTest2.Append(input.String(false))
|
||||
}
|
||||
|
||||
func TestLogger_SetHandlers2(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user