wavefront_parser_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package wavefrontreceiver
  4. import (
  5. "math"
  6. "testing"
  7. "time"
  8. "github.com/stretchr/testify/assert"
  9. "go.opentelemetry.io/collector/pdata/pcommon"
  10. "go.opentelemetry.io/collector/pdata/pmetric"
  11. )
  12. func Test_buildLabels(t *testing.T) {
  13. tests := []struct {
  14. name string
  15. tags string
  16. wantAttributes pcommon.Map
  17. wantErr bool
  18. }{
  19. {
  20. name: "empty_tags",
  21. wantAttributes: pcommon.NewMap(),
  22. },
  23. {
  24. name: "only_source",
  25. tags: "source=test",
  26. wantAttributes: func() pcommon.Map {
  27. m := pcommon.NewMap()
  28. m.PutStr("source", "test")
  29. return m
  30. }(),
  31. },
  32. {
  33. name: "no_quotes",
  34. tags: "source=tst k0=v0 k1=v1",
  35. wantAttributes: func() pcommon.Map {
  36. m := pcommon.NewMap()
  37. m.PutStr("source", "tst")
  38. m.PutStr("k0", "v0")
  39. m.PutStr("k1", "v1")
  40. return m
  41. }(),
  42. },
  43. {
  44. name: "end_with_quotes",
  45. tags: "source=\"tst escape\\\" tst\" x=\"tst spc\"",
  46. wantAttributes: func() pcommon.Map {
  47. m := pcommon.NewMap()
  48. m.PutStr("source", "tst escape\" tst")
  49. m.PutStr("x", "tst spc")
  50. return m
  51. }(),
  52. },
  53. {
  54. name: "multiple_escapes",
  55. tags: "source=\"tst\\\"\\ntst\\\"\" bgn=\"\nb\" mid=\"tst\\nspc\" end=\"e\n\"",
  56. wantAttributes: func() pcommon.Map {
  57. m := pcommon.NewMap()
  58. m.PutStr("source", "tst\"\ntst\"")
  59. m.PutStr("bgn", "\nb")
  60. m.PutStr("mid", "tst\nspc")
  61. m.PutStr("end", "e\n")
  62. return m
  63. }(),
  64. },
  65. {
  66. name: "missing_tagValue",
  67. tags: "k0=0 k1= k2=2",
  68. wantAttributes: func() pcommon.Map {
  69. m := pcommon.NewMap()
  70. m.PutStr("k0", "0")
  71. m.PutStr("k1", "")
  72. m.PutStr("k2", "2")
  73. return m
  74. }(),
  75. },
  76. {
  77. name: "empty_tagValue",
  78. tags: "k0=0 k1=\"\"",
  79. wantAttributes: func() pcommon.Map {
  80. m := pcommon.NewMap()
  81. m.PutStr("k0", "0")
  82. m.PutStr("k1", "")
  83. return m
  84. }(),
  85. },
  86. {
  87. name: "no_tag",
  88. tags: "k0=0 k1",
  89. wantErr: true,
  90. },
  91. }
  92. for _, tt := range tests {
  93. t.Run(tt.name, func(t *testing.T) {
  94. gotAttributes := pcommon.NewMap()
  95. err := buildLabels(gotAttributes, tt.tags)
  96. if !tt.wantErr {
  97. assert.Equal(t, tt.wantAttributes, gotAttributes)
  98. }
  99. assert.Equal(t, tt.wantErr, err != nil)
  100. })
  101. }
  102. }
  103. func Test_wavefrontParser_Parse(t *testing.T) {
  104. tests := []struct {
  105. line string
  106. extractCollectDTags bool
  107. missingTimestamp bool
  108. want pmetric.Metric
  109. wantErr bool
  110. }{
  111. {
  112. line: "no.tags 1 1582230020",
  113. want: buildIntMetric(
  114. "no.tags",
  115. pcommon.NewMap(),
  116. 1582230020,
  117. 1,
  118. ),
  119. },
  120. {
  121. line: "\"/and,\" 1 1582230020 source=tst",
  122. want: buildIntMetric(
  123. "/and,",
  124. func() pcommon.Map {
  125. m := pcommon.NewMap()
  126. m.PutStr("source", "tst")
  127. return m
  128. }(),
  129. 1582230020,
  130. 1,
  131. ),
  132. },
  133. {
  134. line: "tst.int 1 1582230020 source=tst",
  135. want: buildIntMetric(
  136. "tst.int",
  137. func() pcommon.Map {
  138. m := pcommon.NewMap()
  139. m.PutStr("source", "tst")
  140. return m
  141. }(),
  142. 1582230020,
  143. 1,
  144. ),
  145. },
  146. {
  147. line: "tst.dbl 3.14 source=tst k0=v0",
  148. missingTimestamp: true,
  149. want: buildDoubleMetric(
  150. "tst.dbl",
  151. func() pcommon.Map {
  152. m := pcommon.NewMap()
  153. m.PutStr("source", "tst")
  154. m.PutStr("k0", "v0")
  155. return m
  156. }(),
  157. 0,
  158. 3.14,
  159. ),
  160. },
  161. {
  162. line: "tst.int.3tags 128 1582230020 k0=v_0 k1=v_1 k2=v_2",
  163. want: buildIntMetric(
  164. "tst.int.3tags",
  165. func() pcommon.Map {
  166. m := pcommon.NewMap()
  167. m.PutStr("k0", "v_0")
  168. m.PutStr("k1", "v_1")
  169. m.PutStr("k2", "v_2")
  170. return m
  171. }(),
  172. 1582230020,
  173. 128,
  174. ),
  175. },
  176. {
  177. line: "tst.int.1tag 1.23 1582230020 k0=v_0",
  178. want: buildDoubleMetric(
  179. "tst.int.1tag",
  180. func() pcommon.Map {
  181. m := pcommon.NewMap()
  182. m.PutStr("k0", "v_0")
  183. return m
  184. }(),
  185. 1582230020,
  186. 1.23,
  187. ),
  188. },
  189. {
  190. line: "collectd.[cdk=cdv].tags 1 source=tst k0=v0",
  191. missingTimestamp: true,
  192. extractCollectDTags: true,
  193. want: buildIntMetric(
  194. "collectd.tags",
  195. func() pcommon.Map {
  196. m := pcommon.NewMap()
  197. m.PutStr("source", "tst")
  198. m.PutStr("k0", "v0")
  199. m.PutStr("cdk", "cdv")
  200. return m
  201. }(),
  202. 0,
  203. 1,
  204. ),
  205. },
  206. {
  207. line: "mult.[cdk0=cdv0].collectd.[cdk1=cdv1].groups 1 1582230020 source=tst",
  208. extractCollectDTags: true,
  209. want: buildIntMetric(
  210. "mult.collectd.groups",
  211. func() pcommon.Map {
  212. m := pcommon.NewMap()
  213. m.PutStr("source", "tst")
  214. m.PutStr("cdk0", "cdv0")
  215. m.PutStr("cdk1", "cdv1")
  216. return m
  217. }(),
  218. 1582230020,
  219. 1,
  220. ),
  221. },
  222. {
  223. line: "collectd.last[cdk0=cdv0] 1 1582230020 source=tst",
  224. extractCollectDTags: true,
  225. want: buildIntMetric(
  226. "collectd.last",
  227. func() pcommon.Map {
  228. m := pcommon.NewMap()
  229. m.PutStr("source", "tst")
  230. m.PutStr("cdk0", "cdv0")
  231. return m
  232. }(),
  233. 1582230020,
  234. 1,
  235. ),
  236. },
  237. {
  238. line: "incorrect.tags 1.23 1582230000 1582230020",
  239. wantErr: true,
  240. },
  241. {
  242. line: "nan.value xyz 1582230000 source=tst",
  243. wantErr: true,
  244. },
  245. {
  246. line: " 1.23 1582230000",
  247. wantErr: true,
  248. },
  249. {
  250. line: "invalid.timestamppb.not.tag 1.23 xyz source=tst",
  251. wantErr: true,
  252. },
  253. {
  254. line: "missing.parts 3",
  255. wantErr: true,
  256. },
  257. }
  258. for _, tt := range tests {
  259. t.Run(tt.line, func(t *testing.T) {
  260. p := WavefrontParser{ExtractCollectdTags: tt.extractCollectDTags}
  261. got, err := p.Parse(tt.line)
  262. if tt.missingTimestamp {
  263. // The timestamp was actually generated by the parser.
  264. // Assert that it is within a certain range around now.
  265. unixNow := time.Now().Unix()
  266. ts := got.Gauge().DataPoints().At(0).Timestamp().AsTime()
  267. assert.LessOrEqual(t, ts, time.Now())
  268. assert.LessOrEqual(t, math.Abs(float64(ts.Unix()-unixNow)), 2.0)
  269. // Copy returned timestamp so asserts below can succeed.
  270. tt.want.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(ts))
  271. }
  272. assert.Equal(t, tt.want, got)
  273. assert.Equal(t, tt.wantErr, err != nil)
  274. })
  275. }
  276. }
  277. func buildDoubleMetric(
  278. name string,
  279. attributes pcommon.Map,
  280. ts int64,
  281. dblVal float64,
  282. ) pmetric.Metric {
  283. metric := pmetric.NewMetric()
  284. metric.SetName(name)
  285. g := metric.SetEmptyGauge()
  286. dp := g.DataPoints().AppendEmpty()
  287. dp.SetDoubleValue(dblVal)
  288. dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Unix(ts, 0)))
  289. attributes.CopyTo(dp.Attributes())
  290. return metric
  291. }
  292. func buildIntMetric(
  293. name string,
  294. attributes pcommon.Map,
  295. ts int64,
  296. intVal int64,
  297. ) pmetric.Metric {
  298. metric := pmetric.NewMetric()
  299. metric.SetName(name)
  300. g := metric.SetEmptyGauge()
  301. dp := g.DataPoints().AppendEmpty()
  302. dp.SetIntValue(intVal)
  303. dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Unix(ts, 0)))
  304. attributes.CopyTo(dp.Attributes())
  305. return metric
  306. }