github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/zlog/dynamic_level_test.go (about)

     1  package zlog
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"go.uber.org/zap"
    10  	"go.uber.org/zap/zapcore"
    11  )
    12  
    13  func TestDynamicLevelCore(t *testing.T) {
    14  	buf := &bytes.Buffer{}
    15  	logger, _, err := NewWithOutput(&Config{Development: false, Level: "error"}, zapcore.AddSync(buf))
    16  	assert.Nil(t, err)
    17  
    18  	// assert we get a dynamicLevelCore
    19  	_ = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
    20  		_, ok := core.(*dynamicLevelCore)
    21  		assert.True(t, ok)
    22  		return core
    23  	}))
    24  
    25  	// the level is "error", these messages won't be logged
    26  	logger.Debug("debug message 1")
    27  	logger.Info("info message 1")
    28  	logger.Warn("warn message 1")
    29  
    30  	// this error message will be logged
    31  	logger.Error("error message 1")
    32  
    33  	got1 := buf.String()
    34  	assert.NotContains(t, got1, "debug message 1")
    35  	assert.NotContains(t, got1, "info message 1")
    36  	assert.NotContains(t, got1, "warn message 1")
    37  	assert.Contains(t, got1, "error message 1")
    38  
    39  	// change level to debug
    40  	logger = logger.WithOptions(zap.WrapCore(changeLevel(DebugLevel)))
    41  	logger.Debug("debug message 2")
    42  	logger.Info("info message 2")
    43  	logger.Warn("warn message 2")
    44  	logger.Error("error message 2")
    45  
    46  	got2 := buf.String()
    47  	assert.Contains(t, got2, "debug message 2")
    48  	assert.Contains(t, got2, "info message 2")
    49  	assert.Contains(t, got2, "warn message 2")
    50  	assert.Contains(t, got2, "error message 2")
    51  }
    52  
    53  func TestDynamicLevelCore_ChangeLevelWithCtx(t *testing.T) {
    54  	var buf = &bytes.Buffer{}
    55  	var _replace = func(buf *bytes.Buffer) func() {
    56  		cfg := &Config{
    57  			Level: "warn",
    58  			GlobalConfig: GlobalConfig{
    59  				CtxHandler: CtxHandler{
    60  					WithCtx: func(ctx context.Context) (result CtxResult) {
    61  						if ctx.Value("level") != nil {
    62  							level := ctx.Value("level").(Level)
    63  							result.Level = &level
    64  						}
    65  						return result
    66  					},
    67  				},
    68  			},
    69  		}
    70  		l, p, err := NewWithOutput(cfg, zapcore.AddSync(buf))
    71  		if err != nil {
    72  			panic(err)
    73  		}
    74  		return ReplaceGlobals(l, p)
    75  	}
    76  	defer _replace(buf)()
    77  
    78  	// the level is "warn", this info message won't be logged
    79  	ctx1 := context.Background()
    80  	WithCtx(ctx1).Info("info message 1")
    81  
    82  	got1 := buf.String()
    83  	assert.NotContains(t, got1, "info message 1")
    84  
    85  	// set level to "info" from ctx, info messages will be logged
    86  	ctx2 := context.WithValue(context.Background(), "level", InfoLevel)
    87  	WithCtx(ctx2).Debug("debug message 2")
    88  	WithCtx(ctx2).Info("info message 2")
    89  
    90  	got2 := buf.String()
    91  	assert.NotContains(t, got2, "debug message 2")
    92  	assert.Contains(t, got2, "info message 2")
    93  }
    94  
    95  var (
    96  	benchmarkMessage = "some test debug message is not too long and not too short"
    97  	benchmarkFields  = []zap.Field{
    98  		zap.String("key1", "value1"),
    99  		zap.String("some_key_2", "some_value2"),
   100  		zap.Int64("some_key_3", 183491839141471),
   101  		zap.Int64s("some_slice_key_4", []int64{18412, 1312490194301, 318431849, 18912438918941}),
   102  	}
   103  )
   104  
   105  func BenchmarkZapCore(b *testing.B) {
   106  	logger := newBenchmarkZapCoreLogger()
   107  
   108  	b.ResetTimer()
   109  	b.ReportAllocs()
   110  	for i := 0; i < b.N; i++ {
   111  		logger.Trace(benchmarkMessage, benchmarkFields...)
   112  		logger.Debug(benchmarkMessage, benchmarkFields...)
   113  		logger.Info(benchmarkMessage, benchmarkFields...)
   114  		logger.Warn(benchmarkMessage, benchmarkFields...)
   115  	}
   116  }
   117  
   118  func BenchmarkDynamicLevelCore(b *testing.B) {
   119  	logger := newBenchmarkDynamicLevelCoreLogger()
   120  
   121  	b.ResetTimer()
   122  	b.ReportAllocs()
   123  	for i := 0; i < b.N; i++ {
   124  		logger.Trace(benchmarkMessage, benchmarkFields...)
   125  		logger.Debug(benchmarkMessage, benchmarkFields...)
   126  		logger.Info(benchmarkMessage, benchmarkFields...)
   127  		logger.Warn(benchmarkMessage, benchmarkFields...)
   128  	}
   129  }
   130  
   131  type discardWriter struct{}
   132  
   133  func (w *discardWriter) Write(p []byte) (n int, err error) {
   134  	return len(p), nil
   135  }
   136  
   137  func (w *discardWriter) Sync() error {
   138  	return nil
   139  }
   140  
   141  func newBenchmarkZapCoreLogger() Logger {
   142  	logger, _, err := NewWithOutput(&Config{Development: false, Level: "info"}, &discardWriter{})
   143  	if err != nil {
   144  		panic(err)
   145  	}
   146  
   147  	// Make sure we unwrap the dynamic level wrapper.
   148  	logger = logger.WithOptions(zap.WrapCore(unwrapDynamicLevelCore))
   149  	_ = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
   150  		if _, ok := core.(*dynamicLevelCore); ok {
   151  			panic("core is wrapped by dynamicLevelCore")
   152  		}
   153  		return core
   154  	}))
   155  	return Logger{Logger: logger}
   156  }
   157  
   158  func newBenchmarkDynamicLevelCoreLogger() Logger {
   159  	logger, _, err := NewWithOutput(&Config{Development: false, Level: "info"}, &discardWriter{})
   160  	if err != nil {
   161  		panic(err)
   162  	}
   163  
   164  	// Make sure we get a wrapped dynamic level core.
   165  	logger = logger.WithOptions(zap.WrapCore(changeLevel(DebugLevel)))
   166  	_ = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
   167  		if _, ok := core.(*dynamicLevelCore); !ok {
   168  			panic("core is not wrapped by dynamicLevelCore")
   169  		}
   170  		return core
   171  	}))
   172  	return Logger{Logger: logger}
   173  }