You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
1.9 KiB

  1. package metric
  2. import (
  3. "strconv"
  4. "time"
  5. "github.com/gin-gonic/gin"
  6. "github.com/prometheus/client_golang/prometheus"
  7. )
  8. const (
  9. favicon = "/favicon.ico"
  10. )
  11. // Prometheus contains the metrics gathered by the instance and its path
  12. type Prometheus struct {
  13. reqCnt *prometheus.CounterVec
  14. reqDur *prometheus.HistogramVec
  15. }
  16. // NewPrometheus generates a new set of metrics with a certain subsystem name
  17. func NewPrometheus() (*Prometheus, error) {
  18. reqCnt := prometheus.NewCounterVec(
  19. prometheus.CounterOpts{
  20. Namespace: namespaceAPI,
  21. Name: "requests_total",
  22. Help: "How many HTTP requests processed, partitioned by status code and HTTP method",
  23. },
  24. []string{"code", "method", "path"},
  25. )
  26. if err := registerCollector(reqCnt); err != nil {
  27. return nil, err
  28. }
  29. reqDur := prometheus.NewHistogramVec(
  30. prometheus.HistogramOpts{
  31. Namespace: namespaceAPI,
  32. Name: "request_duration_seconds",
  33. Help: "The HTTP request latencies in seconds",
  34. },
  35. []string{"code", "method", "path"},
  36. )
  37. if err := registerCollector(reqDur); err != nil {
  38. return nil, err
  39. }
  40. return &Prometheus{
  41. reqCnt: reqCnt,
  42. reqDur: reqDur,
  43. }, nil
  44. }
  45. // PrometheusMiddleware creates the prometheus collector and
  46. // defines status handler function for the middleware
  47. func PrometheusMiddleware() (gin.HandlerFunc, error) {
  48. p, err := NewPrometheus()
  49. if err != nil {
  50. return nil, err
  51. }
  52. return p.Middleware(), nil
  53. }
  54. // Middleware defines status handler function for middleware
  55. func (p *Prometheus) Middleware() gin.HandlerFunc {
  56. return func(c *gin.Context) {
  57. if c.Request.URL.Path == favicon {
  58. c.Next()
  59. return
  60. }
  61. start := time.Now()
  62. c.Next()
  63. status := strconv.Itoa(c.Writer.Status())
  64. elapsed := float64(time.Since(start)) / float64(time.Second)
  65. fullPath := c.FullPath()
  66. p.reqDur.WithLabelValues(status, c.Request.Method, fullPath).Observe(elapsed)
  67. p.reqCnt.WithLabelValues(status, c.Request.Method, fullPath).Inc()
  68. }
  69. }