func (eng *Engine) Report(metrics interface{}, tags ...Tag) {
	eng.ReportAt(time.Now(), metrics, tags...)
}
Report calls ReportAt with time.Now() as first argument.
package stats
import (
	"os"
	"path/filepath"
	"reflect"
	"sync"
	"time"
)
type Engine struct {
	Handler Handler
	Prefix string
	Tags []Tag
	cache measureCache
}
func NewEngine(prefix string, handler Handler, tags ...Tag) *Engine {
	return &Engine{
		Handler: handler,
		Prefix:  prefix,
		Tags:    SortTags(copyTags(tags)),
	}
}
func (eng *Engine) Register(handler Handler) {
	if eng.Handler == Discard {
		eng.Handler = handler
	} else {
		eng.Handler = MultiHandler(eng.Handler, handler)
	}
}
func (eng *Engine) Flush() {
	flush(eng.Handler)
}
func (eng *Engine) WithPrefix(prefix string, tags ...Tag) *Engine {
	return &Engine{
		Handler: eng.Handler,
		Prefix:  eng.makeName(prefix),
		Tags:    eng.makeTags(tags),
	}
}
func (eng *Engine) WithTags(tags ...Tag) *Engine {
	return eng.WithPrefix("", tags...)
}
func (eng *Engine) Incr(name string, tags ...Tag) {
	eng.Add(name, 1, tags...)
}
func (eng *Engine) IncrAt(time time.Time, name string, tags ...Tag) {
	eng.AddAt(time, name, 1, tags...)
}
func (eng *Engine) Add(name string, value interface{}, tags ...Tag) {
	eng.measure(time.Now(), name, value, Counter, tags...)
}
func (eng *Engine) AddAt(t time.Time, name string, value interface{}, tags ...Tag) {
	eng.measure(t, name, value, Counter, tags...)
}
func (eng *Engine) Set(name string, value interface{}, tags ...Tag) {
	eng.measure(time.Now(), name, value, Gauge, tags...)
}
func (eng *Engine) SetAt(t time.Time, name string, value interface{}, tags ...Tag) {
	eng.measure(t, name, value, Gauge, tags...)
}
func (eng *Engine) Observe(name string, value interface{}, tags ...Tag) {
	eng.measure(time.Now(), name, value, Histogram, tags...)
}
func (eng *Engine) ObserveAt(t time.Time, name string, value interface{}, tags ...Tag) {
	eng.measure(t, name, value, Histogram, tags...)
}
func (eng *Engine) Clock(name string, tags ...Tag) *Clock {
	return eng.ClockAt(name, time.Now(), tags...)
}
func (eng *Engine) ClockAt(name string, start time.Time, tags ...Tag) *Clock {
	cpy := make([]Tag, len(tags), len(tags)+1)  
	copy(cpy, tags)
	return &Clock{
		name:  name,
		first: start,
		last:  start,
		tags:  cpy,
		eng:   eng,
	}
}
func (eng *Engine) measure(t time.Time, name string, value interface{}, ftype FieldType, tags ...Tag) {
	name, field := splitMeasureField(name)
	mp := measureArrayPool.Get().(*[1]Measure)
	m := &(*mp)[0]
	m.Name = eng.makeName(name)  
	m.Fields = append(m.Fields[:0], MakeField(field, value, ftype))
	m.Tags = append(m.Tags[:0], eng.Tags...)
	m.Tags = append(m.Tags, tags...)
	if len(tags) != 0 && !TagsAreSorted(m.Tags) {
		SortTags(m.Tags)
	}
	eng.Handler.HandleMeasures(t, (*mp)[:]...)
	for i := range m.Fields {
		m.Fields[i] = Field{}
	}
	for i := range m.Tags {
		m.Tags[i] = Tag{}
	}
	m.Name = ""
	measureArrayPool.Put(mp)
}
func (eng *Engine) makeName(name string) string {
	return concat(eng.Prefix, name)
}
func (eng *Engine) makeTags(tags []Tag) []Tag {
	return SortTags(concatTags(eng.Tags, tags))
}
var measureArrayPool = sync.Pool{
	New: func() interface{} { return new([1]Measure) },
}