123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- package logx
- import (
- "context"
- "encoding/json"
- "fmt"
- "io"
- "strings"
- "sync/atomic"
- "testing"
- "time"
- "github.com/stretchr/testify/assert"
- "go.opentelemetry.io/otel"
- sdktrace "go.opentelemetry.io/otel/sdk/trace"
- )
- func TestTraceLog(t *testing.T) {
- SetLevel(InfoLevel)
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id")
- defer span.End()
- WithContext(ctx).Info(testlog)
- validate(t, w.String(), true, true)
- }
- func TestTraceDebug(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
- defer span.End()
- l := WithContext(ctx)
- SetLevel(DebugLevel)
- l.WithDuration(time.Second).Debug(testlog)
- assert.True(t, strings.Contains(w.String(), traceKey))
- assert.True(t, strings.Contains(w.String(), spanKey))
- w.Reset()
- l.WithDuration(time.Second).Debugf(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Debugv(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Debugv(testobj)
- validateContentType(t, w.String(), map[string]any{}, true, true)
- w.Reset()
- l.WithDuration(time.Second).Debugw(testlog, Field("foo", "bar"))
- validate(t, w.String(), true, true)
- assert.True(t, strings.Contains(w.String(), "foo"), w.String())
- assert.True(t, strings.Contains(w.String(), "bar"), w.String())
- }
- func TestTraceError(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id")
- defer span.End()
- var nilCtx context.Context
- l := WithContext(context.Background())
- l = l.WithContext(nilCtx)
- l = l.WithContext(ctx)
- SetLevel(ErrorLevel)
- l.WithDuration(time.Second).Error(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Errorf(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Errorv(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Errorv(testobj)
- validateContentType(t, w.String(), map[string]any{}, true, true)
- w.Reset()
- l.WithDuration(time.Second).Errorw(testlog, Field("basket", "ball"))
- validate(t, w.String(), true, true)
- assert.True(t, strings.Contains(w.String(), "basket"), w.String())
- assert.True(t, strings.Contains(w.String(), "ball"), w.String())
- }
- func TestTraceInfo(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id")
- defer span.End()
- SetLevel(InfoLevel)
- l := WithContext(ctx)
- l.WithDuration(time.Second).Info(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infof(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infov(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infov(testobj)
- validateContentType(t, w.String(), map[string]any{}, true, true)
- w.Reset()
- l.WithDuration(time.Second).Infow(testlog, Field("basket", "ball"))
- validate(t, w.String(), true, true)
- assert.True(t, strings.Contains(w.String(), "basket"), w.String())
- assert.True(t, strings.Contains(w.String(), "ball"), w.String())
- }
- func TestTraceInfoConsole(t *testing.T) {
- old := atomic.SwapUint32(&encoding, jsonEncodingType)
- defer atomic.StoreUint32(&encoding, old)
- w := new(mockWriter)
- o := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(o)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id")
- defer span.End()
- l := WithContext(ctx)
- SetLevel(InfoLevel)
- l.WithDuration(time.Second).Info(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infof(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infov(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Infov(testobj)
- validateContentType(t, w.String(), map[string]any{}, true, true)
- }
- func TestTraceSlow(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- otp := otel.GetTracerProvider()
- tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
- otel.SetTracerProvider(tp)
- defer otel.SetTracerProvider(otp)
- ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id")
- defer span.End()
- l := WithContext(ctx)
- SetLevel(InfoLevel)
- l.WithDuration(time.Second).Slow(testlog)
- assert.True(t, strings.Contains(w.String(), traceKey))
- assert.True(t, strings.Contains(w.String(), spanKey))
- w.Reset()
- l.WithDuration(time.Second).Slowf(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Slowv(testlog)
- validate(t, w.String(), true, true)
- w.Reset()
- l.WithDuration(time.Second).Slowv(testobj)
- validateContentType(t, w.String(), map[string]any{}, true, true)
- w.Reset()
- l.WithDuration(time.Second).Sloww(testlog, Field("basket", "ball"))
- validate(t, w.String(), true, true)
- assert.True(t, strings.Contains(w.String(), "basket"), w.String())
- assert.True(t, strings.Contains(w.String(), "ball"), w.String())
- }
- func TestTraceWithoutContext(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- l := WithContext(context.Background())
- SetLevel(InfoLevel)
- l.WithDuration(time.Second).Info(testlog)
- validate(t, w.String(), false, false)
- w.Reset()
- l.WithDuration(time.Second).Infof(testlog)
- validate(t, w.String(), false, false)
- }
- func TestLogWithFields(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- ctx := ContextWithFields(context.Background(), Field("foo", "bar"))
- l := WithContext(ctx)
- SetLevel(InfoLevel)
- l.Info(testlog)
- var val mockValue
- assert.Nil(t, json.Unmarshal([]byte(w.String()), &val))
- assert.Equal(t, "bar", val.Foo)
- }
- func TestLogWithCallerSkip(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- l := WithCallerSkip(1).WithCallerSkip(0)
- p := func(v string) {
- l.Info(v)
- }
- file, line := getFileLine()
- p(testlog)
- assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
- w.Reset()
- l = WithCallerSkip(0).WithCallerSkip(1)
- file, line = getFileLine()
- p(testlog)
- assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
- }
- func TestLoggerWithFields(t *testing.T) {
- w := new(mockWriter)
- old := writer.Swap(w)
- writer.lock.RLock()
- defer func() {
- writer.lock.RUnlock()
- writer.Store(old)
- }()
- l := WithContext(context.Background()).WithFields(Field("foo", "bar"))
- l.Info(testlog)
- var val mockValue
- assert.Nil(t, json.Unmarshal([]byte(w.String()), &val))
- assert.Equal(t, "bar", val.Foo)
- }
- func validate(t *testing.T, body string, expectedTrace, expectedSpan bool) {
- var val mockValue
- dec := json.NewDecoder(strings.NewReader(body))
- for {
- var doc mockValue
- err := dec.Decode(&doc)
- if err == io.EOF {
- // all done
- break
- }
- if err != nil {
- continue
- }
- val = doc
- }
- assert.Equal(t, expectedTrace, len(val.Trace) > 0, body)
- assert.Equal(t, expectedSpan, len(val.Span) > 0, body)
- }
- func validateContentType(t *testing.T, body string, expectedType any, expectedTrace, expectedSpan bool) {
- var val mockValue
- dec := json.NewDecoder(strings.NewReader(body))
- for {
- var doc mockValue
- err := dec.Decode(&doc)
- if err == io.EOF {
- // all done
- break
- }
- if err != nil {
- continue
- }
- val = doc
- }
- assert.IsType(t, expectedType, val.Content, body)
- assert.Equal(t, expectedTrace, len(val.Trace) > 0, body)
- assert.Equal(t, expectedSpan, len(val.Span) > 0, body)
- }
- type mockValue struct {
- Trace string `json:"trace"`
- Span string `json:"span"`
- Foo string `json:"foo"`
- Content any `json:"content"`
- }
|