contextlogger_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package logx
  2. import (
  3. "context"
  4. "encoding/json"
  5. "io"
  6. "strings"
  7. "sync/atomic"
  8. "testing"
  9. "time"
  10. "github.com/stretchr/testify/assert"
  11. "go.opentelemetry.io/otel"
  12. sdktrace "go.opentelemetry.io/otel/sdk/trace"
  13. )
  14. func TestTraceLog(t *testing.T) {
  15. SetLevel(InfoLevel)
  16. w := new(mockWriter)
  17. old := writer.Swap(w)
  18. writer.lock.RLock()
  19. defer func() {
  20. writer.lock.RUnlock()
  21. writer.Store(old)
  22. }()
  23. otp := otel.GetTracerProvider()
  24. tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
  25. otel.SetTracerProvider(tp)
  26. defer otel.SetTracerProvider(otp)
  27. ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
  28. defer span.End()
  29. WithContext(ctx).Info(testlog)
  30. validate(t, w.String(), true, true)
  31. }
  32. func TestTraceError(t *testing.T) {
  33. w := new(mockWriter)
  34. old := writer.Swap(w)
  35. writer.lock.RLock()
  36. defer func() {
  37. writer.lock.RUnlock()
  38. writer.Store(old)
  39. }()
  40. otp := otel.GetTracerProvider()
  41. tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
  42. otel.SetTracerProvider(tp)
  43. defer otel.SetTracerProvider(otp)
  44. ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
  45. defer span.End()
  46. var nilCtx context.Context
  47. l := WithContext(context.Background())
  48. l = l.WithContext(nilCtx)
  49. l = l.WithContext(ctx)
  50. SetLevel(ErrorLevel)
  51. l.WithDuration(time.Second).Error(testlog)
  52. validate(t, w.String(), true, true)
  53. w.Reset()
  54. l.WithDuration(time.Second).Errorf(testlog)
  55. validate(t, w.String(), true, true)
  56. w.Reset()
  57. l.WithDuration(time.Second).Errorv(testlog)
  58. validate(t, w.String(), true, true)
  59. w.Reset()
  60. l.WithDuration(time.Second).Errorw(testlog, Field("foo", "bar"))
  61. validate(t, w.String(), true, true)
  62. assert.True(t, strings.Contains(w.String(), "foo"), w.String())
  63. assert.True(t, strings.Contains(w.String(), "bar"), w.String())
  64. }
  65. func TestTraceInfo(t *testing.T) {
  66. w := new(mockWriter)
  67. old := writer.Swap(w)
  68. writer.lock.RLock()
  69. defer func() {
  70. writer.lock.RUnlock()
  71. writer.Store(old)
  72. }()
  73. otp := otel.GetTracerProvider()
  74. tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
  75. otel.SetTracerProvider(tp)
  76. defer otel.SetTracerProvider(otp)
  77. ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
  78. defer span.End()
  79. SetLevel(InfoLevel)
  80. l := WithContext(ctx)
  81. l.WithDuration(time.Second).Info(testlog)
  82. validate(t, w.String(), true, true)
  83. w.Reset()
  84. l.WithDuration(time.Second).Infof(testlog)
  85. validate(t, w.String(), true, true)
  86. w.Reset()
  87. l.WithDuration(time.Second).Infov(testlog)
  88. validate(t, w.String(), true, true)
  89. w.Reset()
  90. l.WithDuration(time.Second).Infow(testlog, Field("foo", "bar"))
  91. validate(t, w.String(), true, true)
  92. assert.True(t, strings.Contains(w.String(), "foo"), w.String())
  93. assert.True(t, strings.Contains(w.String(), "bar"), w.String())
  94. }
  95. func TestTraceInfoConsole(t *testing.T) {
  96. old := atomic.SwapUint32(&encoding, jsonEncodingType)
  97. defer atomic.StoreUint32(&encoding, old)
  98. w := new(mockWriter)
  99. o := writer.Swap(w)
  100. writer.lock.RLock()
  101. defer func() {
  102. writer.lock.RUnlock()
  103. writer.Store(o)
  104. }()
  105. otp := otel.GetTracerProvider()
  106. tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
  107. otel.SetTracerProvider(tp)
  108. defer otel.SetTracerProvider(otp)
  109. ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
  110. defer span.End()
  111. l := WithContext(ctx)
  112. SetLevel(InfoLevel)
  113. l.WithDuration(time.Second).Info(testlog)
  114. validate(t, w.String(), true, true)
  115. w.Reset()
  116. l.WithDuration(time.Second).Infof(testlog)
  117. validate(t, w.String(), true, true)
  118. w.Reset()
  119. l.WithDuration(time.Second).Infov(testlog)
  120. validate(t, w.String(), true, true)
  121. }
  122. func TestTraceSlow(t *testing.T) {
  123. w := new(mockWriter)
  124. old := writer.Swap(w)
  125. writer.lock.RLock()
  126. defer func() {
  127. writer.lock.RUnlock()
  128. writer.Store(old)
  129. }()
  130. otp := otel.GetTracerProvider()
  131. tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
  132. otel.SetTracerProvider(tp)
  133. defer otel.SetTracerProvider(otp)
  134. ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
  135. defer span.End()
  136. l := WithContext(ctx)
  137. SetLevel(InfoLevel)
  138. l.WithDuration(time.Second).Slow(testlog)
  139. assert.True(t, strings.Contains(w.String(), traceKey))
  140. assert.True(t, strings.Contains(w.String(), spanKey))
  141. w.Reset()
  142. l.WithDuration(time.Second).Slowf(testlog)
  143. validate(t, w.String(), true, true)
  144. w.Reset()
  145. l.WithDuration(time.Second).Slowv(testlog)
  146. validate(t, w.String(), true, true)
  147. w.Reset()
  148. l.WithDuration(time.Second).Sloww(testlog, Field("foo", "bar"))
  149. validate(t, w.String(), true, true)
  150. assert.True(t, strings.Contains(w.String(), "foo"), w.String())
  151. assert.True(t, strings.Contains(w.String(), "bar"), w.String())
  152. }
  153. func TestTraceWithoutContext(t *testing.T) {
  154. w := new(mockWriter)
  155. old := writer.Swap(w)
  156. writer.lock.RLock()
  157. defer func() {
  158. writer.lock.RUnlock()
  159. writer.Store(old)
  160. }()
  161. l := WithContext(context.Background())
  162. SetLevel(InfoLevel)
  163. l.WithDuration(time.Second).Info(testlog)
  164. validate(t, w.String(), false, false)
  165. w.Reset()
  166. l.WithDuration(time.Second).Infof(testlog)
  167. validate(t, w.String(), false, false)
  168. }
  169. func TestLogWithFields(t *testing.T) {
  170. w := new(mockWriter)
  171. old := writer.Swap(w)
  172. writer.lock.RLock()
  173. defer func() {
  174. writer.lock.RUnlock()
  175. writer.Store(old)
  176. }()
  177. ctx := WithFields(context.Background(), Field("foo", "bar"))
  178. l := WithContext(ctx)
  179. SetLevel(InfoLevel)
  180. l.Info(testlog)
  181. var val mockValue
  182. assert.Nil(t, json.Unmarshal([]byte(w.String()), &val))
  183. assert.Equal(t, "bar", val.Foo)
  184. }
  185. func validate(t *testing.T, body string, expectedTrace, expectedSpan bool) {
  186. var val mockValue
  187. dec := json.NewDecoder(strings.NewReader(body))
  188. for {
  189. var doc mockValue
  190. err := dec.Decode(&doc)
  191. if err == io.EOF {
  192. // all done
  193. break
  194. }
  195. if err != nil {
  196. continue
  197. }
  198. val = doc
  199. }
  200. assert.Equal(t, expectedTrace, len(val.Trace) > 0, body)
  201. assert.Equal(t, expectedSpan, len(val.Span) > 0, body)
  202. }
  203. type mockValue struct {
  204. Trace string `json:"trace"`
  205. Span string `json:"span"`
  206. Foo string `json:"foo"`
  207. }