113 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
package stats
 | 
						|
 | 
						|
import "fmt"
 | 
						|
 | 
						|
// Type is the type of aggregation of apply
 | 
						|
type Type int
 | 
						|
 | 
						|
const (
 | 
						|
	AggregateAvg Type = iota
 | 
						|
	AggregateSum
 | 
						|
	AggregateHistogram
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// HistogramPercentiles is used to determine which percentiles to return for
 | 
						|
	// SimpleCounter.Aggregate
 | 
						|
	HistogramPercentiles = map[string]float64{
 | 
						|
		"p50": 0.5,
 | 
						|
		"p95": 0.95,
 | 
						|
		"p99": 0.99,
 | 
						|
	}
 | 
						|
 | 
						|
	// MinSamplesForPercentiles is used by SimpleCounter.Aggregate to determine
 | 
						|
	// what the minimum number of samples is required for percentile analysis
 | 
						|
	MinSamplesForPercentiles = 10
 | 
						|
)
 | 
						|
 | 
						|
// Aggregates can be used to merge counters together. This is not goroutine safe
 | 
						|
type Aggregates map[string]Counter
 | 
						|
 | 
						|
// Add adds the counter for aggregation. This is not goroutine safe
 | 
						|
func (a Aggregates) Add(c Counter) error {
 | 
						|
	key := c.FullKey()
 | 
						|
	if counter, ok := a[key]; ok {
 | 
						|
		if counter.GetType() != c.GetType() {
 | 
						|
			return fmt.Errorf("stats: mismatched aggregation type for: %s", key)
 | 
						|
		}
 | 
						|
		counter.AddValues(c.GetValues()...)
 | 
						|
	} else {
 | 
						|
		a[key] = c
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Counter is the interface used by Aggregates to merge counters together
 | 
						|
type Counter interface {
 | 
						|
	// FullKey is used to uniquely identify the counter
 | 
						|
	FullKey() string
 | 
						|
 | 
						|
	// AddValues adds values for aggregation
 | 
						|
	AddValues(...float64)
 | 
						|
 | 
						|
	// GetValues returns the values for aggregation
 | 
						|
	GetValues() []float64
 | 
						|
 | 
						|
	// GetType returns the type of aggregation to apply
 | 
						|
	GetType() Type
 | 
						|
}
 | 
						|
 | 
						|
// SimpleCounter is a basic implementation of the Counter interface
 | 
						|
type SimpleCounter struct {
 | 
						|
	Key    string
 | 
						|
	Values []float64
 | 
						|
	Type   Type
 | 
						|
}
 | 
						|
 | 
						|
// FullKey is part of the Counter interace
 | 
						|
func (s *SimpleCounter) FullKey() string {
 | 
						|
	return s.Key
 | 
						|
}
 | 
						|
 | 
						|
// GetValues is part of the Counter interface
 | 
						|
func (s *SimpleCounter) GetValues() []float64 {
 | 
						|
	return s.Values
 | 
						|
}
 | 
						|
 | 
						|
// AddValues is part of the Counter interface
 | 
						|
func (s *SimpleCounter) AddValues(vs ...float64) {
 | 
						|
	s.Values = append(s.Values, vs...)
 | 
						|
}
 | 
						|
 | 
						|
// GetType is part of the Counter interface
 | 
						|
func (s *SimpleCounter) GetType() Type {
 | 
						|
	return s.Type
 | 
						|
}
 | 
						|
 | 
						|
// Aggregate aggregates the provided values appropriately, returning a map
 | 
						|
// from key to value. If AggregateHistogram is specified, the map will contain
 | 
						|
// the relevant percentiles as specified by HistogramPercentiles
 | 
						|
func (s *SimpleCounter) Aggregate() map[string]float64 {
 | 
						|
	switch s.Type {
 | 
						|
	case AggregateAvg:
 | 
						|
		return map[string]float64{
 | 
						|
			s.Key: Average(s.Values),
 | 
						|
		}
 | 
						|
	case AggregateSum:
 | 
						|
		return map[string]float64{
 | 
						|
			s.Key: Sum(s.Values),
 | 
						|
		}
 | 
						|
	case AggregateHistogram:
 | 
						|
		histogram := map[string]float64{
 | 
						|
			s.Key: Average(s.Values),
 | 
						|
		}
 | 
						|
		if len(s.Values) > MinSamplesForPercentiles {
 | 
						|
			for k, v := range Percentiles(s.Values, HistogramPercentiles) {
 | 
						|
				histogram[fmt.Sprintf("%s.%s", s.Key, k)] = v
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return histogram
 | 
						|
	}
 | 
						|
	panic("stats: unsupported aggregation type")
 | 
						|
}
 |