metrics.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package workqueue
  14. import (
  15. "time"
  16. "github.com/prometheus/client_golang/prometheus"
  17. )
  18. type queueMetrics interface {
  19. add(item t)
  20. get(item t)
  21. done(item t)
  22. }
  23. type defaultQueueMetrics struct {
  24. depth prometheus.Gauge
  25. adds prometheus.Counter
  26. latency prometheus.Summary
  27. workDuration prometheus.Summary
  28. addTimes map[t]time.Time
  29. processingStartTimes map[t]time.Time
  30. }
  31. func newQueueMetrics(name string) queueMetrics {
  32. var ret *defaultQueueMetrics
  33. if len(name) == 0 {
  34. return ret
  35. }
  36. ret = &defaultQueueMetrics{
  37. depth: prometheus.NewGauge(prometheus.GaugeOpts{
  38. Subsystem: name,
  39. Name: "depth",
  40. Help: "Current depth of workqueue: " + name,
  41. }),
  42. adds: prometheus.NewCounter(prometheus.CounterOpts{
  43. Subsystem: name,
  44. Name: "adds",
  45. Help: "Total number of adds handled by workqueue: " + name,
  46. }),
  47. latency: prometheus.NewSummary(prometheus.SummaryOpts{
  48. Subsystem: name,
  49. Name: "queue_latency",
  50. Help: "How long an item stays in workqueue" + name + " before being requested.",
  51. }),
  52. workDuration: prometheus.NewSummary(prometheus.SummaryOpts{
  53. Subsystem: name,
  54. Name: "work_duration",
  55. Help: "How long processing an item from workqueue" + name + " takes.",
  56. }),
  57. addTimes: map[t]time.Time{},
  58. processingStartTimes: map[t]time.Time{},
  59. }
  60. prometheus.Register(ret.depth)
  61. prometheus.Register(ret.adds)
  62. prometheus.Register(ret.latency)
  63. prometheus.Register(ret.workDuration)
  64. return ret
  65. }
  66. func (m *defaultQueueMetrics) add(item t) {
  67. if m == nil {
  68. return
  69. }
  70. m.adds.Inc()
  71. m.depth.Inc()
  72. if _, exists := m.addTimes[item]; !exists {
  73. m.addTimes[item] = time.Now()
  74. }
  75. }
  76. func (m *defaultQueueMetrics) get(item t) {
  77. if m == nil {
  78. return
  79. }
  80. m.depth.Dec()
  81. m.processingStartTimes[item] = time.Now()
  82. if startTime, exists := m.addTimes[item]; exists {
  83. m.latency.Observe(sinceInMicroseconds(startTime))
  84. delete(m.addTimes, item)
  85. }
  86. }
  87. func (m *defaultQueueMetrics) done(item t) {
  88. if m == nil {
  89. return
  90. }
  91. if startTime, exists := m.processingStartTimes[item]; exists {
  92. m.workDuration.Observe(sinceInMicroseconds(startTime))
  93. delete(m.processingStartTimes, item)
  94. }
  95. }
  96. // Gets the time since the specified start in microseconds.
  97. func sinceInMicroseconds(start time.Time) float64 {
  98. return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds())
  99. }
  100. type retryMetrics interface {
  101. retry()
  102. }
  103. type defaultRetryMetrics struct {
  104. retries prometheus.Counter
  105. }
  106. func newRetryMetrics(name string) retryMetrics {
  107. var ret *defaultRetryMetrics
  108. if len(name) == 0 {
  109. return ret
  110. }
  111. ret = &defaultRetryMetrics{
  112. retries: prometheus.NewCounter(prometheus.CounterOpts{
  113. Subsystem: name,
  114. Name: "retries",
  115. Help: "Total number of retries handled by workqueue: " + name,
  116. }),
  117. }
  118. prometheus.Register(ret.retries)
  119. return ret
  120. }
  121. func (m *defaultRetryMetrics) retry() {
  122. if m == nil {
  123. return
  124. }
  125. m.retries.Inc()
  126. }