func (d *Dogstatsd) WriteTo(w io.Writer) (count int64, err error) {
	var n int
	d.counters.Reset().Walk(func(name string, lvs lv.LabelValues, values []float64) bool {
		n, err = fmt.Fprintf(w, "%s:%f|c%s%s\n", name, sum(values), sampling(d.rates.Get(name)), tagValues(lvs))
		if err != nil {
			return false
		}
		count += int64(n)
		return true
	})
	if err != nil {
		return count, err
	}
	d.gauges.Reset().Walk(func(name string, lvs lv.LabelValues, values []float64) bool {
		n, err = fmt.Fprintf(w, "%s:%f|g%s\n", name, last(values), tagValues(lvs))
		if err != nil {
			return false
		}
		count += int64(n)
		return true
	})
	if err != nil {
		return count, err
	}
	d.timings.Reset().Walk(func(name string, lvs lv.LabelValues, values []float64) bool {
		sampleRate := d.rates.Get(name)
		for _, value := range values {
			n, err = fmt.Fprintf(w, "%s:%f|ms%s%s\n", name, value, sampling(sampleRate), tagValues(lvs))
			if err != nil {
				return false
			}
			count += int64(n)
		}
		return true
	})
	if err != nil {
		return count, err
	}
	d.histograms.Reset().Walk(func(name string, lvs lv.LabelValues, values []float64) bool {
		sampleRate := d.rates.Get(name)
		for _, value := range values {
			n, err = fmt.Fprintf(w, "%s:%f|h%s%s\n", name, value, sampling(sampleRate), tagValues(lvs))
			if err != nil {
				return false
			}
			count += int64(n)
		}
		return true
	})
	if err != nil {
		return count, err
	}
	return count, err
}
WriteTo flushes the buffered content of the metrics to the writer, in
DogStatsD format. WriteTo abides best-effort semantics, so observations are
lost if there is a problem with the write. Clients should be sure to call
WriteTo regularly, ideally through the WriteLoop or SendLoop helper methods.
package dogstatsd
import (
	"fmt"
	"io"
	"strings"
	"time"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/metrics"
	"github.com/go-kit/kit/metrics/internal/lv"
	"github.com/go-kit/kit/metrics/internal/ratemap"
	"github.com/go-kit/kit/util/conn"
)
type Dogstatsd struct {
	prefix     string
	rates      *ratemap.RateMap
	counters   *lv.Space
	gauges     *lv.Space
	timings    *lv.Space
	histograms *lv.Space
	logger     log.Logger
}
func New(prefix string, logger log.Logger) *Dogstatsd {
	return &Dogstatsd{
		prefix:     prefix,
		rates:      ratemap.New(),
		counters:   lv.NewSpace(),
		gauges:     lv.NewSpace(),
		timings:    lv.NewSpace(),
		histograms: lv.NewSpace(),
		logger:     logger,
	}
}
func (d *Dogstatsd) NewCounter(name string, sampleRate float64) *Counter {
	d.rates.Set(d.prefix+name, sampleRate)
	return &Counter{
		name: d.prefix + name,
		obs:  d.counters.Observe,
	}
}
func (d *Dogstatsd) NewGauge(name string) *Gauge {
	return &Gauge{
		name: d.prefix + name,
		obs:  d.gauges.Observe,
		add:  d.gauges.Add,
	}
}
func (d *Dogstatsd) NewTiming(name string, sampleRate float64) *Timing {
	d.rates.Set(d.prefix+name, sampleRate)
	return &Timing{
		name: d.prefix + name,
		obs:  d.timings.Observe,
	}
}
func (d *Dogstatsd) NewHistogram(name string, sampleRate float64) *Histogram {
	d.rates.Set(d.prefix+name, sampleRate)
	return &Histogram{
		name: d.prefix + name,
		obs:  d.histograms.Observe,
	}
}
func (d *Dogstatsd) WriteLoop(c <-chan time.Time, w io.Writer) {
	for range c {
		if _, err := d.WriteTo(w); err != nil {
			d.logger.Log("during", "WriteTo", "err", err)
		}
	}
}
func (d *Dogstatsd) SendLoop(c <-chan time.Time, network, address string) {
	d.WriteLoop(c, conn.NewDefaultManager(network, address, d.logger))
}