1package protocol
2
3import (
4	"fmt"
5	"hash/fnv"
6	"sort"
7	"time"
8)
9
10// Tag holds the keys and values for a bunch of Tag k/v pairs.
11type Tag struct {
12	Key   string
13	Value string
14}
15
16// Field holds the keys and values for a bunch of Metric Field k/v pairs where Value can be a uint64, int64, int, float32, float64, string, or bool.
17type Field struct {
18	Key   string
19	Value interface{}
20}
21
22// Metric is the interface for marshaling, if you implement this interface you can be marshalled into the line protocol.  Woot!
23type Metric interface {
24	Time() time.Time
25	Name() string
26	TagList() []*Tag
27	FieldList() []*Field
28}
29
30// MutableMetric represents a metric that can be be modified.
31type MutableMetric interface {
32	Metric
33	SetTime(time.Time)
34	AddTag(key, value string)
35	AddField(key string, value interface{})
36}
37
38// FieldSortOrder is a type for controlling if Fields are sorted
39type FieldSortOrder int
40
41const (
42	// NoSortFields tells the Decoder to not sort the fields.
43	NoSortFields FieldSortOrder = iota
44
45	// SortFields tells the Decoder to sort the fields.
46	SortFields
47)
48
49// FieldTypeSupport is a type for the parser to understand its type support.
50type FieldTypeSupport int
51
52const (
53	// UintSupport means the parser understands uint64s and can store them without having to convert to int64.
54	UintSupport FieldTypeSupport = 1 << iota
55)
56
57// MetricError is an error causing a metric to be unserializable.
58type MetricError struct {
59	s string
60}
61
62func (e MetricError) Error() string {
63	return e.s
64}
65
66// FieldError is an error causing a field to be unserializable.
67type FieldError struct {
68	s string
69}
70
71func (e FieldError) Error() string {
72	return e.s
73}
74
75var (
76	// ErrNeedMoreSpace tells us that the Decoder's io.Reader is full.
77	ErrNeedMoreSpace = &MetricError{"need more space"}
78
79	// ErrInvalidName tells us that the chosen name is invalid.
80	ErrInvalidName = &MetricError{"invalid name"}
81
82	// ErrNoFields tells us that there were no serializable fields in the line/metric.
83	ErrNoFields = &MetricError{"no serializable fields"}
84)
85
86type metric struct {
87	name   string
88	tags   []*Tag
89	fields []*Field
90	tm     time.Time
91}
92
93// New creates a new metric via maps.
94func New(
95	name string,
96	tags map[string]string,
97	fields map[string]interface{},
98	tm time.Time,
99) (MutableMetric, error) {
100	m := &metric{
101		name:   name,
102		tags:   nil,
103		fields: nil,
104		tm:     tm,
105	}
106
107	if len(tags) > 0 {
108		m.tags = make([]*Tag, 0, len(tags))
109		for k, v := range tags {
110			m.tags = append(m.tags,
111				&Tag{Key: k, Value: v})
112		}
113		sort.Slice(m.tags, func(i, j int) bool { return m.tags[i].Key < m.tags[j].Key })
114	}
115
116	if len(fields) > 0 {
117		m.fields = make([]*Field, 0, len(fields))
118		for k, v := range fields {
119			v := convertField(v)
120			if v == nil {
121				continue
122			}
123			m.AddField(k, v)
124		}
125	}
126
127	return m, nil
128}
129
130// FromMetric returns a deep copy of the metric with any tracking information
131// removed.
132func FromMetric(other Metric) Metric {
133	m := &metric{
134		name:   other.Name(),
135		tags:   make([]*Tag, len(other.TagList())),
136		fields: make([]*Field, len(other.FieldList())),
137		tm:     other.Time(),
138	}
139
140	for i, tag := range other.TagList() {
141		m.tags[i] = &Tag{Key: tag.Key, Value: tag.Value}
142	}
143
144	for i, field := range other.FieldList() {
145		m.fields[i] = &Field{Key: field.Key, Value: field.Value}
146	}
147	return m
148}
149
150func (m *metric) String() string {
151	return fmt.Sprintf("%s %v %v %d", m.name, m.Tags(), m.Fields(), m.tm.UnixNano())
152}
153
154func (m *metric) Name() string {
155	return m.name
156}
157
158func (m *metric) Tags() map[string]string {
159	tags := make(map[string]string, len(m.tags))
160	for _, tag := range m.tags {
161		tags[tag.Key] = tag.Value
162	}
163	return tags
164}
165
166func (m *metric) TagList() []*Tag {
167	return m.tags
168}
169
170func (m *metric) Fields() map[string]interface{} {
171	fields := make(map[string]interface{}, len(m.fields))
172	for _, field := range m.fields {
173		fields[field.Key] = field.Value
174	}
175
176	return fields
177}
178
179func (m *metric) FieldList() []*Field {
180	return m.fields
181}
182
183func (m *metric) Time() time.Time {
184	return m.tm
185}
186
187func (m *metric) SetName(name string) {
188	m.name = name
189}
190
191func (m *metric) AddPrefix(prefix string) {
192	m.name = prefix + m.name
193}
194
195func (m *metric) AddSuffix(suffix string) {
196	m.name = m.name + suffix
197}
198
199func (m *metric) AddTag(key, value string) {
200	for i, tag := range m.tags {
201		if key > tag.Key {
202			continue
203		}
204
205		if key == tag.Key {
206			tag.Value = value
207			return
208		}
209
210		m.tags = append(m.tags, nil)
211		copy(m.tags[i+1:], m.tags[i:])
212		m.tags[i] = &Tag{Key: key, Value: value}
213		return
214	}
215
216	m.tags = append(m.tags, &Tag{Key: key, Value: value})
217}
218
219func (m *metric) HasTag(key string) bool {
220	for _, tag := range m.tags {
221		if tag.Key == key {
222			return true
223		}
224	}
225	return false
226}
227
228func (m *metric) GetTag(key string) (string, bool) {
229	for _, tag := range m.tags {
230		if tag.Key == key {
231			return tag.Value, true
232		}
233	}
234	return "", false
235}
236
237func (m *metric) RemoveTag(key string) {
238	for i, tag := range m.tags {
239		if tag.Key == key {
240			copy(m.tags[i:], m.tags[i+1:])
241			m.tags[len(m.tags)-1] = nil
242			m.tags = m.tags[:len(m.tags)-1]
243			return
244		}
245	}
246}
247
248func (m *metric) AddField(key string, value interface{}) {
249	for i, field := range m.fields {
250		if key == field.Key {
251			m.fields[i] = &Field{Key: key, Value: convertField(value)}
252			return
253		}
254	}
255	m.fields = append(m.fields, &Field{Key: key, Value: convertField(value)})
256}
257
258func (m *metric) HasField(key string) bool {
259	for _, field := range m.fields {
260		if field.Key == key {
261			return true
262		}
263	}
264	return false
265}
266
267func (m *metric) GetField(key string) (interface{}, bool) {
268	for _, field := range m.fields {
269		if field.Key == key {
270			return field.Value, true
271		}
272	}
273	return nil, false
274}
275
276func (m *metric) RemoveField(key string) {
277	for i, field := range m.fields {
278		if field.Key == key {
279			copy(m.fields[i:], m.fields[i+1:])
280			m.fields[len(m.fields)-1] = nil
281			m.fields = m.fields[:len(m.fields)-1]
282			return
283		}
284	}
285}
286
287func (m *metric) SetTime(t time.Time) {
288	m.tm = t
289}
290
291func (m *metric) Copy() Metric {
292	m2 := &metric{
293		name:   m.name,
294		tags:   make([]*Tag, len(m.tags)),
295		fields: make([]*Field, len(m.fields)),
296		tm:     m.tm,
297	}
298
299	for i, tag := range m.tags {
300		m2.tags[i] = &Tag{Key: tag.Key, Value: tag.Value}
301	}
302
303	for i, field := range m.fields {
304		m2.fields[i] = &Field{Key: field.Key, Value: field.Value}
305	}
306	return m2
307}
308
309func (m *metric) HashID() uint64 {
310	h := fnv.New64a()
311	h.Write([]byte(m.name))
312	h.Write([]byte("\n"))
313	for _, tag := range m.tags {
314		h.Write([]byte(tag.Key))
315		h.Write([]byte("\n"))
316		h.Write([]byte(tag.Value))
317		h.Write([]byte("\n"))
318	}
319	return h.Sum64()
320}
321
322func (m *metric) Accept() {
323}
324
325func (m *metric) Reject() {
326}
327
328func (m *metric) Drop() {
329}
330
331// Convert field to a supported type or nil if unconvertible
332func convertField(v interface{}) interface{} {
333	switch v := v.(type) {
334	case float64:
335		return v
336	case int64:
337		return v
338	case string:
339		return v
340	case bool:
341		return v
342	case int:
343		return int64(v)
344	case uint:
345		return uint64(v)
346	case uint64:
347		return uint64(v)
348	case []byte:
349		return string(v)
350	case int32:
351		return int64(v)
352	case int16:
353		return int64(v)
354	case int8:
355		return int64(v)
356	case uint32:
357		return uint64(v)
358	case uint16:
359		return uint64(v)
360	case uint8:
361		return uint64(v)
362	case float32:
363		return float64(v)
364	case *float64:
365		if v != nil {
366			return *v
367		}
368	case *int64:
369		if v != nil {
370			return *v
371		}
372	case *string:
373		if v != nil {
374			return *v
375		}
376	case *bool:
377		if v != nil {
378			return *v
379		}
380	case *int:
381		if v != nil {
382			return int64(*v)
383		}
384	case *uint:
385		if v != nil {
386			return uint64(*v)
387		}
388	case *uint64:
389		if v != nil {
390			return uint64(*v)
391		}
392	case *[]byte:
393		if v != nil {
394			return string(*v)
395		}
396	case *int32:
397		if v != nil {
398			return int64(*v)
399		}
400	case *int16:
401		if v != nil {
402			return int64(*v)
403		}
404	case *int8:
405		if v != nil {
406			return int64(*v)
407		}
408	case *uint32:
409		if v != nil {
410			return uint64(*v)
411		}
412	case *uint16:
413		if v != nil {
414			return uint64(*v)
415		}
416	case *uint8:
417		if v != nil {
418			return uint64(*v)
419		}
420	case *float32:
421		if v != nil {
422			return float64(*v)
423		}
424	default:
425		return nil
426	}
427	return nil
428}
429