spanbucket.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2017, OpenCensus Authors
  2. //
  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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package trace
  15. import (
  16. "time"
  17. )
  18. // samplePeriod is the minimum time between accepting spans in a single bucket.
  19. const samplePeriod = time.Second
  20. // defaultLatencies contains the default latency bucket bounds.
  21. // TODO: consider defaults, make configurable
  22. var defaultLatencies = [...]time.Duration{
  23. 10 * time.Microsecond,
  24. 100 * time.Microsecond,
  25. time.Millisecond,
  26. 10 * time.Millisecond,
  27. 100 * time.Millisecond,
  28. time.Second,
  29. 10 * time.Second,
  30. time.Minute,
  31. }
  32. // bucket is a container for a set of spans for a particular error code or latency range.
  33. type bucket struct {
  34. nextTime time.Time // next time we can accept a span
  35. buffer []*SpanData // circular buffer of spans
  36. nextIndex int // location next SpanData should be placed in buffer
  37. overflow bool // whether the circular buffer has wrapped around
  38. }
  39. func makeBucket(bufferSize int) bucket {
  40. return bucket{
  41. buffer: make([]*SpanData, bufferSize),
  42. }
  43. }
  44. // add adds a span to the bucket, if nextTime has been reached.
  45. func (b *bucket) add(s *SpanData) {
  46. if s.EndTime.Before(b.nextTime) {
  47. return
  48. }
  49. if len(b.buffer) == 0 {
  50. return
  51. }
  52. b.nextTime = s.EndTime.Add(samplePeriod)
  53. b.buffer[b.nextIndex] = s
  54. b.nextIndex++
  55. if b.nextIndex == len(b.buffer) {
  56. b.nextIndex = 0
  57. b.overflow = true
  58. }
  59. }
  60. // size returns the number of spans in the bucket.
  61. func (b *bucket) size() int {
  62. if b.overflow {
  63. return len(b.buffer)
  64. }
  65. return b.nextIndex
  66. }
  67. // span returns the ith span in the bucket.
  68. func (b *bucket) span(i int) *SpanData {
  69. if !b.overflow {
  70. return b.buffer[i]
  71. }
  72. if i < len(b.buffer)-b.nextIndex {
  73. return b.buffer[b.nextIndex+i]
  74. }
  75. return b.buffer[b.nextIndex+i-len(b.buffer)]
  76. }
  77. // resize changes the size of the bucket to n, keeping up to n existing spans.
  78. func (b *bucket) resize(n int) {
  79. cur := b.size()
  80. newBuffer := make([]*SpanData, n)
  81. if cur < n {
  82. for i := 0; i < cur; i++ {
  83. newBuffer[i] = b.span(i)
  84. }
  85. b.buffer = newBuffer
  86. b.nextIndex = cur
  87. b.overflow = false
  88. return
  89. }
  90. for i := 0; i < n; i++ {
  91. newBuffer[i] = b.span(i + cur - n)
  92. }
  93. b.buffer = newBuffer
  94. b.nextIndex = 0
  95. b.overflow = true
  96. }
  97. // latencyBucket returns the appropriate bucket number for a given latency.
  98. func latencyBucket(latency time.Duration) int {
  99. i := 0
  100. for i < len(defaultLatencies) && latency >= defaultLatencies[i] {
  101. i++
  102. }
  103. return i
  104. }
  105. // latencyBucketBounds returns the lower and upper bounds for a latency bucket
  106. // number.
  107. //
  108. // The lower bound is inclusive, the upper bound is exclusive (except for the
  109. // last bucket.)
  110. func latencyBucketBounds(index int) (lower time.Duration, upper time.Duration) {
  111. if index == 0 {
  112. return 0, defaultLatencies[index]
  113. }
  114. if index == len(defaultLatencies) {
  115. return defaultLatencies[index-1], 1<<63 - 1
  116. }
  117. return defaultLatencies[index-1], defaultLatencies[index]
  118. }