@@ -57,10 +57,11 @@ const (
57
57
58
58
// metricID represents the minimum attributes that uniquely identifies a metric in our tests.
59
59
type metricID struct {
60
- service string
61
- name string
62
- kind string
63
- statusCode string
60
+ service string
61
+ name string
62
+ kind string
63
+ statusCode string
64
+ otelStatusCode string
64
65
}
65
66
66
67
type metricDataPoint interface {
@@ -133,6 +134,66 @@ func verifyBadMetricsOkay(testing.TB, pmetric.Metrics) bool {
133
134
return true // Validating no exception
134
135
}
135
136
137
+ func verifyOtelStatusCode (tb testing.TB , input pmetric.Metrics ) bool {
138
+ require .Equal (tb , 8 , input .DataPointCount (),
139
+ "Should be 4 for each of call count and latency split into three resource scopes defined by: " +
140
+ "service-a: service-a (server kind) -> service-a (client kind), " +
141
+ "service-b: service-b (server kind), and" +
142
+ "service-c: service-c (server kind)" ,
143
+ )
144
+
145
+ require .Equal (tb , 3 , input .ResourceMetrics ().Len ())
146
+
147
+ for i := 0 ; i < input .ResourceMetrics ().Len (); i ++ {
148
+ rm := input .ResourceMetrics ().At (i )
149
+
150
+ var expectedStatusCode string
151
+ val , ok := rm .Resource ().Attributes ().Get (serviceNameKey )
152
+ require .True (tb , ok )
153
+ serviceName := val .AsString ()
154
+ switch serviceName {
155
+ case "service-a" :
156
+ expectedStatusCode = "OK"
157
+ case "service-b" :
158
+ expectedStatusCode = "ERROR"
159
+ case "service-c" :
160
+ expectedStatusCode = ""
161
+ default :
162
+ require .Fail (tb , "Unexpected service name: %s" , serviceName )
163
+ }
164
+
165
+ ilm := rm .ScopeMetrics ()
166
+ require .Equal (tb , 1 , ilm .Len ())
167
+ assert .Equal (tb , "spanmetricsconnector" , ilm .At (0 ).Scope ().Name ())
168
+
169
+ m := ilm .At (0 ).Metrics ()
170
+ require .Equal (tb , 2 , m .Len (), "only sum and histogram metric types generated" )
171
+
172
+ metric := m .At (0 )
173
+ // validate the sum metrics for simplicity
174
+ assert .Equal (tb , pmetric .MetricTypeSum , metric .Type ())
175
+ seenMetricIDs := make (map [metricID ]bool )
176
+
177
+ dataPoints := metric .Sum ().DataPoints ()
178
+ for dpi := 0 ; dpi < dataPoints .Len (); dpi ++ {
179
+ dp := dataPoints .At (dpi )
180
+ statusCode , ok := dp .Attributes ().Get (otelStatusCodeKey )
181
+ if expectedStatusCode == "" {
182
+ require .False (tb , ok )
183
+ } else {
184
+ require .True (tb , ok )
185
+ assert .Equal (tb , expectedStatusCode , statusCode .AsString ())
186
+ }
187
+ verifyMetricLabels (tb , dp , seenMetricIDs )
188
+ }
189
+ for id := range seenMetricIDs {
190
+ assert .Equal (tb , expectedStatusCode , id .otelStatusCode )
191
+ assert .Equal (tb , "" , id .statusCode )
192
+ }
193
+ }
194
+ return true
195
+ }
196
+
136
197
// verifyConsumeMetricsInputDelta expects one accumulation of metrics, and marked as delta
137
198
func verifyConsumeMetricsInputDelta (tb testing.TB , input pmetric.Metrics ) bool {
138
199
return verifyConsumeMetricsInput (tb , input , pmetric .AggregationTemporalityDelta , 1 )
@@ -304,6 +365,8 @@ func verifyMetricLabels(tb testing.TB, dp metricDataPoint, seenMetricIDs map[met
304
365
mID .kind = v .Str ()
305
366
case statusCodeKey :
306
367
mID .statusCode = v .Str ()
368
+ case otelStatusCodeKey :
369
+ mID .otelStatusCode = v .Str ()
307
370
case notInSpanAttrName1 :
308
371
assert .Fail (tb , notInSpanAttrName1 + " should not be in this metric" )
309
372
default :
@@ -374,6 +437,26 @@ func buildSampleTrace() ptrace.Traces {
374
437
return traces
375
438
}
376
439
440
+ // buildTraceWithUnsetStatusCode builds the following trace:
441
+ //
442
+ // service-c/ping (server)
443
+ func appendTraceWithUnsetStatusCode (traces ptrace.Traces ) ptrace.Traces {
444
+ initServiceSpans (
445
+ serviceSpans {
446
+ serviceName : "service-c" ,
447
+ spans : []span {
448
+ {
449
+ name : "/ping" ,
450
+ kind : ptrace .SpanKindServer ,
451
+ statusCode : ptrace .StatusCodeUnset ,
452
+ traceID : [16 ]byte {0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 , 0x19 , 0x1A , 0x1B , 0x1C , 0x1D , 0x1E , 0x1F , 0x20 },
453
+ spanID : [8 ]byte {0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26 , 0x27 , 0x28 },
454
+ },
455
+ },
456
+ }, traces .ResourceSpans ().AppendEmpty ())
457
+ return traces
458
+ }
459
+
377
460
func initServiceSpans (serviceSpans serviceSpans , spans ptrace.ResourceSpans ) {
378
461
if serviceSpans .serviceName != "" {
379
462
spans .Resource ().Attributes ().PutStr (string (conventions .ServiceNameKey ), serviceSpans .serviceName )
@@ -774,6 +857,7 @@ func TestConsumeTraces(t *testing.T) {
774
857
exemplarConfig func () ExemplarsConfig
775
858
verifier func (tb testing.TB , input pmetric.Metrics ) bool
776
859
traces []ptrace.Traces
860
+ statusCodeFeatureGate bool
777
861
}{
778
862
// disabling histogram
779
863
{
@@ -828,6 +912,16 @@ func TestConsumeTraces(t *testing.T) {
828
912
verifier : verifyBadMetricsOkay ,
829
913
traces : []ptrace.Traces {buildBadSampleTrace ()},
830
914
},
915
+ {
916
+ // Test that the status code is set properly
917
+ name : "Test using new status code attribute" ,
918
+ aggregationTemporality : delta ,
919
+ histogramConfig : exponentialHistogramsConfig ,
920
+ exemplarConfig : disabledExemplarsConfig ,
921
+ verifier : verifyOtelStatusCode ,
922
+ traces : []ptrace.Traces {appendTraceWithUnsetStatusCode (buildSampleTrace ())},
923
+ statusCodeFeatureGate : true ,
924
+ },
831
925
832
926
// explicit buckets histogram
833
927
{
@@ -894,6 +988,12 @@ func TestConsumeTraces(t *testing.T) {
894
988
require .NoError (t , err )
895
989
// Override the default no-op consumer with metrics sink for testing.
896
990
p .metricsConsumer = mcon
991
+ if tc .statusCodeFeatureGate {
992
+ require .NoError (t , featuregate .GlobalRegistry ().Set (useOtelStatusCodeAttribute .ID (), true ))
993
+ defer func () {
994
+ require .NoError (t , featuregate .GlobalRegistry ().Set (useOtelStatusCodeAttribute .ID (), false ))
995
+ }()
996
+ }
897
997
898
998
ctx := metadata .NewIncomingContext (t .Context (), nil )
899
999
err = p .Start (ctx , componenttest .NewNopHost ())
0 commit comments