github.com/lingyao2333/mo-zero@v1.4.1/core/logx/richlogger_test.go (about) 1 package logx 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "strings" 9 "sync/atomic" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 "go.opentelemetry.io/otel" 15 sdktrace "go.opentelemetry.io/otel/sdk/trace" 16 ) 17 18 func TestTraceLog(t *testing.T) { 19 SetLevel(InfoLevel) 20 w := new(mockWriter) 21 old := writer.Swap(w) 22 writer.lock.RLock() 23 defer func() { 24 writer.lock.RUnlock() 25 writer.Store(old) 26 }() 27 28 otp := otel.GetTracerProvider() 29 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 30 otel.SetTracerProvider(tp) 31 defer otel.SetTracerProvider(otp) 32 33 ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id") 34 defer span.End() 35 36 WithContext(ctx).Info(testlog) 37 validate(t, w.String(), true, true) 38 } 39 40 func TestTraceDebug(t *testing.T) { 41 w := new(mockWriter) 42 old := writer.Swap(w) 43 writer.lock.RLock() 44 defer func() { 45 writer.lock.RUnlock() 46 writer.Store(old) 47 }() 48 49 otp := otel.GetTracerProvider() 50 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 51 otel.SetTracerProvider(tp) 52 defer otel.SetTracerProvider(otp) 53 54 ctx, span := tp.Tracer("foo").Start(context.Background(), "bar") 55 defer span.End() 56 57 l := WithContext(ctx) 58 SetLevel(DebugLevel) 59 l.WithDuration(time.Second).Debug(testlog) 60 assert.True(t, strings.Contains(w.String(), traceKey)) 61 assert.True(t, strings.Contains(w.String(), spanKey)) 62 w.Reset() 63 l.WithDuration(time.Second).Debugf(testlog) 64 validate(t, w.String(), true, true) 65 w.Reset() 66 l.WithDuration(time.Second).Debugv(testlog) 67 validate(t, w.String(), true, true) 68 w.Reset() 69 l.WithDuration(time.Second).Debugw(testlog, Field("foo", "bar")) 70 validate(t, w.String(), true, true) 71 assert.True(t, strings.Contains(w.String(), "foo"), w.String()) 72 assert.True(t, strings.Contains(w.String(), "bar"), w.String()) 73 } 74 75 func TestTraceError(t *testing.T) { 76 w := new(mockWriter) 77 old := writer.Swap(w) 78 writer.lock.RLock() 79 defer func() { 80 writer.lock.RUnlock() 81 writer.Store(old) 82 }() 83 84 otp := otel.GetTracerProvider() 85 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 86 otel.SetTracerProvider(tp) 87 defer otel.SetTracerProvider(otp) 88 89 ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id") 90 defer span.End() 91 92 var nilCtx context.Context 93 l := WithContext(context.Background()) 94 l = l.WithContext(nilCtx) 95 l = l.WithContext(ctx) 96 SetLevel(ErrorLevel) 97 l.WithDuration(time.Second).Error(testlog) 98 validate(t, w.String(), true, true) 99 w.Reset() 100 l.WithDuration(time.Second).Errorf(testlog) 101 validate(t, w.String(), true, true) 102 w.Reset() 103 l.WithDuration(time.Second).Errorv(testlog) 104 validate(t, w.String(), true, true) 105 w.Reset() 106 l.WithDuration(time.Second).Errorw(testlog, Field("basket", "ball")) 107 validate(t, w.String(), true, true) 108 assert.True(t, strings.Contains(w.String(), "basket"), w.String()) 109 assert.True(t, strings.Contains(w.String(), "ball"), w.String()) 110 } 111 112 func TestTraceInfo(t *testing.T) { 113 w := new(mockWriter) 114 old := writer.Swap(w) 115 writer.lock.RLock() 116 defer func() { 117 writer.lock.RUnlock() 118 writer.Store(old) 119 }() 120 121 otp := otel.GetTracerProvider() 122 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 123 otel.SetTracerProvider(tp) 124 defer otel.SetTracerProvider(otp) 125 126 ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id") 127 defer span.End() 128 129 SetLevel(InfoLevel) 130 l := WithContext(ctx) 131 l.WithDuration(time.Second).Info(testlog) 132 validate(t, w.String(), true, true) 133 w.Reset() 134 l.WithDuration(time.Second).Infof(testlog) 135 validate(t, w.String(), true, true) 136 w.Reset() 137 l.WithDuration(time.Second).Infov(testlog) 138 validate(t, w.String(), true, true) 139 w.Reset() 140 l.WithDuration(time.Second).Infow(testlog, Field("basket", "ball")) 141 validate(t, w.String(), true, true) 142 assert.True(t, strings.Contains(w.String(), "basket"), w.String()) 143 assert.True(t, strings.Contains(w.String(), "ball"), w.String()) 144 } 145 146 func TestTraceInfoConsole(t *testing.T) { 147 old := atomic.SwapUint32(&encoding, jsonEncodingType) 148 defer atomic.StoreUint32(&encoding, old) 149 150 w := new(mockWriter) 151 o := writer.Swap(w) 152 writer.lock.RLock() 153 defer func() { 154 writer.lock.RUnlock() 155 writer.Store(o) 156 }() 157 158 otp := otel.GetTracerProvider() 159 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 160 otel.SetTracerProvider(tp) 161 defer otel.SetTracerProvider(otp) 162 163 ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id") 164 defer span.End() 165 166 l := WithContext(ctx) 167 SetLevel(InfoLevel) 168 l.WithDuration(time.Second).Info(testlog) 169 validate(t, w.String(), true, true) 170 w.Reset() 171 l.WithDuration(time.Second).Infof(testlog) 172 validate(t, w.String(), true, true) 173 w.Reset() 174 l.WithDuration(time.Second).Infov(testlog) 175 validate(t, w.String(), true, true) 176 } 177 178 func TestTraceSlow(t *testing.T) { 179 w := new(mockWriter) 180 old := writer.Swap(w) 181 writer.lock.RLock() 182 defer func() { 183 writer.lock.RUnlock() 184 writer.Store(old) 185 }() 186 187 otp := otel.GetTracerProvider() 188 tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample())) 189 otel.SetTracerProvider(tp) 190 defer otel.SetTracerProvider(otp) 191 192 ctx, span := tp.Tracer("trace-id").Start(context.Background(), "span-id") 193 defer span.End() 194 195 l := WithContext(ctx) 196 SetLevel(InfoLevel) 197 l.WithDuration(time.Second).Slow(testlog) 198 assert.True(t, strings.Contains(w.String(), traceKey)) 199 assert.True(t, strings.Contains(w.String(), spanKey)) 200 w.Reset() 201 l.WithDuration(time.Second).Slowf(testlog) 202 validate(t, w.String(), true, true) 203 w.Reset() 204 l.WithDuration(time.Second).Slowv(testlog) 205 validate(t, w.String(), true, true) 206 w.Reset() 207 l.WithDuration(time.Second).Sloww(testlog, Field("basket", "ball")) 208 validate(t, w.String(), true, true) 209 assert.True(t, strings.Contains(w.String(), "basket"), w.String()) 210 assert.True(t, strings.Contains(w.String(), "ball"), w.String()) 211 } 212 213 func TestTraceWithoutContext(t *testing.T) { 214 w := new(mockWriter) 215 old := writer.Swap(w) 216 writer.lock.RLock() 217 defer func() { 218 writer.lock.RUnlock() 219 writer.Store(old) 220 }() 221 222 l := WithContext(context.Background()) 223 SetLevel(InfoLevel) 224 l.WithDuration(time.Second).Info(testlog) 225 validate(t, w.String(), false, false) 226 w.Reset() 227 l.WithDuration(time.Second).Infof(testlog) 228 validate(t, w.String(), false, false) 229 } 230 231 func TestLogWithFields(t *testing.T) { 232 w := new(mockWriter) 233 old := writer.Swap(w) 234 writer.lock.RLock() 235 defer func() { 236 writer.lock.RUnlock() 237 writer.Store(old) 238 }() 239 240 ctx := ContextWithFields(context.Background(), Field("foo", "bar")) 241 l := WithContext(ctx) 242 SetLevel(InfoLevel) 243 l.Info(testlog) 244 245 var val mockValue 246 assert.Nil(t, json.Unmarshal([]byte(w.String()), &val)) 247 assert.Equal(t, "bar", val.Foo) 248 } 249 250 func TestLogWithCallerSkip(t *testing.T) { 251 w := new(mockWriter) 252 old := writer.Swap(w) 253 writer.lock.RLock() 254 defer func() { 255 writer.lock.RUnlock() 256 writer.Store(old) 257 }() 258 259 l := WithCallerSkip(1).WithCallerSkip(0) 260 p := func(v string) { 261 l.Info(v) 262 } 263 264 file, line := getFileLine() 265 p(testlog) 266 assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1))) 267 268 w.Reset() 269 l = WithCallerSkip(0).WithCallerSkip(1) 270 file, line = getFileLine() 271 p(testlog) 272 assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1))) 273 } 274 275 func TestLoggerWithFields(t *testing.T) { 276 w := new(mockWriter) 277 old := writer.Swap(w) 278 writer.lock.RLock() 279 defer func() { 280 writer.lock.RUnlock() 281 writer.Store(old) 282 }() 283 284 l := WithContext(context.Background()).WithFields(Field("foo", "bar")) 285 l.Info(testlog) 286 287 var val mockValue 288 assert.Nil(t, json.Unmarshal([]byte(w.String()), &val)) 289 assert.Equal(t, "bar", val.Foo) 290 } 291 292 func validate(t *testing.T, body string, expectedTrace, expectedSpan bool) { 293 var val mockValue 294 dec := json.NewDecoder(strings.NewReader(body)) 295 296 for { 297 var doc mockValue 298 err := dec.Decode(&doc) 299 if err == io.EOF { 300 // all done 301 break 302 } 303 if err != nil { 304 continue 305 } 306 307 val = doc 308 } 309 310 assert.Equal(t, expectedTrace, len(val.Trace) > 0, body) 311 assert.Equal(t, expectedSpan, len(val.Span) > 0, body) 312 } 313 314 type mockValue struct { 315 Trace string `json:"trace"` 316 Span string `json:"span"` 317 Foo string `json:"foo"` 318 }