1package protocol 2 3import ( 4 "bytes" 5 "errors" 6 "strconv" 7 "time" 8) 9 10// MetricHandler implements the Handler interface and produces Metric. 11type MetricHandler struct { 12 timePrecision time.Duration 13 timeFunc TimeFunc 14 metric MutableMetric 15} 16 17func NewMetricHandler() *MetricHandler { 18 return &MetricHandler{ 19 timePrecision: time.Nanosecond, 20 timeFunc: time.Now, 21 } 22} 23 24func (h *MetricHandler) SetTimePrecision(p time.Duration) { 25 h.timePrecision = p 26 // When the timestamp is omitted from the metric, the timestamp 27 // comes from the server clock, truncated to the nearest unit of 28 // measurement provided in precision. 29 // 30 // When a timestamp is provided in the metric, precsision is 31 // overloaded to hold the unit of measurement of the timestamp. 32} 33 34func (h *MetricHandler) SetTimeFunc(f TimeFunc) { 35 h.timeFunc = f 36} 37 38func (h *MetricHandler) Metric() (Metric, error) { 39 if h.metric.Time().IsZero() { 40 h.metric.SetTime(h.timeFunc().Truncate(h.timePrecision)) 41 } 42 return h.metric, nil 43} 44 45func (h *MetricHandler) SetMeasurement(name []byte) error { 46 var err error 47 h.metric, err = New(nameUnescape(name), 48 nil, nil, time.Time{}) 49 return err 50} 51 52func (h *MetricHandler) AddTag(key []byte, value []byte) error { 53 tk := unescape(key) 54 tv := unescape(value) 55 h.metric.AddTag(tk, tv) 56 return nil 57} 58 59func (h *MetricHandler) AddInt(key []byte, value []byte) error { 60 fk := unescape(key) 61 fv, err := parseIntBytes(bytes.TrimSuffix(value, []byte("i")), 10, 64) 62 if err != nil { 63 if numerr, ok := err.(*strconv.NumError); ok { 64 return numerr.Err 65 } 66 return err 67 } 68 h.metric.AddField(fk, fv) 69 return nil 70} 71 72func (h *MetricHandler) AddUint(key []byte, value []byte) error { 73 fk := unescape(key) 74 fv, err := parseUintBytes(bytes.TrimSuffix(value, []byte("u")), 10, 64) 75 if err != nil { 76 if numerr, ok := err.(*strconv.NumError); ok { 77 return numerr.Err 78 } 79 return err 80 } 81 h.metric.AddField(fk, fv) 82 return nil 83} 84 85func (h *MetricHandler) AddFloat(key []byte, value []byte) error { 86 fk := unescape(key) 87 fv, err := parseFloatBytes(value, 64) 88 if err != nil { 89 if numerr, ok := err.(*strconv.NumError); ok { 90 return numerr.Err 91 } 92 return err 93 } 94 h.metric.AddField(fk, fv) 95 return nil 96} 97 98func (h *MetricHandler) AddString(key []byte, value []byte) error { 99 fk := unescape(key) 100 fv := stringFieldUnescape(value) 101 h.metric.AddField(fk, fv) 102 return nil 103} 104 105func (h *MetricHandler) AddBool(key []byte, value []byte) error { 106 fk := unescape(key) 107 fv, err := parseBoolBytes(value) 108 if err != nil { 109 return errors.New("unparseable bool") 110 } 111 h.metric.AddField(fk, fv) 112 return nil 113} 114 115func (h *MetricHandler) SetTimestamp(tm []byte) error { 116 v, err := parseIntBytes(tm, 10, 64) 117 if err != nil { 118 if numerr, ok := err.(*strconv.NumError); ok { 119 return numerr.Err 120 } 121 return err 122 } 123 124 //time precision is overloaded to mean time unit here 125 ns := v * int64(h.timePrecision) 126 h.metric.SetTime(time.Unix(0, ns)) 127 return nil 128} 129