mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
add context id feature for package gctx/glog
This commit is contained in:
@ -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
51
os/gctx/gctx_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user