mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
151 lines
4.1 KiB
Go
151 lines
4.1 KiB
Go
// Copyright 2021 Molecula Corp. All rights reserved.
|
|
package statsd
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/DataDog/datadog-go/statsd"
|
|
"github.com/molecula/featurebase/v3/logger"
|
|
"github.com/molecula/featurebase/v3/stats"
|
|
)
|
|
|
|
// StatsD protocol wrapper using the DataDog library that added Tags to the StatsD protocol
|
|
// statsD defailt host is "127.0.0.1:8125"
|
|
|
|
const (
|
|
// bufferLen Stats lient buffer size.
|
|
bufferLen = 1024
|
|
)
|
|
|
|
// Ensure client implements interface.
|
|
var _ stats.StatsClient = &statsClient{}
|
|
|
|
// statsClient represents a StatsD implementation of pilosa.statsClient.
|
|
type statsClient struct {
|
|
client *statsd.Client
|
|
tags []string
|
|
logger logger.Logger
|
|
|
|
// prefix is appended to each metric event name
|
|
prefix string
|
|
}
|
|
|
|
// NewStatsClient returns a new instance of StatsClient.
|
|
func NewStatsClient(host string, namespace string) (*statsClient, error) {
|
|
c, err := statsd.NewBuffered(host, bufferLen)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &statsClient{
|
|
client: c,
|
|
logger: logger.NopLogger,
|
|
prefix: namespace + ".",
|
|
}, nil
|
|
}
|
|
|
|
// Open no-op
|
|
func (c *statsClient) Open() {}
|
|
|
|
// Close closes the connection to the agent.
|
|
func (c *statsClient) Close() error {
|
|
return c.client.Close()
|
|
}
|
|
|
|
// Tags returns a sorted list of tags on the client.
|
|
func (c *statsClient) Tags() []string {
|
|
return c.tags
|
|
}
|
|
|
|
// WithTags returns a new client with additional tags appended.
|
|
func (c *statsClient) WithTags(tags ...string) stats.StatsClient {
|
|
return &statsClient{
|
|
client: c.client,
|
|
tags: unionStringSlice(c.tags, tags),
|
|
logger: c.logger,
|
|
}
|
|
}
|
|
|
|
// Count tracks the number of times something occurs per second.
|
|
func (c *statsClient) Count(name string, value int64, rate float64) {
|
|
if err := c.client.Count(c.prefix+name, value, c.tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Count error: %s", err)
|
|
}
|
|
}
|
|
|
|
// CountWithCustomTags tracks the number of times something occurs per second with custom tags.
|
|
func (c *statsClient) CountWithCustomTags(name string, value int64, rate float64, t []string) {
|
|
tags := append(c.tags, t...)
|
|
if err := c.client.Count(c.prefix+name, value, tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Count error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Gauge sets the value of a metric.
|
|
func (c *statsClient) Gauge(name string, value float64, rate float64) {
|
|
if err := c.client.Gauge(c.prefix+name, value, c.tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Gauge error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Histogram tracks statistical distribution of a metric.
|
|
func (c *statsClient) Histogram(name string, value float64, rate float64) {
|
|
if err := c.client.Histogram(c.prefix+name, value, c.tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Histogram error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Set tracks number of unique elements.
|
|
func (c *statsClient) Set(name string, value string, rate float64) {
|
|
if err := c.client.Set(c.prefix+name, value, c.tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Set error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Timing tracks timing information for a metric.
|
|
func (c *statsClient) Timing(name string, value time.Duration, rate float64) {
|
|
if err := c.client.Timing(c.prefix+name, value, c.tags, rate); err != nil {
|
|
c.logger.Errorf("statsd.StatsClient.Timing error: %s", err)
|
|
}
|
|
}
|
|
|
|
// SetLogger sets the logger for client.
|
|
func (c *statsClient) SetLogger(logger logger.Logger) {
|
|
c.logger = logger
|
|
}
|
|
|
|
// unionStringSlice returns a sorted set of tags which combine a & b.
|
|
func unionStringSlice(a, b []string) []string {
|
|
// Sort both sets first.
|
|
sort.Strings(a)
|
|
sort.Strings(b)
|
|
|
|
// Find size of largest slice.
|
|
n := len(a)
|
|
if len(b) > n {
|
|
n = len(b)
|
|
}
|
|
|
|
// Exit if both sets are empty.
|
|
if n == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Iterate over both in order and merge.
|
|
other := make([]string, 0, n)
|
|
for len(a) > 0 || len(b) > 0 {
|
|
if len(a) == 0 {
|
|
other, b = append(other, b[0]), b[1:]
|
|
} else if len(b) == 0 {
|
|
other, a = append(other, a[0]), a[1:]
|
|
} else if a[0] < b[0] {
|
|
other, a = append(other, a[0]), a[1:]
|
|
} else if b[0] < a[0] {
|
|
other, b = append(other, b[0]), b[1:]
|
|
} else {
|
|
other, a, b = append(other, a[0]), a[1:], b[1:]
|
|
}
|
|
}
|
|
return other
|
|
}
|