Skip to content

Commit 46e50da

Browse files
authored
feat: make the assertion engine return a different error when no spans (#3666)
* feat: make the assertion engine return a different error when no spans * fix tests * add message suggestion from Julianne
1 parent 3e1352f commit 46e50da

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

server/expression/data_store.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ func (ds AttributeDataStore) getFromAlias(name string) (string, error) {
4141
}
4242

4343
func (ds AttributeDataStore) Get(name string) (string, error) {
44+
if !ds.Span.ID.IsValid() {
45+
// It's probably a nil span and we never got a matching selector,
46+
// so instead of returning a resolution error, let's return a non-matching
47+
// span error instead
48+
return "", fmt.Errorf(`there are no matching spans to retrieve the attribute "%s" from. To fix this error, create a selector matching at least one span.`, name)
49+
}
50+
4451
value := ds.Span.Attributes.Get(name)
4552
if value == "" {
4653
return ds.getFromAlias(name)

server/expression/executor_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/kubeshop/tracetest/server/expression"
11+
"github.com/kubeshop/tracetest/server/pkg/id"
1112
"github.com/kubeshop/tracetest/server/traces"
1213
"github.com/kubeshop/tracetest/server/variableset"
1314
"github.com/stretchr/testify/assert"
@@ -103,6 +104,7 @@ func TestAttributeExecution(t *testing.T) {
103104

104105
AttributeDataStore: expression.AttributeDataStore{
105106
Span: traces.Span{
107+
ID: id.NewRandGenerator().SpanID(),
106108
Attributes: traces.NewAttributes(map[string]string{
107109
"my_attribute": "42",
108110
}),
@@ -116,12 +118,39 @@ func TestAttributeExecution(t *testing.T) {
116118

117119
AttributeDataStore: expression.AttributeDataStore{
118120
Span: traces.Span{
121+
ID: id.NewRandGenerator().SpanID(),
119122
Attributes: traces.NewAttributes(map[string]string{
120123
"dapr-app-id": "42",
121124
}),
122125
},
123126
},
124127
},
128+
{
129+
Name: "should_return_error_when_attribute_doesnt_exist",
130+
Query: "attr:dapr-app-id = 43",
131+
ShouldPass: false,
132+
ExpectedErrorMessage: `resolution error: attribute "dapr-app-id" not found`,
133+
134+
AttributeDataStore: expression.AttributeDataStore{
135+
Span: traces.Span{
136+
ID: id.NewRandGenerator().SpanID(),
137+
},
138+
},
139+
},
140+
{
141+
Name: "should_return_error_when_no_matching_spans",
142+
Query: "attr:dapr-app-id = 42",
143+
ShouldPass: false,
144+
ExpectedErrorMessage: `resolution error: there are no matching spans to retrieve the attribute "dapr-app-id" from. To fix this error, create a selector matching at least one span.`,
145+
146+
AttributeDataStore: expression.AttributeDataStore{
147+
Span: traces.Span{
148+
// An span without an id is an invalid span
149+
// this is the value received when we don't have any matching
150+
// spans in the assertion.
151+
},
152+
},
153+
},
125154
}
126155

127156
executeTestCases(t, testCases)
@@ -135,6 +164,7 @@ func TestStringInterpolationExecution(t *testing.T) {
135164
ShouldPass: true,
136165
AttributeDataStore: expression.AttributeDataStore{
137166
Span: traces.Span{
167+
ID: id.NewRandGenerator().SpanID(),
138168
Attributes: traces.NewAttributes(map[string]string{
139169
"text": "this run took 25ms",
140170
}),
@@ -159,6 +189,7 @@ func TestFilterExecution(t *testing.T) {
159189
ShouldPass: true,
160190
AttributeDataStore: expression.AttributeDataStore{
161191
Span: traces.Span{
192+
ID: id.NewRandGenerator().SpanID(),
162193
Attributes: traces.NewAttributes(map[string]string{
163194
"tracetest.response.body": `{"id": 8, "name": "john doe"}`,
164195
}),
@@ -345,6 +376,9 @@ func executeTestCases(t *testing.T, testCases []executorTestCase) {
345376
assert.NoError(t, err, debugMessage)
346377
} else {
347378
assert.Error(t, err, debugMessage)
379+
if testCase.ExpectedErrorMessage != "" {
380+
assert.Equal(t, testCase.ExpectedErrorMessage, err.Error())
381+
}
348382
}
349383
})
350384
}
@@ -376,6 +410,7 @@ func TestResolveStatementAttributeExecution(t *testing.T) {
376410

377411
AttributeDataStore: expression.AttributeDataStore{
378412
Span: traces.Span{
413+
ID: id.NewRandGenerator().SpanID(),
379414
Attributes: traces.NewAttributes(map[string]string{
380415
"my_attribute": "42",
381416
}),
@@ -395,6 +430,7 @@ func TestResolveStatementStringInterpolationExecution(t *testing.T) {
395430
ShouldPass: true,
396431
AttributeDataStore: expression.AttributeDataStore{
397432
Span: traces.Span{
433+
ID: id.NewRandGenerator().SpanID(),
398434
Attributes: traces.NewAttributes(map[string]string{
399435
"text": "this run took 25ms",
400436
}),
@@ -419,6 +455,7 @@ func TestResolveStatementFilterExecution(t *testing.T) {
419455
ShouldPass: true,
420456
AttributeDataStore: expression.AttributeDataStore{
421457
Span: traces.Span{
458+
ID: id.NewRandGenerator().SpanID(),
422459
Attributes: traces.NewAttributes(map[string]string{
423460
"tracetest.response.body": `{"id": 8, "name": "john doe"}`,
424461
}),
@@ -480,6 +517,7 @@ func TestFailureCases(t *testing.T) {
480517

481518
AttributeDataStore: expression.AttributeDataStore{
482519
Span: traces.Span{
520+
ID: id.NewRandGenerator().SpanID(),
483521
Attributes: traces.NewAttributes(map[string]string{
484522
"attr1": "1",
485523
"attr2": "2",

0 commit comments

Comments
 (0)