Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
4.2 KiB
166 lines
4.2 KiB
// 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 |
|
}
|
|
|