summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/facebookgo/stats
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/facebookgo/stats')
-rw-r--r--vendor/github.com/facebookgo/stats/aggregation.go35
-rw-r--r--vendor/github.com/facebookgo/stats/counter.go112
-rw-r--r--vendor/github.com/facebookgo/stats/license30
-rw-r--r--vendor/github.com/facebookgo/stats/stats.go166
-rw-r--r--vendor/github.com/facebookgo/stats/stopper.go17
5 files changed, 360 insertions, 0 deletions
diff --git a/vendor/github.com/facebookgo/stats/aggregation.go b/vendor/github.com/facebookgo/stats/aggregation.go
new file mode 100644
index 00000000..8f57fb7f
--- /dev/null
+++ b/vendor/github.com/facebookgo/stats/aggregation.go
@@ -0,0 +1,35 @@
+package stats
+
+import "sort"
+
+// Average returns the average value
+func Average(values []float64) float64 {
+ if len(values) == 0 {
+ return 0
+ }
+
+ var val float64
+ for _, point := range values {
+ val += point
+ }
+ return val / float64(len(values))
+}
+
+// Sum returns the sum of all the given values
+func Sum(values []float64) float64 {
+ var val float64
+ for _, point := range values {
+ val += point
+ }
+ return val
+}
+
+// Percentiles returns a map containing the asked for percentiles
+func Percentiles(values []float64, percentiles map[string]float64) map[string]float64 {
+ sort.Float64s(values)
+ results := map[string]float64{}
+ for label, p := range percentiles {
+ results[label] = values[int(float64(len(values))*p)]
+ }
+ return results
+}
diff --git a/vendor/github.com/facebookgo/stats/counter.go b/vendor/github.com/facebookgo/stats/counter.go
new file mode 100644
index 00000000..59a0ed1e
--- /dev/null
+++ b/vendor/github.com/facebookgo/stats/counter.go
@@ -0,0 +1,112 @@
+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")
+}
diff --git a/vendor/github.com/facebookgo/stats/license b/vendor/github.com/facebookgo/stats/license
new file mode 100644
index 00000000..feae8707
--- /dev/null
+++ b/vendor/github.com/facebookgo/stats/license
@@ -0,0 +1,30 @@
+BSD License
+
+For stats software
+
+Copyright (c) 2015, Facebook, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name Facebook nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/facebookgo/stats/stats.go b/vendor/github.com/facebookgo/stats/stats.go
new file mode 100644
index 00000000..b833506a
--- /dev/null
+++ b/vendor/github.com/facebookgo/stats/stats.go
@@ -0,0 +1,166 @@
+// Package stats defines a lightweight interface for collecting statistics. It
+// doesn't provide an implementation, just the shared interface.
+package stats
+
+// Client provides methods to collection statistics.
+type Client interface {
+ // BumpAvg bumps the average for the given key.
+ BumpAvg(key string, val float64)
+
+ // BumpSum bumps the sum for the given key.
+ BumpSum(key string, val float64)
+
+ // BumpHistogram bumps the histogram for the given key.
+ BumpHistogram(key string, val float64)
+
+ // BumpTime is a special version of BumpHistogram which is specialized for
+ // timers. Calling it starts the timer, and it returns a value on which End()
+ // can be called to indicate finishing the timer. A convenient way of
+ // recording the duration of a function is calling it like such at the top of
+ // the function:
+ //
+ // defer s.BumpTime("my.function").End()
+ BumpTime(key string) interface {
+ End()
+ }
+}
+
+// PrefixClient adds multiple keys for the same value, with each prefix
+// added to the key and calls the underlying client.
+func PrefixClient(prefixes []string, client Client) Client {
+ return &prefixClient{
+ Prefixes: prefixes,
+ Client: client,
+ }
+}
+
+type prefixClient struct {
+ Prefixes []string
+ Client Client
+}
+
+func (p *prefixClient) BumpAvg(key string, val float64) {
+ for _, prefix := range p.Prefixes {
+ p.Client.BumpAvg(prefix+key, val)
+ }
+}
+
+func (p *prefixClient) BumpSum(key string, val float64) {
+ for _, prefix := range p.Prefixes {
+ p.Client.BumpSum(prefix+key, val)
+ }
+}
+
+func (p *prefixClient) BumpHistogram(key string, val float64) {
+ for _, prefix := range p.Prefixes {
+ p.Client.BumpHistogram(prefix+key, val)
+ }
+}
+
+func (p *prefixClient) BumpTime(key string) interface {
+ End()
+} {
+ var m multiEnder
+ for _, prefix := range p.Prefixes {
+ m = append(m, p.Client.BumpTime(prefix+key))
+ }
+ return m
+}
+
+// multiEnder combines many enders together.
+type multiEnder []interface {
+ End()
+}
+
+func (m multiEnder) End() {
+ for _, e := range m {
+ e.End()
+ }
+}
+
+// HookClient is useful for testing. It provides optional hooks for each
+// expected method in the interface, which if provided will be called. If a
+// hook is not provided, it will be ignored.
+type HookClient struct {
+ BumpAvgHook func(key string, val float64)
+ BumpSumHook func(key string, val float64)
+ BumpHistogramHook func(key string, val float64)
+ BumpTimeHook func(key string) interface {
+ End()
+ }
+}
+
+// BumpAvg will call BumpAvgHook if defined.
+func (c *HookClient) BumpAvg(key string, val float64) {
+ if c.BumpAvgHook != nil {
+ c.BumpAvgHook(key, val)
+ }
+}
+
+// BumpSum will call BumpSumHook if defined.
+func (c *HookClient) BumpSum(key string, val float64) {
+ if c.BumpSumHook != nil {
+ c.BumpSumHook(key, val)
+ }
+}
+
+// BumpHistogram will call BumpHistogramHook if defined.
+func (c *HookClient) BumpHistogram(key string, val float64) {
+ if c.BumpHistogramHook != nil {
+ c.BumpHistogramHook(key, val)
+ }
+}
+
+// BumpTime will call BumpTimeHook if defined.
+func (c *HookClient) BumpTime(key string) interface {
+ End()
+} {
+ if c.BumpTimeHook != nil {
+ return c.BumpTimeHook(key)
+ }
+ return NoOpEnd
+}
+
+type noOpEnd struct{}
+
+func (n noOpEnd) End() {}
+
+// NoOpEnd provides a dummy value for use in tests as valid return value for
+// BumpTime().
+var NoOpEnd = noOpEnd{}
+
+// BumpAvg calls BumpAvg on the Client if it isn't nil. This is useful when a
+// component has an optional stats.Client.
+func BumpAvg(c Client, key string, val float64) {
+ if c != nil {
+ c.BumpAvg(key, val)
+ }
+}
+
+// BumpSum calls BumpSum on the Client if it isn't nil. This is useful when a
+// component has an optional stats.Client.
+func BumpSum(c Client, key string, val float64) {
+ if c != nil {
+ c.BumpSum(key, val)
+ }
+}
+
+// BumpHistogram calls BumpHistogram on the Client if it isn't nil. This is
+// useful when a component has an optional stats.Client.
+func BumpHistogram(c Client, key string, val float64) {
+ if c != nil {
+ c.BumpHistogram(key, val)
+ }
+}
+
+// BumpTime calls BumpTime on the Client if it isn't nil. If the Client is nil
+// it still returns a valid return value which will be a no-op. This is useful
+// when a component has an optional stats.Client.
+func BumpTime(c Client, key string) interface {
+ End()
+} {
+ if c != nil {
+ return c.BumpTime(key)
+ }
+ return NoOpEnd
+}
diff --git a/vendor/github.com/facebookgo/stats/stopper.go b/vendor/github.com/facebookgo/stats/stopper.go
new file mode 100644
index 00000000..38e8eab8
--- /dev/null
+++ b/vendor/github.com/facebookgo/stats/stopper.go
@@ -0,0 +1,17 @@
+package stats
+
+import "time"
+
+// Stopper calls Client.BumpSum and Client.BumpHistogram when End'ed
+type Stopper struct {
+ Key string
+ Start time.Time
+ Client Client
+}
+
+// End the Stopper
+func (s *Stopper) End() {
+ since := time.Since(s.Start).Seconds() * 1000.0
+ s.Client.BumpSum(s.Key+".total", since)
+ s.Client.BumpHistogram(s.Key, since)
+}