hemera is a zero-dependency statsd implementation written in Go. The project takes advantage of modular packages and interfaces to make connecting to any backend simple. By default, the hemera binary connects to a Graphite server over TCP.
- Installing hemera
- Basic usage
- Supported metrics
- Creating new backend interfaces
- Using new backend interfaces
- To Do
Install the binary by running the following:
go install github.com/andresoro/hemera
Install both the binary and the package by running:
go get github.com/andresoro/hemera
First make sure the package has been installed then simply run the following to run hemera with default configuration.
hemera
This will start the server with default configuration with the following flags but each one can be changed individually:
-p 8484
port where hemera server listens for metrics over UDP-g 2003
port to connect to graphite instance to purge metrics over TCP-s localhost
server host-t 10
interval in seconds for purging metrics to the server
# listen for metrics on port 8000 and purge to backend every 5 seconds
hemera -p 8000 -t 5
hemera supports the four metrics that statsd supports. They are of the following form where bucket represents the name of the metric to update.
<bucket>:<value>|<metric-type>|@<sampling-rate>
Counters represent metrics that can only be incremented. During each purge cycle the counter is reset to 0.
# increment the 'button' bucket by 2
button:2|c
Sets hold a unique collection of values which represent events from the client. What is purge is the cardinality of the set at the purge interval.
# set named uniques will add the value '22' only if it does not already exist
uniques:22|s
A gauge can fluctuate positively or negatively and will take on an arbitrary value assigned to it.
# set the 'gaugor' gauge to 100
gaugor:100|g
# set the 'gaugor' gauge to 1000
gaugor:1000|g
Timers generate an array of statistics that are purged to the backend:
- Min/Max value
- Count
- Average
- Median
- 95th percentile
- Standard Deviation
Timers currently only support the ms
metric tag.
Hemera has two timer metrics. First is the raw input metrics under cache.Timers
and the second is the computed metric statistics in this form <metric-name>.min.<value>
which is returned by cache.TimerStats()
.
# load-time took 225ms to complete this time
load-time:225|ms
Backends must simply satisfy the following interface:
type Backend interface {
Purge(c *cache.Cache) error
}
It is up to the user to decide how to purge the actual values out. The cache.Cache
struct exports all the values that are currently held since last purge cycle.
Warning: Do not clear the cache from the Purge() function as it is done by the server. Would cause issues when using multiple backends.
For example, a backend implementation where we only purge counters to the standard output would look like this.
type ConsoleBackend struct{}
// implement backend interface
func (cb *ConsoleBackend) Purge(c *cache.Cache) error {
// only handling counters
for name, value := range c.Counters {
fmt.Printf("counter name: %s value: %f \n", name, value)
}
return nil
}
Remember while the cache.Timers
map holds raw timer metrics, the statistics (min,max, std dev, etc) comes from calling cache.TimerStats()
and getting values from the cache.TimerData
map.
Take a look at the graphite implementation for a more robust example.
The server takes care of the cache and metric collection. If you want to use a new backend interface simply define it and add it to a new server instance. The server.New()
function can take in a variadic amount of backends.
import github.com/andresoro/hemera/pkg/backend
import github.com/andresoro/hemera/pkg/server
// import a backend from the hemera backend package
graphite := &backend.Graphite{Addr: "localhost:2003"}
// and use a backend you implemented
console := &ConsoleBackend{}
// new server with given purge interval, host/port, and the backends that we would like to purge to.
srv, err := server.New(purgeTime, host, port, graphite, console)
srv.Run()
- Actually tackle to-dos
- Add support for incrementing/decrementing gauges with '+' or '-' signs in metric value.
- Benchmark tests
- Better logging
- Full testing