Skip to content

Commit b09cb40

Browse files
authored
test(instrumentation-express): update to use correct span kind enum; also fix test flakiness (#2421)
This is a follow-up on #2408 (comment) to update one more usage of SpanKind.* to testUtils.OtlpSpanKind.*. While testing this locally I also noticed that the instr-express tests using runTestFixture are flaky. The issue is that TestCollector#sortedSpans can get the span ordering wrong when spans start in the same millisecond (the resolution of span.startTimeUnixNano). This happens with Express middleware spans on a fast machine. I've updated sortedSpans to fallback to using span.parentSpanId to attempt to get more reliable sorting.
1 parent bc69fff commit b09cb40

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

packages/opentelemetry-test-utils/src/test-fixtures.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,38 @@ export class TestCollector {
110110
return this._http.close();
111111
}
112112

113-
// Return the spans sorted by start time for testing convenience.
113+
/**
114+
* Return the spans sorted by which started first, for testing convenience.
115+
*
116+
* Note: This sorting is a *best effort*. `span.startTimeUnixNano` has
117+
* millisecond accuracy, so if multiple spans start in the same millisecond
118+
* then this cannot know the start ordering. If `startTimeUnixNano` are the
119+
* same, this attempts to get the correct ordering using `parentSpanId` -- a
120+
* parent span starts before any of its direct children. This isn't perfect.
121+
*/
114122
get sortedSpans(): Array<TestSpan> {
115123
return this.spans.slice().sort((a, b) => {
116124
assert(typeof a.startTimeUnixNano === 'string');
117125
assert(typeof b.startTimeUnixNano === 'string');
118126
const aStartInt = BigInt(a.startTimeUnixNano);
119127
const bStartInt = BigInt(b.startTimeUnixNano);
120-
return aStartInt < bStartInt ? -1 : aStartInt > bStartInt ? 1 : 0;
128+
if (aStartInt < bStartInt) {
129+
return -1;
130+
} else if (aStartInt > bStartInt) {
131+
return 1;
132+
} else {
133+
// Same startTimeUnixNano, which has millisecond accuracy. This is
134+
// common for Express middleware spans on a fast enough dev machine.
135+
// Attempt to use spanId/parentSpanId to decide on span ordering.
136+
if (a.traceId === b.traceId) {
137+
if (a.spanId === b.parentSpanId) {
138+
return -1;
139+
} else if (a.parentSpanId === b.spanId) {
140+
return 1;
141+
}
142+
}
143+
return 0;
144+
}
121145
});
122146
}
123147

plugins/node/opentelemetry-instrumentation-express/test/express.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { SpanStatusCode, context, SpanKind, trace } from '@opentelemetry/api';
17+
import { SpanStatusCode, context, trace } from '@opentelemetry/api';
1818
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
1919
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
2020
import {
@@ -675,7 +675,7 @@ describe('ExpressInstrumentation', () => {
675675
spans[5].name,
676676
'request handler - /\\/test\\/regex/'
677677
);
678-
assert.strictEqual(spans[5].kind, SpanKind.SERVER);
678+
assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL);
679679
assert.strictEqual(spans[5].parentSpanId, spans[1].spanId);
680680
},
681681
});

0 commit comments

Comments
 (0)