add context id feature for package gctx/glog

This commit is contained in:
John Guo
2021-08-20 15:44:08 +08:00
parent 43180ef239
commit a229960218
5 changed files with 128 additions and 15 deletions

View File

@ -7,9 +7,54 @@
// Package gctx wraps context.Context and provides extra context features.
package gctx
import "context"
import (
"context"
"github.com/gogf/gf/util/guid"
)
type (
Ctx = context.Context // Ctx is short name alias for context.Context.
StrKey string // StrKey is a type for warps basic type string as context key.
)
const (
// CtxKey is custom tracing context key for context id.
// The context id a unique string for certain context.
CtxKey StrKey = "GoFrameCtxId"
)
// New creates and returns a context which contains context id.
func New() context.Context {
return WithCtx(context.Background())
}
// WithCtx creates and returns a context containing context id upon given parent context `ctx`.
func WithCtx(ctx context.Context) context.Context {
return WithPrefix(ctx, "")
}
// WithPrefix creates and returns a context containing context id upon given parent context `ctx`.
// The generated context id has custom prefix string specified by parameter `prefix`.
func WithPrefix(ctx context.Context, prefix string) context.Context {
return WithValue(ctx, prefix+getUniqueID())
}
// WithValue creates and returns a context containing context id upon given parent context `ctx`.
// The generated context id value is specified by parameter `value`.
func WithValue(ctx context.Context, value string) context.Context {
if value == "" {
return New()
}
return context.WithValue(ctx, CtxKey, value)
}
// Value retrieves and returns the context id from context.
func Value(ctx context.Context) string {
s, _ := ctx.Value(CtxKey).(string)
return s
}
// getUniqueID produces a global unique string.
func getUniqueID() string {
return guid.S()
}

51
os/gctx/gctx_test.go Normal file
View File

@ -0,0 +1,51 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gctx_test
import (
"context"
"github.com/gogf/gf/os/gctx"
"github.com/gogf/gf/text/gstr"
"testing"
"github.com/gogf/gf/test/gtest"
)
func Test_New(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ctx := gctx.New()
t.AssertNE(ctx, nil)
t.AssertNE(gctx.Value(ctx), "")
})
}
func Test_WithCtx(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ctx := context.WithValue(context.TODO(), "TEST", 1)
ctx = gctx.WithCtx(ctx)
t.AssertNE(gctx.Value(ctx), "")
t.Assert(ctx.Value("TEST"), 1)
})
}
func Test_WithPrefix(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ctx := context.WithValue(context.TODO(), "TEST", 1)
ctx = gctx.WithPrefix(ctx, "H-")
t.Assert(gstr.Contains(gctx.Value(ctx), "H-"), true)
t.Assert(ctx.Value("TEST"), 1)
})
}
func Test_WithValue(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ctx := context.WithValue(context.TODO(), "TEST", 1)
ctx = gctx.WithValue(ctx, "123")
t.Assert(gctx.Value(ctx), "123")
t.Assert(ctx.Value("TEST"), 1)
})
}

View File

@ -154,13 +154,17 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
if l.config.Flags&(F_FILE_LONG|F_FILE_SHORT|F_CALLER_FN) > 0 {
callerFnName, path, line := gdebug.CallerWithFilter(pathFilterKey, l.config.StSkip)
if l.config.Flags&F_CALLER_FN > 0 {
input.CallerFunc = fmt.Sprintf(`[%s]`, callerFnName)
if len(callerFnName) > 2 {
input.CallerFunc = fmt.Sprintf(`[%s]`, callerFnName)
}
}
if l.config.Flags&F_FILE_LONG > 0 {
input.CallerPath = fmt.Sprintf(`%s:%d:`, path, line)
}
if l.config.Flags&F_FILE_SHORT > 0 {
input.CallerPath = fmt.Sprintf(`%s:%d:`, gfile.Basename(path), line)
if line >= 0 && len(path) > 1 {
if l.config.Flags&F_FILE_LONG > 0 {
input.CallerPath = fmt.Sprintf(`%s:%d:`, path, line)
}
if l.config.Flags&F_FILE_SHORT > 0 {
input.CallerPath = fmt.Sprintf(`%s:%d:`, gfile.Basename(path), line)
}
}
}
// Prefix.
@ -173,26 +177,25 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
// Tracing values.
spanCtx := trace.SpanContextFromContext(ctx)
if traceId := spanCtx.TraceID(); traceId.IsValid() {
input.CtxStr = "{" + traceId.String() + "}"
input.CtxStr = traceId.String()
}
// Context values.
if len(l.config.CtxKeys) > 0 {
ctxStr := ""
for _, ctxKey := range l.config.CtxKeys {
var ctxValue interface{}
if ctxValue = ctx.Value(ctxKey); ctxValue == nil {
ctxValue = ctx.Value(gctx.StrKey(gconv.String(ctxKey)))
}
if ctxValue != nil {
if ctxStr != "" {
ctxStr += ", "
if input.CtxStr != "" {
input.CtxStr += ", "
}
ctxStr += gconv.String(ctxValue)
input.CtxStr += gconv.String(ctxValue)
}
}
if ctxStr != "" {
input.CtxStr += "{" + ctxStr + "}"
}
}
if input.CtxStr != "" {
input.CtxStr = "{" + input.CtxStr + "}"
}
}
var tempStr string

View File

@ -7,6 +7,7 @@
package glog
import (
"github.com/gogf/gf/os/gctx"
"io"
"strings"
"time"
@ -49,6 +50,7 @@ func DefaultConfig() Config {
File: defaultFileFormat,
Flags: F_TIME_STD,
Level: LEVEL_ALL,
CtxKeys: []interface{}{gctx.CtxKey},
StStatus: 1,
HeaderPrint: true,
StdoutPrint: true,
@ -163,6 +165,7 @@ func (l *Logger) SetStackFilter(filter string) {
// Note that multiple calls of this function will overwrite the previous set context keys.
func (l *Logger) SetCtxKeys(keys ...interface{}) {
l.config.CtxKeys = keys
l.config.CtxKeys = append(l.config.CtxKeys, gctx.CtxKey)
}
// AppendCtxKeys appends extra keys to logger.

View File

@ -10,6 +10,7 @@ import (
"bytes"
"context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gctx"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/test/gtest"
"github.com/gogf/gf/text/gstr"
@ -49,3 +50,13 @@ func Test_Ctx_Config(t *testing.T) {
t.Assert(gstr.Count(w.String(), "1 2 3"), 1)
})
}
func Test_Ctx_CtxKey(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
w := bytes.NewBuffer(nil)
l := glog.NewWithWriter(w)
l.Ctx(gctx.WithValue(context.TODO(), "abcdefg")).Print(1, 2, 3)
t.Assert(gstr.Count(w.String(), "abcdefg"), 1)
t.Assert(gstr.Count(w.String(), "1 2 3"), 1)
})
}