2
0

telemetry.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package metrics
  2. import (
  3. "fmt"
  4. "sync"
  5. "github.com/opencost/opencost/core/pkg/version"
  6. "github.com/kubecost/events"
  7. "github.com/prometheus/client_golang/prometheus"
  8. )
  9. var (
  10. once sync.Once
  11. dispatcher events.Dispatcher[HttpHandlerMetricEvent]
  12. // -- append new dispatchers here for new event types
  13. // prometheus metrics
  14. requestsCount *prometheus.CounterVec
  15. responseTime *prometheus.HistogramVec
  16. responseSize *prometheus.SummaryVec
  17. buildInfo *prometheus.GaugeVec
  18. )
  19. // InitOpencostTelemetry registers Opencost application telemetry.
  20. func InitOpencostTelemetry(config *MetricsConfig) {
  21. once.Do(func() {
  22. disabledMetrics := config.GetDisabledMetricsMap()
  23. // register prometheus metrics
  24. if _, disabled := disabledMetrics["opencost_build_info"]; !disabled {
  25. buildInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{
  26. Name: "opencost_build_info",
  27. Help: "opencost_build_info Build information",
  28. }, []string{"version", "revision"})
  29. buildInfo.WithLabelValues(version.Version, version.GitCommit)
  30. prometheus.MustRegister(buildInfo)
  31. }
  32. if _, disabled := disabledMetrics["kubecost_http_requests_total"]; !disabled {
  33. requestsCount = prometheus.NewCounterVec(prometheus.CounterOpts{
  34. Name: "kubecost_http_requests_total",
  35. Help: "kubecost_http_requests_total Total number of HTTP requests",
  36. }, []string{"handler", "method", "code"})
  37. prometheus.MustRegister(requestsCount)
  38. }
  39. if _, disabled := disabledMetrics["kubecost_http_response_time_seconds"]; !disabled {
  40. var buckets = []float64{0.001, 0.01, 0.1, 0.3, 0.6, 1, 3, 6, 9, 20, 30, 60, 90, 120, 240, 360, 720}
  41. responseTime = prometheus.NewHistogramVec(prometheus.HistogramOpts{
  42. Name: "kubecost_http_response_time_seconds",
  43. Help: "kubecost_http_response_time_seconds Response time in seconds",
  44. Buckets: buckets,
  45. }, []string{"handler", "method", "code"})
  46. prometheus.MustRegister(responseTime)
  47. }
  48. if _, disabled := disabledMetrics["kubecost_http_response_size_bytes"]; !disabled {
  49. responseSize = prometheus.NewSummaryVec(prometheus.SummaryOpts{
  50. Name: "kubecost_http_response_size_bytes",
  51. Help: "kubecost_http_response_size_bytes Response size in bytes",
  52. }, []string{"handler", "method", "code"})
  53. prometheus.MustRegister(responseSize)
  54. }
  55. // register event listeners
  56. dispatcher = events.GlobalDispatcherFor[HttpHandlerMetricEvent]()
  57. dispatcher.AddEventHandler(onHttpHandlerMetricEvent)
  58. // -- append new event handlers here
  59. })
  60. }
  61. // onHttpHandlerMetricEvent handles all incoming HttpHandlerMetricEvents
  62. func onHttpHandlerMetricEvent(event HttpHandlerMetricEvent) {
  63. code := fmt.Sprintf("%d", event.Code)
  64. if requestsCount != nil {
  65. requestsCount.WithLabelValues(event.Handler, event.Method, code).Inc()
  66. }
  67. if responseSize != nil {
  68. responseSize.WithLabelValues(event.Handler, event.Method, code).Observe(float64(event.ResponseSize))
  69. }
  70. if responseTime != nil {
  71. responseTime.WithLabelValues(event.Handler, event.Method, code).Observe(event.ResponseTime.Seconds())
  72. }
  73. }