log_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package log
  2. import (
  3. "bytes"
  4. "github.com/stretchr/testify/require"
  5. "os"
  6. "testing"
  7. "time"
  8. )
  9. func TestMain(m *testing.M) {
  10. exitCode := m.Run()
  11. resetState()
  12. SetLevel(ErrorLevel) // For other modules!
  13. os.Exit(exitCode)
  14. }
  15. func TestLog_TagContextFieldFields(t *testing.T) {
  16. t.Cleanup(resetState)
  17. v := &fakeVisitor{
  18. UserID: "u_abc",
  19. IP: "1.2.3.4",
  20. }
  21. err := &fakeError{
  22. Code: 123,
  23. Message: "some error",
  24. }
  25. var out bytes.Buffer
  26. SetOutput(&out)
  27. SetFormat(JSONFormat)
  28. SetLevelOverride("tag", "stripe", DebugLevel)
  29. SetLevelOverride("number", "5", DebugLevel)
  30. Tag("mytag").
  31. Field("field2", 123).
  32. Field("field1", "value1").
  33. Time(time.Unix(123, 999000000).UTC()).
  34. Info("hi there %s", "phil")
  35. Tag("not-stripe").
  36. Debug("this message will not appear")
  37. With(v).
  38. Fields(Context{
  39. "stripe_customer_id": "acct_123",
  40. "stripe_subscription_id": "sub_123",
  41. }).
  42. Tag("stripe").
  43. Err(err).
  44. Time(time.Unix(456, 123000000).UTC()).
  45. Debug("Subscription status %s", "active")
  46. Field("number", 5).
  47. Time(time.Unix(777, 001000000).UTC()).
  48. Debug("The number 5 is an int, but the level override is a string")
  49. expected := `{"time":"1970-01-01T00:02:03.999Z","level":"INFO","message":"hi there phil","field1":"value1","field2":123,"tag":"mytag"}
  50. {"time":"1970-01-01T00:07:36.123Z","level":"DEBUG","message":"Subscription status active","error":"some error","error_code":123,"stripe_customer_id":"acct_123","stripe_subscription_id":"sub_123","tag":"stripe","user_id":"u_abc","visitor_ip":"1.2.3.4"}
  51. {"time":"1970-01-01T00:12:57Z","level":"DEBUG","message":"The number 5 is an int, but the level override is a string","number":5}
  52. `
  53. require.Equal(t, expected, out.String())
  54. }
  55. func TestLog_NoAllocIfNotPrinted(t *testing.T) {
  56. t.Cleanup(resetState)
  57. v := &fakeVisitor{
  58. UserID: "u_abc",
  59. IP: "1.2.3.4",
  60. }
  61. var out bytes.Buffer
  62. SetOutput(&out)
  63. SetFormat(JSONFormat)
  64. // Do not log, do not call contexters (because global level is INFO)
  65. v.contextCalled = false
  66. ev := With(v)
  67. ev.Debug("some message")
  68. require.False(t, v.contextCalled)
  69. require.Equal(t, "", ev.Timestamp)
  70. require.Equal(t, Level(0), ev.Level)
  71. require.Equal(t, "", ev.Message)
  72. require.Nil(t, ev.fields)
  73. // Logged because info level, contexters called
  74. v.contextCalled = false
  75. ev = With(v).Time(time.Unix(1111, 0).UTC())
  76. ev.Info("some message")
  77. require.True(t, v.contextCalled)
  78. require.NotNil(t, ev.fields)
  79. require.Equal(t, "1.2.3.4", ev.fields["visitor_ip"])
  80. // Not logged, but contexters called, because overrides exist
  81. SetLevel(DebugLevel)
  82. SetLevelOverride("tag", "overridetag", TraceLevel)
  83. v.contextCalled = false
  84. ev = Tag("sometag").Field("field", "value").With(v).Time(time.Unix(123, 0).UTC())
  85. ev.Trace("some debug message")
  86. require.True(t, v.contextCalled) // If there are overrides, we must call the context to determine the filter fields
  87. require.Equal(t, "", ev.Timestamp)
  88. require.Equal(t, Level(0), ev.Level)
  89. require.Equal(t, "", ev.Message)
  90. require.Equal(t, 4, len(ev.fields))
  91. require.Equal(t, "value", ev.fields["field"])
  92. require.Equal(t, "sometag", ev.fields["tag"])
  93. // Logged because of override tag, and contexters called
  94. v.contextCalled = false
  95. ev = Tag("overridetag").Field("field", "value").With(v).Time(time.Unix(123, 0).UTC())
  96. ev.Trace("some trace message")
  97. require.True(t, v.contextCalled)
  98. require.Equal(t, "1970-01-01T00:02:03Z", ev.Timestamp)
  99. require.Equal(t, TraceLevel, ev.Level)
  100. require.Equal(t, "some trace message", ev.Message)
  101. // Logged because of field override, and contexters called
  102. ResetLevelOverrides()
  103. SetLevelOverride("visitor_ip", "1.2.3.4", TraceLevel)
  104. v.contextCalled = false
  105. ev = With(v).Time(time.Unix(124, 0).UTC())
  106. ev.Trace("some trace message with override")
  107. require.True(t, v.contextCalled)
  108. require.Equal(t, "1970-01-01T00:02:04Z", ev.Timestamp)
  109. require.Equal(t, TraceLevel, ev.Level)
  110. require.Equal(t, "some trace message with override", ev.Message)
  111. expected := `{"time":"1970-01-01T00:18:31Z","level":"INFO","message":"some message","user_id":"u_abc","visitor_ip":"1.2.3.4"}
  112. {"time":"1970-01-01T00:02:03Z","level":"TRACE","message":"some trace message","field":"value","tag":"overridetag","user_id":"u_abc","visitor_ip":"1.2.3.4"}
  113. {"time":"1970-01-01T00:02:04Z","level":"TRACE","message":"some trace message with override","user_id":"u_abc","visitor_ip":"1.2.3.4"}
  114. `
  115. require.Equal(t, expected, out.String())
  116. }
  117. type fakeError struct {
  118. Code int
  119. Message string
  120. }
  121. func (e fakeError) Error() string {
  122. return e.Message
  123. }
  124. func (e fakeError) Context() Context {
  125. return Context{
  126. "error": e.Message,
  127. "error_code": e.Code,
  128. }
  129. }
  130. type fakeVisitor struct {
  131. UserID string
  132. IP string
  133. contextCalled bool
  134. }
  135. func (v *fakeVisitor) Context() Context {
  136. v.contextCalled = true
  137. return Context{
  138. "user_id": v.UserID,
  139. "visitor_ip": v.IP,
  140. }
  141. }
  142. func resetState() {
  143. SetLevel(DefaultLevel)
  144. SetFormat(DefaultFormat)
  145. SetOutput(DefaultOutput)
  146. ResetLevelOverrides()
  147. }