entry.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package gonx
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. // Fields is a shortcut for the map of strings
  8. type Fields map[string]string
  9. // Entry is a parsed log record. Use Get method to retrieve a value by name instead of
  10. // threating this as a map, because inner representation is in design.
  11. type Entry struct {
  12. fields Fields
  13. }
  14. // NewEmptyEntry creates an empty Entry to be filled later
  15. func NewEmptyEntry() *Entry {
  16. return &Entry{make(Fields)}
  17. }
  18. // NewEntry creates an Entry with fiven fields
  19. func NewEntry(fields Fields) *Entry {
  20. return &Entry{fields}
  21. }
  22. // Field returns an entry field value by name or empty string and error if it
  23. // does not exist.
  24. func (entry *Entry) Field(name string) (value string, err error) {
  25. value, ok := entry.fields[name]
  26. if !ok {
  27. err = fmt.Errorf("field '%v' does not found in record %+v", name, *entry)
  28. }
  29. return
  30. }
  31. // FloatField returns an entry field value as float64. Return nil if field does not exist
  32. // and conversion error if cannot cast a type.
  33. func (entry *Entry) FloatField(name string) (value float64, err error) {
  34. tmp, err := entry.Field(name)
  35. if err == nil {
  36. value, err = strconv.ParseFloat(tmp, 64)
  37. }
  38. return
  39. }
  40. // SetField sets the value of a field
  41. func (entry *Entry) SetField(name string, value string) {
  42. entry.fields[name] = value
  43. }
  44. // SetFloatField is a Float field value setter. It accepts float64, but still store it as a
  45. // string in the same fields map. The precision is 2, its enough for log
  46. // parsing task
  47. func (entry *Entry) SetFloatField(name string, value float64) {
  48. entry.SetField(name, strconv.FormatFloat(value, 'f', 2, 64))
  49. }
  50. // SetUintField is a Integer field value setter. It accepts float64, but still store it as a
  51. // string in the same fields map.
  52. func (entry *Entry) SetUintField(name string, value uint64) {
  53. entry.SetField(name, strconv.FormatUint(uint64(value), 10))
  54. }
  55. // Merge two entries by updating values for master entry with given.
  56. func (entry *Entry) Merge(merge *Entry) {
  57. for name, value := range merge.fields {
  58. entry.SetField(name, value)
  59. }
  60. }
  61. // FieldsHash returns a hash of all fields
  62. func (entry *Entry) FieldsHash(fields []string) string {
  63. var key []string
  64. for _, name := range fields {
  65. value, err := entry.Field(name)
  66. if err != nil {
  67. value = "NULL"
  68. }
  69. key = append(key, fmt.Sprintf("'%v'=%v", name, value))
  70. }
  71. return strings.Join(key, ";")
  72. }
  73. // Partial returns a partial field entry with the specified fields
  74. func (entry *Entry) Partial(fields []string) *Entry {
  75. partial := NewEmptyEntry()
  76. for _, name := range fields {
  77. value, _ := entry.Field(name)
  78. partial.SetField(name, value)
  79. }
  80. return partial
  81. }