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