writer.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package protocol
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. // Write writes out data to a line protocol encoder. Note: it does no sorting. It assumes you have done your own sorting for tagValues
  7. func (e *Encoder) Write(name []byte, ts time.Time, tagKeys, tagVals, fieldKeys [][]byte, fieldVals []interface{}) (int, error) {
  8. e.header = e.header[:0]
  9. if len(name) == 0 || name[len(name)-1] == byte('\\') {
  10. return 0, ErrInvalidName
  11. }
  12. nameEscapeBytes(&e.header, name)
  13. for i := range tagKeys {
  14. // Some keys and values are not encodeable as line protocol, such as
  15. // those with a trailing '\' or empty strings.
  16. if len(tagKeys[i]) == 0 || len(tagVals[i]) == 0 || tagKeys[i][len(tagKeys[i])-1] == byte('\\') {
  17. if e.failOnFieldError {
  18. return 0, fmt.Errorf("invalid field: key \"%s\", val \"%s\"", tagKeys[i], tagVals[i])
  19. }
  20. continue
  21. }
  22. e.header = append(e.header, byte(','))
  23. escapeBytes(&e.header, tagKeys[i])
  24. e.header = append(e.header, byte('='))
  25. escapeBytes(&e.header, tagVals[i])
  26. }
  27. e.header = append(e.header, byte(' '))
  28. e.buildFooter(ts)
  29. i := 0
  30. totalWritten := 0
  31. pairsLen := 0
  32. firstField := true
  33. for i := range fieldKeys {
  34. e.pair = e.pair[:0]
  35. key := fieldKeys[i]
  36. if len(key) == 0 || key[len(key)-1] == byte('\\') {
  37. if e.failOnFieldError {
  38. return 0, &FieldError{"invalid field key"}
  39. }
  40. continue
  41. }
  42. escapeBytes(&e.pair, key)
  43. // Some keys are not encodeable as line protocol, such as those with a
  44. // trailing '\' or empty strings.
  45. e.pair = append(e.pair, byte('='))
  46. err := e.buildFieldVal(fieldVals[i])
  47. if err != nil {
  48. if e.failOnFieldError {
  49. return 0, err
  50. }
  51. continue
  52. }
  53. bytesNeeded := len(e.header) + pairsLen + len(e.pair) + len(e.footer)
  54. // Additional length needed for field separator `,`
  55. if !firstField {
  56. bytesNeeded++
  57. }
  58. if e.maxLineBytes > 0 && bytesNeeded > e.maxLineBytes {
  59. // Need at least one field per line
  60. if firstField {
  61. return 0, ErrNeedMoreSpace
  62. }
  63. i, err = e.w.Write(e.footer)
  64. if err != nil {
  65. return 0, err
  66. }
  67. totalWritten += i
  68. bytesNeeded = len(e.header) + len(e.pair) + len(e.footer)
  69. if e.maxLineBytes > 0 && bytesNeeded > e.maxLineBytes {
  70. return 0, ErrNeedMoreSpace
  71. }
  72. i, err = e.w.Write(e.header)
  73. if err != nil {
  74. return 0, err
  75. }
  76. totalWritten += i
  77. i, err = e.w.Write(e.pair)
  78. if err != nil {
  79. return 0, err
  80. }
  81. totalWritten += i
  82. pairsLen += len(e.pair)
  83. firstField = false
  84. continue
  85. }
  86. if firstField {
  87. i, err = e.w.Write(e.header)
  88. if err != nil {
  89. return 0, err
  90. }
  91. totalWritten += i
  92. } else {
  93. i, err = e.w.Write(comma)
  94. if err != nil {
  95. return 0, err
  96. }
  97. totalWritten += i
  98. }
  99. e.w.Write(e.pair)
  100. pairsLen += len(e.pair)
  101. firstField = false
  102. }
  103. if firstField {
  104. return 0, ErrNoFields
  105. }
  106. i, err := e.w.Write(e.footer)
  107. if err != nil {
  108. return 0, err
  109. }
  110. totalWritten += i
  111. return totalWritten, nil
  112. }