mirror of https://github.com/knative/docs.git
				
				
				
			
		
			
				
	
	
		
			131 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright 2017, OpenCensus Authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package trace
 | |
| 
 | |
| import (
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| // samplePeriod is the minimum time between accepting spans in a single bucket.
 | |
| const samplePeriod = time.Second
 | |
| 
 | |
| // defaultLatencies contains the default latency bucket bounds.
 | |
| // TODO: consider defaults, make configurable
 | |
| var defaultLatencies = [...]time.Duration{
 | |
| 	10 * time.Microsecond,
 | |
| 	100 * time.Microsecond,
 | |
| 	time.Millisecond,
 | |
| 	10 * time.Millisecond,
 | |
| 	100 * time.Millisecond,
 | |
| 	time.Second,
 | |
| 	10 * time.Second,
 | |
| 	time.Minute,
 | |
| }
 | |
| 
 | |
| // bucket is a container for a set of spans for a particular error code or latency range.
 | |
| type bucket struct {
 | |
| 	nextTime  time.Time   // next time we can accept a span
 | |
| 	buffer    []*SpanData // circular buffer of spans
 | |
| 	nextIndex int         // location next SpanData should be placed in buffer
 | |
| 	overflow  bool        // whether the circular buffer has wrapped around
 | |
| }
 | |
| 
 | |
| func makeBucket(bufferSize int) bucket {
 | |
| 	return bucket{
 | |
| 		buffer: make([]*SpanData, bufferSize),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // add adds a span to the bucket, if nextTime has been reached.
 | |
| func (b *bucket) add(s *SpanData) {
 | |
| 	if s.EndTime.Before(b.nextTime) {
 | |
| 		return
 | |
| 	}
 | |
| 	if len(b.buffer) == 0 {
 | |
| 		return
 | |
| 	}
 | |
| 	b.nextTime = s.EndTime.Add(samplePeriod)
 | |
| 	b.buffer[b.nextIndex] = s
 | |
| 	b.nextIndex++
 | |
| 	if b.nextIndex == len(b.buffer) {
 | |
| 		b.nextIndex = 0
 | |
| 		b.overflow = true
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // size returns the number of spans in the bucket.
 | |
| func (b *bucket) size() int {
 | |
| 	if b.overflow {
 | |
| 		return len(b.buffer)
 | |
| 	}
 | |
| 	return b.nextIndex
 | |
| }
 | |
| 
 | |
| // span returns the ith span in the bucket.
 | |
| func (b *bucket) span(i int) *SpanData {
 | |
| 	if !b.overflow {
 | |
| 		return b.buffer[i]
 | |
| 	}
 | |
| 	if i < len(b.buffer)-b.nextIndex {
 | |
| 		return b.buffer[b.nextIndex+i]
 | |
| 	}
 | |
| 	return b.buffer[b.nextIndex+i-len(b.buffer)]
 | |
| }
 | |
| 
 | |
| // resize changes the size of the bucket to n, keeping up to n existing spans.
 | |
| func (b *bucket) resize(n int) {
 | |
| 	cur := b.size()
 | |
| 	newBuffer := make([]*SpanData, n)
 | |
| 	if cur < n {
 | |
| 		for i := 0; i < cur; i++ {
 | |
| 			newBuffer[i] = b.span(i)
 | |
| 		}
 | |
| 		b.buffer = newBuffer
 | |
| 		b.nextIndex = cur
 | |
| 		b.overflow = false
 | |
| 		return
 | |
| 	}
 | |
| 	for i := 0; i < n; i++ {
 | |
| 		newBuffer[i] = b.span(i + cur - n)
 | |
| 	}
 | |
| 	b.buffer = newBuffer
 | |
| 	b.nextIndex = 0
 | |
| 	b.overflow = true
 | |
| }
 | |
| 
 | |
| // latencyBucket returns the appropriate bucket number for a given latency.
 | |
| func latencyBucket(latency time.Duration) int {
 | |
| 	i := 0
 | |
| 	for i < len(defaultLatencies) && latency >= defaultLatencies[i] {
 | |
| 		i++
 | |
| 	}
 | |
| 	return i
 | |
| }
 | |
| 
 | |
| // latencyBucketBounds returns the lower and upper bounds for a latency bucket
 | |
| // number.
 | |
| //
 | |
| // The lower bound is inclusive, the upper bound is exclusive (except for the
 | |
| // last bucket.)
 | |
| func latencyBucketBounds(index int) (lower time.Duration, upper time.Duration) {
 | |
| 	if index == 0 {
 | |
| 		return 0, defaultLatencies[index]
 | |
| 	}
 | |
| 	if index == len(defaultLatencies) {
 | |
| 		return defaultLatencies[index-1], 1<<63 - 1
 | |
| 	}
 | |
| 	return defaultLatencies[index-1], defaultLatencies[index]
 | |
| }
 |