435c0d9fc8
This PR switches the Nomad repository from using govendor to Go modules for managing dependencies. Aspects of the Nomad workflow remain pretty much the same. The usual Makefile targets should continue to work as they always did. The API submodule simply defers to the parent Nomad version on the repository, keeping the semantics of API versioning that currently exists.
131 lines
4 KiB
Go
131 lines
4 KiB
Go
package statsd
|
|
|
|
type bufferFullError string
|
|
|
|
func (e bufferFullError) Error() string { return string(e) }
|
|
|
|
const errBufferFull = bufferFullError("statsd buffer is full")
|
|
|
|
const metricOverhead = 512
|
|
|
|
// statsdBuffer is a buffer containing statsd messages
|
|
// this struct methods are NOT safe for concurent use
|
|
type statsdBuffer struct {
|
|
buffer []byte
|
|
maxSize int
|
|
maxElements int
|
|
elementCount int
|
|
}
|
|
|
|
func newStatsdBuffer(maxSize, maxElements int) *statsdBuffer {
|
|
return &statsdBuffer{
|
|
buffer: make([]byte, 0, maxSize+metricOverhead), // pre-allocate the needed size + metricOverhead to avoid having Go re-allocate on it's own if an element does not fit
|
|
maxSize: maxSize,
|
|
maxElements: maxElements,
|
|
}
|
|
}
|
|
|
|
func (b *statsdBuffer) writeGauge(namespace string, globalTags []string, name string, value float64, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendGauge(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeCount(namespace string, globalTags []string, name string, value int64, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendCount(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeHistogram(namespace string, globalTags []string, name string, value float64, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendHistogram(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeDistribution(namespace string, globalTags []string, name string, value float64, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendDistribution(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeSet(namespace string, globalTags []string, name string, value string, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendSet(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeTiming(namespace string, globalTags []string, name string, value float64, tags []string, rate float64) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendTiming(b.buffer, namespace, globalTags, name, value, tags, rate)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeEvent(event Event, globalTags []string) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendEvent(b.buffer, event, globalTags)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) writeServiceCheck(serviceCheck ServiceCheck, globalTags []string) error {
|
|
if b.elementCount >= b.maxElements {
|
|
return errBufferFull
|
|
}
|
|
originalBuffer := b.buffer
|
|
b.writeSeparator()
|
|
b.buffer = appendServiceCheck(b.buffer, serviceCheck, globalTags)
|
|
return b.validateNewElement(originalBuffer)
|
|
}
|
|
|
|
func (b *statsdBuffer) validateNewElement(originalBuffer []byte) error {
|
|
if len(b.buffer) > b.maxSize {
|
|
b.buffer = originalBuffer
|
|
return errBufferFull
|
|
}
|
|
b.elementCount++
|
|
return nil
|
|
}
|
|
|
|
func (b *statsdBuffer) writeSeparator() {
|
|
if b.elementCount != 0 {
|
|
b.buffer = appendSeparator(b.buffer)
|
|
}
|
|
}
|
|
|
|
func (b *statsdBuffer) reset() {
|
|
b.buffer = b.buffer[:0]
|
|
b.elementCount = 0
|
|
}
|
|
|
|
func (b *statsdBuffer) bytes() []byte {
|
|
return b.buffer
|
|
}
|