request_metrics.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package middleware
  2. import (
  3. "net/http"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "github.com/grafana/grafana/pkg/metrics"
  8. "gopkg.in/macaron.v1"
  9. )
  10. func RequestMetrics() macaron.Handler {
  11. return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
  12. rw := res.(macaron.ResponseWriter)
  13. now := time.Now()
  14. c.Next()
  15. status := rw.Status()
  16. code := sanitizeCode(status)
  17. method := sanitizeMethod(req.Method)
  18. metrics.M_Http_Request_Total.WithLabelValues(code, method).Inc()
  19. metrics.M_Http_Request_Summary.WithLabelValues(code, method).Observe(time.Since(now).Seconds())
  20. if strings.HasPrefix(req.RequestURI, "/api/datasources/proxy") {
  21. countProxyRequests(status)
  22. } else if strings.HasPrefix(req.RequestURI, "/api/") {
  23. countApiRequests(status)
  24. } else {
  25. countPageRequests(status)
  26. }
  27. }
  28. }
  29. func countApiRequests(status int) {
  30. switch status {
  31. case 200:
  32. metrics.M_Api_Status.WithLabelValues("200").Inc()
  33. case 404:
  34. metrics.M_Api_Status.WithLabelValues("404").Inc()
  35. case 500:
  36. metrics.M_Api_Status.WithLabelValues("500").Inc()
  37. default:
  38. metrics.M_Api_Status.WithLabelValues("unknown").Inc()
  39. }
  40. }
  41. func countPageRequests(status int) {
  42. switch status {
  43. case 200:
  44. metrics.M_Page_Status.WithLabelValues("200").Inc()
  45. case 404:
  46. metrics.M_Page_Status.WithLabelValues("404").Inc()
  47. case 500:
  48. metrics.M_Page_Status.WithLabelValues("500").Inc()
  49. default:
  50. metrics.M_Page_Status.WithLabelValues("unknown").Inc()
  51. }
  52. }
  53. func countProxyRequests(status int) {
  54. switch status {
  55. case 200:
  56. metrics.M_Proxy_Status.WithLabelValues("200").Inc()
  57. case 404:
  58. metrics.M_Proxy_Status.WithLabelValues("400").Inc()
  59. case 500:
  60. metrics.M_Proxy_Status.WithLabelValues("500").Inc()
  61. default:
  62. metrics.M_Proxy_Status.WithLabelValues("unknown").Inc()
  63. }
  64. }
  65. func sanitizeMethod(m string) string {
  66. switch m {
  67. case "GET", "get":
  68. return "get"
  69. case "PUT", "put":
  70. return "put"
  71. case "HEAD", "head":
  72. return "head"
  73. case "POST", "post":
  74. return "post"
  75. case "DELETE", "delete":
  76. return "delete"
  77. case "CONNECT", "connect":
  78. return "connect"
  79. case "OPTIONS", "options":
  80. return "options"
  81. case "NOTIFY", "notify":
  82. return "notify"
  83. default:
  84. return strings.ToLower(m)
  85. }
  86. }
  87. // If the wrapped http.Handler has not set a status code, i.e. the value is
  88. // currently 0, santizeCode will return 200, for consistency with behavior in
  89. // the stdlib.
  90. func sanitizeCode(s int) string {
  91. switch s {
  92. case 100:
  93. return "100"
  94. case 101:
  95. return "101"
  96. case 200, 0:
  97. return "200"
  98. case 201:
  99. return "201"
  100. case 202:
  101. return "202"
  102. case 203:
  103. return "203"
  104. case 204:
  105. return "204"
  106. case 205:
  107. return "205"
  108. case 206:
  109. return "206"
  110. case 300:
  111. return "300"
  112. case 301:
  113. return "301"
  114. case 302:
  115. return "302"
  116. case 304:
  117. return "304"
  118. case 305:
  119. return "305"
  120. case 307:
  121. return "307"
  122. case 400:
  123. return "400"
  124. case 401:
  125. return "401"
  126. case 402:
  127. return "402"
  128. case 403:
  129. return "403"
  130. case 404:
  131. return "404"
  132. case 405:
  133. return "405"
  134. case 406:
  135. return "406"
  136. case 407:
  137. return "407"
  138. case 408:
  139. return "408"
  140. case 409:
  141. return "409"
  142. case 410:
  143. return "410"
  144. case 411:
  145. return "411"
  146. case 412:
  147. return "412"
  148. case 413:
  149. return "413"
  150. case 414:
  151. return "414"
  152. case 415:
  153. return "415"
  154. case 416:
  155. return "416"
  156. case 417:
  157. return "417"
  158. case 418:
  159. return "418"
  160. case 500:
  161. return "500"
  162. case 501:
  163. return "501"
  164. case 502:
  165. return "502"
  166. case 503:
  167. return "503"
  168. case 504:
  169. return "504"
  170. case 505:
  171. return "505"
  172. case 428:
  173. return "428"
  174. case 429:
  175. return "429"
  176. case 431:
  177. return "431"
  178. case 511:
  179. return "511"
  180. default:
  181. return strconv.Itoa(s)
  182. }
  183. }