logger_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package gin
  5. import (
  6. "bytes"
  7. "errors"
  8. "fmt"
  9. "net/http"
  10. "testing"
  11. "time"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. func init() {
  15. SetMode(TestMode)
  16. }
  17. func TestLogger(t *testing.T) {
  18. buffer := new(bytes.Buffer)
  19. router := New()
  20. router.Use(LoggerWithWriter(buffer))
  21. router.GET("/example", func(c *Context) {})
  22. router.POST("/example", func(c *Context) {})
  23. router.PUT("/example", func(c *Context) {})
  24. router.DELETE("/example", func(c *Context) {})
  25. router.PATCH("/example", func(c *Context) {})
  26. router.HEAD("/example", func(c *Context) {})
  27. router.OPTIONS("/example", func(c *Context) {})
  28. performRequest(router, "GET", "/example?a=100")
  29. assert.Contains(t, buffer.String(), "200")
  30. assert.Contains(t, buffer.String(), "GET")
  31. assert.Contains(t, buffer.String(), "/example")
  32. assert.Contains(t, buffer.String(), "a=100")
  33. // I wrote these first (extending the above) but then realized they are more
  34. // like integration tests because they test the whole logging process rather
  35. // than individual functions. Im not sure where these should go.
  36. buffer.Reset()
  37. performRequest(router, "POST", "/example")
  38. assert.Contains(t, buffer.String(), "200")
  39. assert.Contains(t, buffer.String(), "POST")
  40. assert.Contains(t, buffer.String(), "/example")
  41. buffer.Reset()
  42. performRequest(router, "PUT", "/example")
  43. assert.Contains(t, buffer.String(), "200")
  44. assert.Contains(t, buffer.String(), "PUT")
  45. assert.Contains(t, buffer.String(), "/example")
  46. buffer.Reset()
  47. performRequest(router, "DELETE", "/example")
  48. assert.Contains(t, buffer.String(), "200")
  49. assert.Contains(t, buffer.String(), "DELETE")
  50. assert.Contains(t, buffer.String(), "/example")
  51. buffer.Reset()
  52. performRequest(router, "PATCH", "/example")
  53. assert.Contains(t, buffer.String(), "200")
  54. assert.Contains(t, buffer.String(), "PATCH")
  55. assert.Contains(t, buffer.String(), "/example")
  56. buffer.Reset()
  57. performRequest(router, "HEAD", "/example")
  58. assert.Contains(t, buffer.String(), "200")
  59. assert.Contains(t, buffer.String(), "HEAD")
  60. assert.Contains(t, buffer.String(), "/example")
  61. buffer.Reset()
  62. performRequest(router, "OPTIONS", "/example")
  63. assert.Contains(t, buffer.String(), "200")
  64. assert.Contains(t, buffer.String(), "OPTIONS")
  65. assert.Contains(t, buffer.String(), "/example")
  66. buffer.Reset()
  67. performRequest(router, "GET", "/notfound")
  68. assert.Contains(t, buffer.String(), "404")
  69. assert.Contains(t, buffer.String(), "GET")
  70. assert.Contains(t, buffer.String(), "/notfound")
  71. }
  72. func TestLoggerWithConfig(t *testing.T) {
  73. buffer := new(bytes.Buffer)
  74. router := New()
  75. router.Use(LoggerWithConfig(LoggerConfig{Output: buffer}))
  76. router.GET("/example", func(c *Context) {})
  77. router.POST("/example", func(c *Context) {})
  78. router.PUT("/example", func(c *Context) {})
  79. router.DELETE("/example", func(c *Context) {})
  80. router.PATCH("/example", func(c *Context) {})
  81. router.HEAD("/example", func(c *Context) {})
  82. router.OPTIONS("/example", func(c *Context) {})
  83. performRequest(router, "GET", "/example?a=100")
  84. assert.Contains(t, buffer.String(), "200")
  85. assert.Contains(t, buffer.String(), "GET")
  86. assert.Contains(t, buffer.String(), "/example")
  87. assert.Contains(t, buffer.String(), "a=100")
  88. // I wrote these first (extending the above) but then realized they are more
  89. // like integration tests because they test the whole logging process rather
  90. // than individual functions. Im not sure where these should go.
  91. buffer.Reset()
  92. performRequest(router, "POST", "/example")
  93. assert.Contains(t, buffer.String(), "200")
  94. assert.Contains(t, buffer.String(), "POST")
  95. assert.Contains(t, buffer.String(), "/example")
  96. buffer.Reset()
  97. performRequest(router, "PUT", "/example")
  98. assert.Contains(t, buffer.String(), "200")
  99. assert.Contains(t, buffer.String(), "PUT")
  100. assert.Contains(t, buffer.String(), "/example")
  101. buffer.Reset()
  102. performRequest(router, "DELETE", "/example")
  103. assert.Contains(t, buffer.String(), "200")
  104. assert.Contains(t, buffer.String(), "DELETE")
  105. assert.Contains(t, buffer.String(), "/example")
  106. buffer.Reset()
  107. performRequest(router, "PATCH", "/example")
  108. assert.Contains(t, buffer.String(), "200")
  109. assert.Contains(t, buffer.String(), "PATCH")
  110. assert.Contains(t, buffer.String(), "/example")
  111. buffer.Reset()
  112. performRequest(router, "HEAD", "/example")
  113. assert.Contains(t, buffer.String(), "200")
  114. assert.Contains(t, buffer.String(), "HEAD")
  115. assert.Contains(t, buffer.String(), "/example")
  116. buffer.Reset()
  117. performRequest(router, "OPTIONS", "/example")
  118. assert.Contains(t, buffer.String(), "200")
  119. assert.Contains(t, buffer.String(), "OPTIONS")
  120. assert.Contains(t, buffer.String(), "/example")
  121. buffer.Reset()
  122. performRequest(router, "GET", "/notfound")
  123. assert.Contains(t, buffer.String(), "404")
  124. assert.Contains(t, buffer.String(), "GET")
  125. assert.Contains(t, buffer.String(), "/notfound")
  126. }
  127. func TestLoggerWithFormatter(t *testing.T) {
  128. buffer := new(bytes.Buffer)
  129. d := DefaultWriter
  130. DefaultWriter = buffer
  131. defer func() {
  132. DefaultWriter = d
  133. }()
  134. router := New()
  135. router.Use(LoggerWithFormatter(func(param LogFormatterParams) string {
  136. return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
  137. param.TimeStamp.Format("2006/01/02 - 15:04:05"),
  138. param.StatusCode,
  139. param.Latency,
  140. param.ClientIP,
  141. param.Method,
  142. param.Path,
  143. param.ErrorMessage,
  144. )
  145. }))
  146. router.GET("/example", func(c *Context) {})
  147. performRequest(router, "GET", "/example?a=100")
  148. // output test
  149. assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
  150. assert.Contains(t, buffer.String(), "200")
  151. assert.Contains(t, buffer.String(), "GET")
  152. assert.Contains(t, buffer.String(), "/example")
  153. assert.Contains(t, buffer.String(), "a=100")
  154. }
  155. func TestLoggerWithConfigFormatting(t *testing.T) {
  156. var gotParam LogFormatterParams
  157. var gotKeys map[string]interface{}
  158. buffer := new(bytes.Buffer)
  159. router := New()
  160. router.Use(LoggerWithConfig(LoggerConfig{
  161. Output: buffer,
  162. Formatter: func(param LogFormatterParams) string {
  163. // for assert test
  164. gotParam = param
  165. return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
  166. param.TimeStamp.Format("2006/01/02 - 15:04:05"),
  167. param.StatusCode,
  168. param.Latency,
  169. param.ClientIP,
  170. param.Method,
  171. param.Path,
  172. param.ErrorMessage,
  173. )
  174. },
  175. }))
  176. router.GET("/example", func(c *Context) {
  177. // set dummy ClientIP
  178. c.Request.Header.Set("X-Forwarded-For", "20.20.20.20")
  179. gotKeys = c.Keys
  180. })
  181. performRequest(router, "GET", "/example?a=100")
  182. // output test
  183. assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
  184. assert.Contains(t, buffer.String(), "200")
  185. assert.Contains(t, buffer.String(), "GET")
  186. assert.Contains(t, buffer.String(), "/example")
  187. assert.Contains(t, buffer.String(), "a=100")
  188. // LogFormatterParams test
  189. assert.NotNil(t, gotParam.Request)
  190. assert.NotEmpty(t, gotParam.TimeStamp)
  191. assert.Equal(t, 200, gotParam.StatusCode)
  192. assert.NotEmpty(t, gotParam.Latency)
  193. assert.Equal(t, "20.20.20.20", gotParam.ClientIP)
  194. assert.Equal(t, "GET", gotParam.Method)
  195. assert.Equal(t, "/example?a=100", gotParam.Path)
  196. assert.Empty(t, gotParam.ErrorMessage)
  197. assert.Empty(t, gotParam.ErrorMessage)
  198. assert.Equal(t, gotKeys, gotParam.Keys)
  199. }
  200. func TestDefaultLogFormatter(t *testing.T) {
  201. timeStamp := time.Unix(1544173902, 0).UTC()
  202. termFalseParam := LogFormatterParams{
  203. TimeStamp: timeStamp,
  204. StatusCode: 200,
  205. Latency: time.Second * 5,
  206. ClientIP: "20.20.20.20",
  207. Method: "GET",
  208. Path: "/",
  209. ErrorMessage: "",
  210. IsTerm: false,
  211. }
  212. termTrueParam := LogFormatterParams{
  213. TimeStamp: timeStamp,
  214. StatusCode: 200,
  215. Latency: time.Second * 5,
  216. ClientIP: "20.20.20.20",
  217. Method: "GET",
  218. Path: "/",
  219. ErrorMessage: "",
  220. IsTerm: true,
  221. }
  222. assert.Equal(t, "[GIN] 2018/12/07 - 09:11:42 | 200 | 5s | 20.20.20.20 | GET /\n", defaultLogFormatter(termFalseParam))
  223. assert.Equal(t, "[GIN] 2018/12/07 - 09:11:42 |\x1b[97;42m 200 \x1b[0m| 5s | 20.20.20.20 |\x1b[97;44m GET \x1b[0m /\n", defaultLogFormatter(termTrueParam))
  224. }
  225. func TestColorForMethod(t *testing.T) {
  226. colorForMethod := func(method string) string {
  227. p := LogFormatterParams{
  228. Method: method,
  229. }
  230. return p.MethodColor()
  231. }
  232. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 52, 109}), colorForMethod("GET"), "get should be blue")
  233. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 54, 109}), colorForMethod("POST"), "post should be cyan")
  234. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 51, 109}), colorForMethod("PUT"), "put should be yellow")
  235. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForMethod("DELETE"), "delete should be red")
  236. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForMethod("PATCH"), "patch should be green")
  237. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 53, 109}), colorForMethod("HEAD"), "head should be magenta")
  238. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForMethod("OPTIONS"), "options should be white")
  239. assert.Equal(t, string([]byte{27, 91, 48, 109}), colorForMethod("TRACE"), "trace is not defined and should be the reset color")
  240. }
  241. func TestColorForStatus(t *testing.T) {
  242. colorForStatus := func(code int) string {
  243. p := LogFormatterParams{
  244. StatusCode: code,
  245. }
  246. return p.StatusCodeColor()
  247. }
  248. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForStatus(http.StatusOK), "2xx should be green")
  249. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForStatus(http.StatusMovedPermanently), "3xx should be white")
  250. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 51, 109}), colorForStatus(http.StatusNotFound), "4xx should be yellow")
  251. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForStatus(2), "other things should be red")
  252. }
  253. func TestResetColor(t *testing.T) {
  254. p := LogFormatterParams{}
  255. assert.Equal(t, string([]byte{27, 91, 48, 109}), p.ResetColor())
  256. }
  257. func TestErrorLogger(t *testing.T) {
  258. router := New()
  259. router.Use(ErrorLogger())
  260. router.GET("/error", func(c *Context) {
  261. c.Error(errors.New("this is an error")) // nolint: errcheck
  262. })
  263. router.GET("/abort", func(c *Context) {
  264. c.AbortWithError(http.StatusUnauthorized, errors.New("no authorized")) // nolint: errcheck
  265. })
  266. router.GET("/print", func(c *Context) {
  267. c.Error(errors.New("this is an error")) // nolint: errcheck
  268. c.String(http.StatusInternalServerError, "hola!")
  269. })
  270. w := performRequest(router, "GET", "/error")
  271. assert.Equal(t, http.StatusOK, w.Code)
  272. assert.Equal(t, "{\"error\":\"this is an error\"}", w.Body.String())
  273. w = performRequest(router, "GET", "/abort")
  274. assert.Equal(t, http.StatusUnauthorized, w.Code)
  275. assert.Equal(t, "{\"error\":\"no authorized\"}", w.Body.String())
  276. w = performRequest(router, "GET", "/print")
  277. assert.Equal(t, http.StatusInternalServerError, w.Code)
  278. assert.Equal(t, "hola!{\"error\":\"this is an error\"}", w.Body.String())
  279. }
  280. func TestLoggerWithWriterSkippingPaths(t *testing.T) {
  281. buffer := new(bytes.Buffer)
  282. router := New()
  283. router.Use(LoggerWithWriter(buffer, "/skipped"))
  284. router.GET("/logged", func(c *Context) {})
  285. router.GET("/skipped", func(c *Context) {})
  286. performRequest(router, "GET", "/logged")
  287. assert.Contains(t, buffer.String(), "200")
  288. buffer.Reset()
  289. performRequest(router, "GET", "/skipped")
  290. assert.Contains(t, buffer.String(), "")
  291. }
  292. func TestLoggerWithConfigSkippingPaths(t *testing.T) {
  293. buffer := new(bytes.Buffer)
  294. router := New()
  295. router.Use(LoggerWithConfig(LoggerConfig{
  296. Output: buffer,
  297. SkipPaths: []string{"/skipped"},
  298. }))
  299. router.GET("/logged", func(c *Context) {})
  300. router.GET("/skipped", func(c *Context) {})
  301. performRequest(router, "GET", "/logged")
  302. assert.Contains(t, buffer.String(), "200")
  303. buffer.Reset()
  304. performRequest(router, "GET", "/skipped")
  305. assert.Contains(t, buffer.String(), "")
  306. }
  307. func TestDisableConsoleColor(t *testing.T) {
  308. New()
  309. assert.False(t, disableColor)
  310. DisableConsoleColor()
  311. assert.True(t, disableColor)
  312. }
  313. func TestForceConsoleColor(t *testing.T) {
  314. New()
  315. assert.False(t, forceColor)
  316. ForceConsoleColor()
  317. assert.True(t, forceColor)
  318. }