@@ -14,13 +14,38 @@ import (
14
14
"github.com/golang/snappy"
15
15
promconfig "github.com/prometheus/prometheus/config"
16
16
writev2 "github.com/prometheus/prometheus/prompb/io/prometheus/write/v2"
17
+ "github.com/prometheus/prometheus/storage/remote"
17
18
"github.com/stretchr/testify/assert"
18
19
"go.opentelemetry.io/collector/component/componenttest"
19
20
"go.opentelemetry.io/collector/consumer/consumertest"
21
+ "go.opentelemetry.io/collector/pdata/pmetric"
20
22
"go.opentelemetry.io/collector/receiver/receivertest"
23
+
24
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
21
25
)
22
26
23
- func setupServer (t * testing.T ) {
27
+ var writeV2RequestFixture = & writev2.Request {
28
+ Symbols : []string {"" , "__name__" , "test_metric1" , "job" , "service-x/test" , "instance" , "107cn001" , "d" , "e" , "foo" , "bar" , "f" , "g" , "h" , "i" , "Test gauge for test purposes" , "Maybe op/sec who knows (:" , "Test counter for test purposes" },
29
+ Timeseries : []writev2.TimeSeries {
30
+ {
31
+ Metadata : writev2.Metadata {Type : writev2 .Metadata_METRIC_TYPE_GAUGE },
32
+ LabelsRefs : []uint32 {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }, // Symbolized writeRequestFixture.Timeseries[0].Labels
33
+ Samples : []writev2.Sample {{Value : 1 , Timestamp : 1 }},
34
+ },
35
+ {
36
+ Metadata : writev2.Metadata {Type : writev2 .Metadata_METRIC_TYPE_GAUGE },
37
+ LabelsRefs : []uint32 {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }, // Same series as first. Should use the same resource metrics.
38
+ Samples : []writev2.Sample {{Value : 2 , Timestamp : 2 }},
39
+ },
40
+ {
41
+ Metadata : writev2.Metadata {Type : writev2 .Metadata_METRIC_TYPE_GAUGE },
42
+ LabelsRefs : []uint32 {1 , 2 , 3 , 9 , 5 , 10 , 7 , 8 , 9 , 10 }, // This series has different label values for job and instance.
43
+ Samples : []writev2.Sample {{Value : 2 , Timestamp : 2 }},
44
+ },
45
+ },
46
+ }
47
+
48
+ func setupMetricsReceiver (t * testing.T ) * prometheusRemoteWriteReceiver {
24
49
t .Helper ()
25
50
26
51
factory := NewFactory ()
@@ -30,6 +55,13 @@ func setupServer(t *testing.T) {
30
55
assert .NoError (t , err )
31
56
assert .NotNil (t , prwReceiver , "metrics receiver creation failed" )
32
57
58
+ return prwReceiver .(* prometheusRemoteWriteReceiver )
59
+ }
60
+
61
+ func setupServer (t * testing.T ) {
62
+ t .Helper ()
63
+
64
+ prwReceiver := setupMetricsReceiver (t )
33
65
ctx , cancel := context .WithCancel (context .Background ())
34
66
t .Cleanup (cancel )
35
67
@@ -98,3 +130,89 @@ func TestHandlePRWContentTypeNegotiation(t *testing.T) {
98
130
})
99
131
}
100
132
}
133
+
134
+ func TestTranslateV2 (t * testing.T ) {
135
+ prwReceiver := setupMetricsReceiver (t )
136
+ ctx , cancel := context .WithCancel (context .Background ())
137
+ t .Cleanup (cancel )
138
+
139
+ for _ , tc := range []struct {
140
+ name string
141
+ request * writev2.Request
142
+ expectError string
143
+ expectedMetrics pmetric.Metrics
144
+ expectedStats remote.WriteResponseStats
145
+ }{
146
+ {
147
+ name : "missing metric name" ,
148
+ request : & writev2.Request {
149
+ Symbols : []string {"" , "foo" , "bar" },
150
+ Timeseries : []writev2.TimeSeries {
151
+ {
152
+ LabelsRefs : []uint32 {1 , 2 },
153
+ Samples : []writev2.Sample {{Value : 1 , Timestamp : 1 }},
154
+ },
155
+ },
156
+ },
157
+ expectError : "missing metric name in labels" ,
158
+ },
159
+ {
160
+ name : "duplicate label" ,
161
+ request : & writev2.Request {
162
+ Symbols : []string {"" , "__name__" , "test" },
163
+ Timeseries : []writev2.TimeSeries {
164
+ {
165
+ LabelsRefs : []uint32 {1 , 2 , 1 , 2 },
166
+ Samples : []writev2.Sample {{Value : 1 , Timestamp : 1 }},
167
+ },
168
+ },
169
+ },
170
+ expectError : `duplicate label "__name__" in labels` ,
171
+ },
172
+ {
173
+ name : "valid request" ,
174
+ request : writeV2RequestFixture ,
175
+ expectedMetrics : func () pmetric.Metrics {
176
+ expected := pmetric .NewMetrics ()
177
+ rm1 := expected .ResourceMetrics ().AppendEmpty ()
178
+ rmAttributes1 := rm1 .Resource ().Attributes ()
179
+ rmAttributes1 .PutStr ("service.namespace" , "service-x" )
180
+ rmAttributes1 .PutStr ("service.name" , "test" )
181
+ rmAttributes1 .PutStr ("service.instance.id" , "107cn001" )
182
+ sm1 := rm1 .ScopeMetrics ().AppendEmpty ()
183
+ sm1Attributes := sm1 .Metrics ().AppendEmpty ().SetEmptyGauge ().DataPoints ().AppendEmpty ().Attributes ()
184
+ sm1Attributes .PutStr ("d" , "e" )
185
+ sm1Attributes .PutStr ("foo" , "bar" )
186
+ // Since we don't check "scope_name" and "scope_version", we end up with duplicated scope metrics for repeated series.
187
+ // TODO: Properly handle scope metrics.
188
+ sm2 := rm1 .ScopeMetrics ().AppendEmpty ()
189
+ sm2Attributes := sm2 .Metrics ().AppendEmpty ().SetEmptyGauge ().DataPoints ().AppendEmpty ().Attributes ()
190
+ sm2Attributes .PutStr ("d" , "e" )
191
+ sm2Attributes .PutStr ("foo" , "bar" )
192
+
193
+ rm2 := expected .ResourceMetrics ().AppendEmpty ()
194
+ rmAttributes2 := rm2 .Resource ().Attributes ()
195
+ rmAttributes2 .PutStr ("service.name" , "foo" )
196
+ rmAttributes2 .PutStr ("service.instance.id" , "bar" )
197
+ mAttributes2 := rm2 .ScopeMetrics ().AppendEmpty ().Metrics ().AppendEmpty ().SetEmptyGauge ().DataPoints ().AppendEmpty ().Attributes ()
198
+ mAttributes2 .PutStr ("d" , "e" )
199
+ mAttributes2 .PutStr ("foo" , "bar" )
200
+
201
+ return expected
202
+ }(),
203
+ expectedStats : remote.WriteResponseStats {},
204
+ },
205
+ } {
206
+ t .Run (tc .name , func (t * testing.T ) {
207
+ metrics , stats , err := prwReceiver .translateV2 (ctx , tc .request )
208
+ if tc .expectError != "" {
209
+ assert .ErrorContains (t , err , tc .expectError )
210
+ return
211
+ }
212
+
213
+ assert .NoError (t , err )
214
+ assert .NoError (t , pmetrictest .CompareMetrics (tc .expectedMetrics , metrics ))
215
+ assert .Equal (t , tc .expectedStats , stats )
216
+ })
217
+ }
218
+ }
0 commit comments