From 13ecbc263e4b852d5f2a82c67a13386d2611690c Mon Sep 17 00:00:00 2001 From: John Guo Date: Thu, 12 Aug 2021 21:58:06 +0800 Subject: [PATCH] improve handler feature for package glog --- .example/os/glog/glog_CtxKeys.go | 14 +++ ...og_config1.go => glog_SetConfigWithMap.go} | 2 +- ...{glog_async1.go => glog_async_chaining.go} | 5 +- ...glog_async2.go => glog_async_configure.go} | 7 +- .example/os/glog/glog_category.go | 5 +- .example/os/glog/glog_ctx.go | 14 --- .example/os/glog/glog_debug.go | 6 +- .example/os/glog/glog_file.go | 21 ++-- .example/os/glog/glog_flags.go | 14 +-- .example/os/glog/glog_gerror.go | 6 +- .example/os/glog/glog_json.go | 5 +- .example/os/glog/glog_level.go | 8 +- .example/os/glog/glog_level_prefix.go | 6 +- .example/os/glog/glog_line.go | 6 +- .example/os/glog/glog_line2.go | 6 +- .example/os/glog/glog_path.go | 5 +- .example/os/glog/glog_pool.go | 6 +- .example/os/glog/glog_prefix.go | 9 +- .example/os/glog/glog_stack.go | 10 +- .example/os/glog/glog_stdout.go | 15 +-- .example/os/glog/glog_writer_hook.go | 4 +- .example/os/glog/handler/glog_handler_json.go | 42 ++++++++ .../gmlock/{locker1.go => 1.lock&unlock.go} | 6 +- .../os/gmlock/{locker3.go => 2.trylock.go} | 0 .../{locker4.go => 3.lock_conflicts.go} | 0 .../{test_locker.go => 4.test_deadlock.go} | 13 +-- .example/os/gmlock/locker2.go | 23 ----- .example/os/gmlock/test_mutex.go | 95 ------------------- os/glog/glog_logger.go | 43 +++++---- os/glog/glog_logger_config.go | 4 +- os/glog/glog_logger_handler.go | 91 ++++++++++-------- os/glog/glog_z_unit_handler_test.go | 4 +- 32 files changed, 214 insertions(+), 281 deletions(-) create mode 100644 .example/os/glog/glog_CtxKeys.go rename .example/os/glog/{glog_config1.go => glog_SetConfigWithMap.go} (81%) rename .example/os/glog/{glog_async1.go => glog_async_chaining.go} (60%) rename .example/os/glog/{glog_async2.go => glog_async_configure.go} (54%) delete mode 100644 .example/os/glog/glog_ctx.go create mode 100644 .example/os/glog/handler/glog_handler_json.go rename .example/os/gmlock/{locker1.go => 1.lock&unlock.go} (86%) rename .example/os/gmlock/{locker3.go => 2.trylock.go} (100%) rename .example/os/gmlock/{locker4.go => 3.lock_conflicts.go} (100%) rename .example/os/gmlock/{test_locker.go => 4.test_deadlock.go} (91%) delete mode 100644 .example/os/gmlock/locker2.go delete mode 100644 .example/os/gmlock/test_mutex.go diff --git a/.example/os/glog/glog_CtxKeys.go b/.example/os/glog/glog_CtxKeys.go new file mode 100644 index 000000000..3eb6fcc13 --- /dev/null +++ b/.example/os/glog/glog_CtxKeys.go @@ -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) +} diff --git a/.example/os/glog/glog_config1.go b/.example/os/glog/glog_SetConfigWithMap.go similarity index 81% rename from .example/os/glog/glog_config1.go rename to .example/os/glog/glog_SetConfigWithMap.go index fc3c5a3cb..06361b583 100644 --- a/.example/os/glog/glog_config1.go +++ b/.example/os/glog/glog_SetConfigWithMap.go @@ -6,7 +6,7 @@ import ( ) func main() { - err := glog.SetConfigWithMap(g.Map{ + err := g.Log().SetConfigWithMap(g.Map{ "prefix": "[TEST]", }) if err != nil { diff --git a/.example/os/glog/glog_async1.go b/.example/os/glog/glog_async_chaining.go similarity index 60% rename from .example/os/glog/glog_async1.go rename to .example/os/glog/glog_async_chaining.go index 1f17d1c25..a3dda3cd6 100644 --- a/.example/os/glog/glog_async1.go +++ b/.example/os/glog/glog_async_chaining.go @@ -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) } diff --git a/.example/os/glog/glog_async2.go b/.example/os/glog/glog_async_configure.go similarity index 54% rename from .example/os/glog/glog_async2.go rename to .example/os/glog/glog_async_configure.go index 63d6f4278..e9cc86bd6 100644 --- a/.example/os/glog/glog_async2.go +++ b/.example/os/glog/glog_async_configure.go @@ -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) } diff --git a/.example/os/glog/glog_category.go b/.example/os/glog/glog_category.go index 47c56ccf4..2be6ee80b 100644 --- a/.example/os/glog/glog_category.go +++ b/.example/os/glog/glog_category.go @@ -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) diff --git a/.example/os/glog/glog_ctx.go b/.example/os/glog/glog_ctx.go deleted file mode 100644 index b4ca21ea2..000000000 --- a/.example/os/glog/glog_ctx.go +++ /dev/null @@ -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) -} diff --git a/.example/os/glog/glog_debug.go b/.example/os/glog/glog_debug.go index 64ec9c277..579aefe3b 100644 --- a/.example/os/glog/glog_debug.go +++ b/.example/os/glog/glog_debug.go @@ -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) } } diff --git a/.example/os/glog/glog_file.go b/.example/os/glog/glog_file.go index 6a0843dac..9e4f6b858 100644 --- a/.example/os/glog/glog_file.go +++ b/.example/os/glog/glog_file.go @@ -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) diff --git a/.example/os/glog/glog_flags.go b/.example/os/glog/glog_flags.go index ebb3894c3..f3ed32ce3 100644 --- a/.example/os/glog/glog_flags.go +++ b/.example/os/glog/glog_flags.go @@ -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") } diff --git a/.example/os/glog/glog_gerror.go b/.example/os/glog/glog_gerror.go index cbcf405c0..6fb54f726 100644 --- a/.example/os/glog/glog_gerror.go +++ b/.example/os/glog/glog_gerror.go @@ -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() { diff --git a/.example/os/glog/glog_json.go b/.example/os/glog/glog_json.go index f1e28944e..1075bf056 100644 --- a/.example/os/glog/glog_json.go +++ b/.example/os/glog/glog_json.go @@ -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"}) } diff --git a/.example/os/glog/glog_level.go b/.example/os/glog/glog_level.go index c1e07f736..e8c7b917b 100644 --- a/.example/os/glog/glog_level.go +++ b/.example/os/glog/glog_level.go @@ -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") } diff --git a/.example/os/glog/glog_level_prefix.go b/.example/os/glog/glog_level_prefix.go index cd9a7e9f7..014c7c288 100644 --- a/.example/os/glog/glog_level_prefix.go +++ b/.example/os/glog/glog_level_prefix.go @@ -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") } diff --git a/.example/os/glog/glog_line.go b/.example/os/glog/glog_line.go index 4ee2ad1a1..5326cf867 100644 --- a/.example/os/glog/glog_line.go +++ b/.example/os/glog/glog_line.go @@ -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") } diff --git a/.example/os/glog/glog_line2.go b/.example/os/glog/glog_line2.go index b694f7b92..9fd8a60fc 100644 --- a/.example/os/glog/glog_line2.go +++ b/.example/os/glog/glog_line2.go @@ -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() { diff --git a/.example/os/glog/glog_path.go b/.example/os/glog/glog_path.go index 913a037ab..a7d0e4367 100644 --- a/.example/os/glog/glog_path.go +++ b/.example/os/glog/glog_path.go @@ -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) diff --git a/.example/os/glog/glog_pool.go b/.example/os/glog/glog_pool.go index 383b74367..960e85557 100644 --- a/.example/os/glog/glog_pool.go +++ b/.example/os/glog/glog_pool.go @@ -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) } } diff --git a/.example/os/glog/glog_prefix.go b/.example/os/glog/glog_prefix.go index 502467128..b803b9a4e 100644 --- a/.example/os/glog/glog_prefix.go +++ b/.example/os/glog/glog_prefix.go @@ -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") } diff --git a/.example/os/glog/glog_stack.go b/.example/os/glog/glog_stack.go index 1232c2bec..1dced6e69 100644 --- a/.example/os/glog/glog_stack.go +++ b/.example/os/glog/glog_stack.go @@ -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()) } diff --git a/.example/os/glog/glog_stdout.go b/.example/os/glog/glog_stdout.go index 4d2200028..c4ae4d6ba 100644 --- a/.example/os/glog/glog_stdout.go +++ b/.example/os/glog/glog_stdout.go @@ -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() } diff --git a/.example/os/glog/glog_writer_hook.go b/.example/os/glog/glog_writer_hook.go index 67e8863ca..365ec28f0 100644 --- a/.example/os/glog/glog_writer_hook.go +++ b/.example/os/glog/glog_writer_hook.go @@ -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) } diff --git a/.example/os/glog/handler/glog_handler_json.go b/.example/os/glog/handler/glog_handler_json.go new file mode 100644 index 000000000..ee4bb06e6 --- /dev/null +++ b/.example/os/glog/handler/glog_handler_json.go @@ -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") +} diff --git a/.example/os/gmlock/locker1.go b/.example/os/gmlock/1.lock&unlock.go similarity index 86% rename from .example/os/gmlock/locker1.go rename to .example/os/gmlock/1.lock&unlock.go index 946ae72b4..71a4d3534 100644 --- a/.example/os/gmlock/locker1.go +++ b/.example/os/gmlock/1.lock&unlock.go @@ -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) { diff --git a/.example/os/gmlock/locker3.go b/.example/os/gmlock/2.trylock.go similarity index 100% rename from .example/os/gmlock/locker3.go rename to .example/os/gmlock/2.trylock.go diff --git a/.example/os/gmlock/locker4.go b/.example/os/gmlock/3.lock_conflicts.go similarity index 100% rename from .example/os/gmlock/locker4.go rename to .example/os/gmlock/3.lock_conflicts.go diff --git a/.example/os/gmlock/test_locker.go b/.example/os/gmlock/4.test_deadlock.go similarity index 91% rename from .example/os/gmlock/test_locker.go rename to .example/os/gmlock/4.test_deadlock.go index 3600e36b6..b67cf7ddd 100644 --- a/.example/os/gmlock/test_locker.go +++ b/.example/os/gmlock/4.test_deadlock.go @@ -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() { diff --git a/.example/os/gmlock/locker2.go b/.example/os/gmlock/locker2.go deleted file mode 100644 index f340a25c9..000000000 --- a/.example/os/gmlock/locker2.go +++ /dev/null @@ -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() -} diff --git a/.example/os/gmlock/test_mutex.go b/.example/os/gmlock/test_mutex.go deleted file mode 100644 index c03874e70..000000000 --- a/.example/os/gmlock/test_mutex.go +++ /dev/null @@ -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!") -} diff --git a/os/glog/glog_logger.go b/os/glog/glog_logger.go index 04da63b88..8c8dd3716 100644 --- a/os/glog/glog_logger.go +++ b/os/glog/glog_logger.go @@ -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 +} diff --git a/os/glog/glog_logger_config.go b/os/glog/glog_logger_config.go index 33ed77043..705a56b0a 100644 --- a/os/glog/glog_logger_config.go +++ b/os/glog/glog_logger_config.go @@ -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. diff --git a/os/glog/glog_logger_handler.go b/os/glog/glog_logger_handler.go index 71056e848..4217f5a42 100644 --- a/os/glog/glog_logger_handler.go +++ b/os/glog/glog_logger_handler.go @@ -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) } } diff --git a/os/glog/glog_z_unit_handler_test.go b/os/glog/glog_z_unit_handler_test.go index 70acc0f5c..921beb9b5 100644 --- a/os/glog/glog_z_unit_handler_test.go +++ b/os/glog/glog_z_unit_handler_test.go @@ -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) {