Skip to content

Commit 4dbba92

Browse files
authored
serialize each datapoint into separate line (#2618)
* split each datapoint into separate point * fix unit tests * change data in unit tests
1 parent 8c985f8 commit 4dbba92

File tree

3 files changed

+67
-47
lines changed

3 files changed

+67
-47
lines changed

exporter/dynatraceexporter/metrics_exporter.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ func (e *exporter) serializeMetrics(md pdata.Metrics) ([]string, int) {
8989

9090
resourceMetrics := md.ResourceMetrics()
9191

92+
e.logger.Debug(fmt.Sprintf("res metric len: %d, e.cfg.Tags: %v\n", resourceMetrics.Len(), e.cfg.Tags))
93+
9294
for i := 0; i < resourceMetrics.Len(); i++ {
9395
resourceMetric := resourceMetrics.At(i)
9496
libraryMetrics := resourceMetric.InstrumentationLibraryMetrics()
@@ -104,24 +106,25 @@ func (e *exporter) serializeMetrics(md pdata.Metrics) ([]string, int) {
104106
continue
105107
}
106108

107-
e.logger.Debug("Exporting type " + metric.DataType().String())
108-
109+
var l []string
109110
switch metric.DataType() {
110111
case pdata.MetricDataTypeNone:
111112
continue
112113
case pdata.MetricDataTypeIntGauge:
113-
lines = append(lines, serialization.SerializeIntDataPoints(name, metric.IntGauge().DataPoints(), e.cfg.Tags))
114+
l = serialization.SerializeIntDataPoints(name, metric.IntGauge().DataPoints(), e.cfg.Tags)
114115
case pdata.MetricDataTypeDoubleGauge:
115-
lines = append(lines, serialization.SerializeDoubleDataPoints(name, metric.DoubleGauge().DataPoints(), e.cfg.Tags))
116+
l = serialization.SerializeDoubleDataPoints(name, metric.DoubleGauge().DataPoints(), e.cfg.Tags)
116117
case pdata.MetricDataTypeIntSum:
117-
lines = append(lines, serialization.SerializeIntDataPoints(name, metric.IntSum().DataPoints(), e.cfg.Tags))
118+
l = serialization.SerializeIntDataPoints(name, metric.IntSum().DataPoints(), e.cfg.Tags)
118119
case pdata.MetricDataTypeDoubleSum:
119-
lines = append(lines, serialization.SerializeDoubleDataPoints(name, metric.DoubleSum().DataPoints(), e.cfg.Tags))
120+
l = serialization.SerializeDoubleDataPoints(name, metric.DoubleSum().DataPoints(), e.cfg.Tags)
120121
case pdata.MetricDataTypeIntHistogram:
121-
lines = append(lines, serialization.SerializeIntHistogramMetrics(name, metric.IntHistogram().DataPoints(), e.cfg.Tags))
122+
l = serialization.SerializeIntHistogramMetrics(name, metric.IntHistogram().DataPoints(), e.cfg.Tags)
122123
case pdata.MetricDataTypeDoubleHistogram:
123-
lines = append(lines, serialization.SerializeDoubleHistogramMetrics(name, metric.DoubleHistogram().DataPoints(), e.cfg.Tags))
124+
l = serialization.SerializeDoubleHistogramMetrics(name, metric.DoubleHistogram().DataPoints(), e.cfg.Tags)
124125
}
126+
lines = append(lines, l...)
127+
e.logger.Debug(fmt.Sprintf("Exporting type %s, Name: %s, len: %d ", metric.DataType().String(), name, len(l)))
125128
}
126129
}
127130
}
@@ -163,7 +166,8 @@ func (e *exporter) send(ctx context.Context, lines []string) (int, error) {
163166
// An error indicates all lines were dropped regardless of the returned number.
164167
func (e *exporter) sendBatch(ctx context.Context, lines []string) (int, error) {
165168
message := strings.Join(lines, "\n")
166-
e.logger.Debug("Sending lines to Dynatrace\n" + message)
169+
e.logger.Debug(fmt.Sprintf("Sending lines to Dynatrace: %d", len(lines)))
170+
167171
req, err := http.NewRequestWithContext(ctx, "POST", e.cfg.Endpoint, bytes.NewBufferString(message))
168172
if err != nil {
169173
return 0, consumererror.Permanent(err)

exporter/dynatraceexporter/serialization/serialization.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,28 @@ const (
3232
)
3333

3434
// SerializeIntDataPoints serializes a slice of integer datapoints to a Dynatrace gauge.
35-
func SerializeIntDataPoints(name string, data pdata.IntDataPointSlice, tags []string) string {
35+
func SerializeIntDataPoints(name string, data pdata.IntDataPointSlice, tags []string) []string {
3636
// {name} {value} {timestamp}
37-
output := ""
37+
output := []string{}
38+
3839
for i := 0; i < data.Len(); i++ {
3940
p := data.At(i)
4041
tagline := serializeTags(p.LabelsMap(), tags)
4142
valueLine := strconv.FormatInt(p.Value(), 10)
4243

43-
output += serializeLine(name, tagline, valueLine, p.Timestamp())
44+
output = append(output, serializeLine(name, tagline, valueLine, p.Timestamp()))
4445
}
4546

4647
return output
4748
}
4849

4950
// SerializeDoubleDataPoints serializes a slice of double datapoints to a Dynatrace gauge.
50-
func SerializeDoubleDataPoints(name string, data pdata.DoubleDataPointSlice, tags []string) string {
51+
func SerializeDoubleDataPoints(name string, data pdata.DoubleDataPointSlice, tags []string) []string {
5152
// {name} {value} {timestamp}
52-
output := ""
53+
output := []string{}
5354
for i := 0; i < data.Len(); i++ {
5455
p := data.At(i)
55-
output += serializeLine(name, serializeTags(p.LabelsMap(), tags), serializeFloat64(p.Value()), p.Timestamp())
56+
output = append(output, serializeLine(name, serializeTags(p.LabelsMap(), tags), serializeFloat64(p.Value()), p.Timestamp()))
5657
}
5758

5859
return output
@@ -61,20 +62,20 @@ func SerializeDoubleDataPoints(name string, data pdata.DoubleDataPointSlice, tag
6162
// SerializeDoubleHistogramMetrics serializes a slice of double histogram datapoints to a Dynatrace gauge.
6263
//
6364
// IMPORTANT: Min and max are required by Dynatrace but not provided by histogram so they are assumed to be the average.
64-
func SerializeDoubleHistogramMetrics(name string, data pdata.DoubleHistogramDataPointSlice, tags []string) string {
65+
func SerializeDoubleHistogramMetrics(name string, data pdata.DoubleHistogramDataPointSlice, tags []string) []string {
6566
// {name} gauge,min=9.75,max=9.75,sum=19.5,count=2 {timestamp_unix_ms}
66-
output := ""
67+
output := []string{}
6768
for i := 0; i < data.Len(); i++ {
6869
p := data.At(i)
6970
tagline := serializeTags(p.LabelsMap(), tags)
7071
if p.Count() == 0 {
71-
return ""
72+
return []string{}
7273
}
7374
avg := p.Sum() / float64(p.Count())
7475

7576
valueLine := fmt.Sprintf("gauge,min=%[1]s,max=%[1]s,sum=%s,count=%d", serializeFloat64(avg), serializeFloat64(p.Sum()), p.Count())
7677

77-
output += serializeLine(name, tagline, valueLine, p.Timestamp())
78+
output = append(output, serializeLine(name, tagline, valueLine, p.Timestamp()))
7879
}
7980

8081
return output
@@ -83,23 +84,23 @@ func SerializeDoubleHistogramMetrics(name string, data pdata.DoubleHistogramData
8384
// SerializeIntHistogramMetrics serializes a slice of integer histogram datapoints to a Dynatrace gauge.
8485
//
8586
// IMPORTANT: Min and max are required by Dynatrace but not provided by histogram so they are assumed to be the average.
86-
func SerializeIntHistogramMetrics(name string, data pdata.IntHistogramDataPointSlice, tags []string) string {
87+
func SerializeIntHistogramMetrics(name string, data pdata.IntHistogramDataPointSlice, tags []string) []string {
8788
// {name} gauge,min=9.5,max=9.5,sum=19,count=2 {timestamp_unix_ms}
88-
output := ""
89+
output := []string{}
8990
for i := 0; i < data.Len(); i++ {
9091
p := data.At(i)
9192
tagline := serializeTags(p.LabelsMap(), tags)
9293
count := p.Count()
9394

9495
if count == 0 {
95-
return ""
96+
return []string{}
9697
}
9798

9899
avg := float64(p.Sum()) / float64(count)
99100

100101
valueLine := fmt.Sprintf("gauge,min=%[1]s,max=%[1]s,sum=%d,count=%d", serializeFloat64(avg), p.Sum(), count)
101102

102-
output += serializeLine(name, tagline, valueLine, p.Timestamp())
103+
output = append(output, serializeLine(name, tagline, valueLine, p.Timestamp()))
103104
}
104105

105106
return output

exporter/dynatraceexporter/serialization/serialization_test.go

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ func TestSerializeIntDataPoints(t *testing.T) {
2828
}
2929

3030
intSlice := pdata.NewIntDataPointSlice()
31-
intSlice.Resize(1)
31+
intSlice.Resize(2)
3232
intPoint := intSlice.At(0)
3333
intPoint.SetValue(13)
3434
intPoint.SetTimestamp(pdata.Timestamp(100_000_000))
35+
intPoint1 := intSlice.At(1)
36+
intPoint1.SetValue(14)
37+
intPoint1.SetTimestamp(pdata.Timestamp(101_000_000))
3538

3639
labelIntSlice := pdata.NewIntDataPointSlice()
3740
labelIntSlice.Resize(1)
@@ -50,7 +53,7 @@ func TestSerializeIntDataPoints(t *testing.T) {
5053
tests := []struct {
5154
name string
5255
args args
53-
want string
56+
want []string
5457
}{
5558
{
5659
name: "Serialize integer data points",
@@ -59,7 +62,7 @@ func TestSerializeIntDataPoints(t *testing.T) {
5962
data: intSlice,
6063
tags: []string{},
6164
},
62-
want: "my_int_gauge 13 100",
65+
want: []string{"my_int_gauge 13 100", "my_int_gauge 14 101"},
6366
},
6467
{
6568
name: "Serialize integer data points with tags",
@@ -68,7 +71,7 @@ func TestSerializeIntDataPoints(t *testing.T) {
6871
data: intSlice,
6972
tags: []string{"test_key=testval"},
7073
},
71-
want: "my_int_gauge_with_tags,test_key=testval 13 100",
74+
want: []string{"my_int_gauge_with_tags,test_key=testval 13 100", "my_int_gauge_with_tags,test_key=testval 14 101"},
7275
},
7376
{
7477
name: "Serialize integer data points with labels",
@@ -77,7 +80,7 @@ func TestSerializeIntDataPoints(t *testing.T) {
7780
data: labelIntSlice,
7881
tags: []string{},
7982
},
80-
want: "my_int_gauge_with_labels,labelkey=\"labelValue\" 13 100",
83+
want: []string{"my_int_gauge_with_labels,labelkey=\"labelValue\" 13 100"},
8184
},
8285
{
8386
name: "Serialize integer data points with empty label",
@@ -86,12 +89,12 @@ func TestSerializeIntDataPoints(t *testing.T) {
8689
data: emptyLabelIntSlice,
8790
tags: []string{},
8891
},
89-
want: "my_int_gauge_with_empty_labels,emptylabelkey=\"\" 13 100",
92+
want: []string{"my_int_gauge_with_empty_labels,emptylabelkey=\"\" 13 100"},
9093
},
9194
}
9295
for _, tt := range tests {
9396
t.Run(tt.name, func(t *testing.T) {
94-
if got := SerializeIntDataPoints(tt.args.name, tt.args.data, tt.args.tags); got != tt.want {
97+
if got := SerializeIntDataPoints(tt.args.name, tt.args.data, tt.args.tags); !equal(got, tt.want) {
9598
t.Errorf("SerializeIntDataPoints() = %#v, want %#v", got, tt.want)
9699
}
97100
})
@@ -120,7 +123,7 @@ func TestSerializeDoubleDataPoints(t *testing.T) {
120123
tests := []struct {
121124
name string
122125
args args
123-
want string
126+
want []string
124127
}{
125128
{
126129
name: "Serialize double data points",
@@ -129,7 +132,7 @@ func TestSerializeDoubleDataPoints(t *testing.T) {
129132
data: doubleSlice,
130133
tags: []string{},
131134
},
132-
want: "my_double_gauge 13.1 100",
135+
want: []string{"my_double_gauge 13.1 100"},
133136
},
134137
{
135138
name: "Serialize double data points with tags",
@@ -138,7 +141,7 @@ func TestSerializeDoubleDataPoints(t *testing.T) {
138141
data: doubleSlice,
139142
tags: []string{"test_key=testval"},
140143
},
141-
want: "my_double_gauge_with_tags,test_key=testval 13.1 100",
144+
want: []string{"my_double_gauge_with_tags,test_key=testval 13.1 100"},
142145
},
143146
{
144147
name: "Serialize double data points with labels",
@@ -147,12 +150,12 @@ func TestSerializeDoubleDataPoints(t *testing.T) {
147150
data: labelDoubleSlice,
148151
tags: []string{},
149152
},
150-
want: "my_double_gauge_with_labels,labelkey=\"labelValue\" 13.1 100",
153+
want: []string{"my_double_gauge_with_labels,labelkey=\"labelValue\" 13.1 100"},
151154
},
152155
}
153156
for _, tt := range tests {
154157
t.Run(tt.name, func(t *testing.T) {
155-
if got := SerializeDoubleDataPoints(tt.args.name, tt.args.data, tt.args.tags); got != tt.want {
158+
if got := SerializeDoubleDataPoints(tt.args.name, tt.args.data, tt.args.tags); !equal(got, tt.want) {
156159
t.Errorf("SerializeDoubleDataPoints() = %v, want %v", got, tt.want)
157160
}
158161
})
@@ -190,7 +193,7 @@ func TestSerializeDoubleHistogramMetrics(t *testing.T) {
190193
tests := []struct {
191194
name string
192195
args args
193-
want string
196+
want []string
194197
}{
195198
{
196199
name: "Serialize double histogram data points",
@@ -199,7 +202,7 @@ func TestSerializeDoubleHistogramMetrics(t *testing.T) {
199202
data: doubleHistSlice,
200203
tags: []string{},
201204
},
202-
want: "my_double_hist gauge,min=10.1,max=10.1,sum=101,count=10 100",
205+
want: []string{"my_double_hist gauge,min=10.1,max=10.1,sum=101,count=10 100"},
203206
},
204207
{
205208
name: "Serialize double histogram data points with tags",
@@ -208,7 +211,7 @@ func TestSerializeDoubleHistogramMetrics(t *testing.T) {
208211
data: doubleHistSlice,
209212
tags: []string{"test_key=testval"},
210213
},
211-
want: "my_double_hist_with_tags,test_key=testval gauge,min=10.1,max=10.1,sum=101,count=10 100",
214+
want: []string{"my_double_hist_with_tags,test_key=testval gauge,min=10.1,max=10.1,sum=101,count=10 100"},
212215
},
213216
{
214217
name: "Serialize double histogram data points with labels",
@@ -217,7 +220,7 @@ func TestSerializeDoubleHistogramMetrics(t *testing.T) {
217220
data: labelDoubleHistSlice,
218221
tags: []string{},
219222
},
220-
want: "my_double_hist_with_labels,labelkey=\"labelValue\" gauge,min=10.1,max=10.1,sum=101,count=10 100",
223+
want: []string{"my_double_hist_with_labels,labelkey=\"labelValue\" gauge,min=10.1,max=10.1,sum=101,count=10 100"},
221224
},
222225
{
223226
name: "Serialize zero double histogram",
@@ -226,12 +229,12 @@ func TestSerializeDoubleHistogramMetrics(t *testing.T) {
226229
data: zeroDoubleHistogramSlice,
227230
tags: []string{},
228231
},
229-
want: "",
232+
want: []string{},
230233
},
231234
}
232235
for _, tt := range tests {
233236
t.Run(tt.name, func(t *testing.T) {
234-
if got := SerializeDoubleHistogramMetrics(tt.args.name, tt.args.data, tt.args.tags); got != tt.want {
237+
if got := SerializeDoubleHistogramMetrics(tt.args.name, tt.args.data, tt.args.tags); !equal(got, tt.want) {
235238
t.Errorf("SerializeDoubleHistogramMetrics() = %v, want %v", got, tt.want)
236239
}
237240
})
@@ -269,7 +272,7 @@ func TestSerializeIntHistogramMetrics(t *testing.T) {
269272
tests := []struct {
270273
name string
271274
args args
272-
want string
275+
want []string
273276
}{
274277
{
275278
name: "Serialize integer histogram data points",
@@ -278,7 +281,7 @@ func TestSerializeIntHistogramMetrics(t *testing.T) {
278281
data: intHistSlice,
279282
tags: []string{},
280283
},
281-
want: "my_int_hist gauge,min=11,max=11,sum=110,count=10 100",
284+
want: []string{"my_int_hist gauge,min=11,max=11,sum=110,count=10 100"},
282285
},
283286
{
284287
name: "Serialize integer histogram data points with tags",
@@ -287,7 +290,7 @@ func TestSerializeIntHistogramMetrics(t *testing.T) {
287290
data: intHistSlice,
288291
tags: []string{"test_key=testval"},
289292
},
290-
want: "my_int_hist_with_tags,test_key=testval gauge,min=11,max=11,sum=110,count=10 100",
293+
want: []string{"my_int_hist_with_tags,test_key=testval gauge,min=11,max=11,sum=110,count=10 100"},
291294
},
292295
{
293296
name: "Serialize integer histogram data points with labels",
@@ -296,7 +299,7 @@ func TestSerializeIntHistogramMetrics(t *testing.T) {
296299
data: labelIntHistSlice,
297300
tags: []string{},
298301
},
299-
want: "my_int_hist_with_labels,labelkey=\"labelValue\" gauge,min=11,max=11,sum=110,count=10 100",
302+
want: []string{"my_int_hist_with_labels,labelkey=\"labelValue\" gauge,min=11,max=11,sum=110,count=10 100"},
300303
},
301304
{
302305
name: "Serialize zero integer histogram",
@@ -305,12 +308,12 @@ func TestSerializeIntHistogramMetrics(t *testing.T) {
305308
data: zeroIntHistogramSlice,
306309
tags: []string{},
307310
},
308-
want: "",
311+
want: []string{},
309312
},
310313
}
311314
for _, tt := range tests {
312315
t.Run(tt.name, func(t *testing.T) {
313-
if got := SerializeIntHistogramMetrics(tt.args.name, tt.args.data, tt.args.tags); got != tt.want {
316+
if got := SerializeIntHistogramMetrics(tt.args.name, tt.args.data, tt.args.tags); !equal(got, tt.want) {
314317
t.Errorf("SerializeIntHistogramMetrics() = %v, want %v", got, tt.want)
315318
}
316319
})
@@ -506,3 +509,15 @@ func Test_serializeFloat64(t *testing.T) {
506509
})
507510
}
508511
}
512+
513+
func equal(a, b []string) bool {
514+
if len(a) == len(b) {
515+
for i := range a {
516+
if a[i] != b[i] {
517+
return false
518+
}
519+
}
520+
return true
521+
}
522+
return false
523+
}

0 commit comments

Comments
 (0)