@zendesk/retrace
Version:
define and capture Product Operation Traces along with computed metrics with an optional friendly React beacon API
842 lines • 39.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const convertToRum_1 = require("./convertToRum");
const matchSpan_1 = require("./matchSpan");
const recordingComputeUtils_1 = require("./recordingComputeUtils");
const createMockFactory_1 = require("./testUtility/createMockFactory");
const baseDefinitionFixture = {
name: 'test-trace',
relationSchemaName: 'global',
relationSchema: { global: {} },
requiredSpans: [() => true],
computedSpanDefinitions: {},
computedValueDefinitions: {},
variants: {
origin: { timeout: 45_000 },
},
};
(0, vitest_1.describe)('recordingComputeUtils', () => {
(0, vitest_1.describe)('error status propagation', () => {
(0, vitest_1.it)('should mark trace as error if any non-suppressed span has error status', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: baseDefinitionFixture,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
status: 'error',
name: 'error-span',
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok', name: 'ok-span' }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
lastRelevantSpanAndAnnotation: undefined,
transitionToState: 'complete',
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.status).toBe('error');
(0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull();
(0, vitest_1.expect)(recording.additionalDurations.completeTillInteractive).toBeNull();
(0, vitest_1.expect)(recording.additionalDurations.startTillRequirementsMet).toBeNull();
});
(0, vitest_1.it)('should not mark trace as error if all error spans are suppressed', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: {
...baseDefinitionFixture,
suppressErrorStatusPropagationOnSpans: [
({ span }) => span.name === 'suppressed-error-span',
],
},
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
status: 'error',
name: 'suppressed-error-span',
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok', name: 'ok-span' }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
lastRelevantSpanAndAnnotation: undefined,
transitionToState: 'complete',
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.status).toBe('ok');
(0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull();
});
(0, vitest_1.it)('should mark trace as error if any error span is not suppressed', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: {
...baseDefinitionFixture,
suppressErrorStatusPropagationOnSpans: [
({ span }) => span.name === 'suppressed-error-span',
],
},
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
status: 'error',
name: 'suppressed-error-span',
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
status: 'error',
name: 'non-suppressed-error-span',
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'ok', name: 'ok-span' }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
lastRelevantSpanAndAnnotation: undefined,
transitionToState: 'complete',
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.status).toBe('error');
(0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull();
});
(0, vitest_1.it)('should prioritize interrupted status over error status', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: baseDefinitionFixture,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
status: 'error',
name: 'error-span',
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
interruptionReason: 'timeout',
transitionToState: 'interrupted',
lastRelevantSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.status).toBe('interrupted');
(0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull();
});
});
(0, vitest_1.describe)('getComputedSpans', () => {
const baseDefinition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: ({ span }) => span.name === 'start-span',
endSpan: ({ span }) => span.name === 'end-span',
},
},
};
(0, vitest_1.it)('should compute duration and startOffset correctly', () => {
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition: baseDefinition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'start-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 150, // (200 + 50) - 100
startOffset: 100,
});
});
(0, vitest_1.it)('should handle operation-start and operation-end special matchers', () => {
const definition = {
...baseDefinition,
computedSpanDefinitions: {
'operation-span': {
startSpan: 'operation-start',
endSpan: 'operation-end',
},
},
};
const markedCompleteSpan = (0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'end-span',
});
markedCompleteSpan.annotation.markedComplete = true;
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
markedCompleteSpan,
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, { completeSpanAndAnnotation: markedCompleteSpan });
(0, vitest_1.expect)(result['operation-span']).toBeDefined();
});
(0, vitest_1.describe)('matchingIndex', () => {
(0, vitest_1.it)('should select the correct start span using a positive matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({
name: 'start-span',
matchingIndex: 1, // starts at 0th index
}),
endSpan: (0, matchSpan_1.fromDefinition)({ name: 'end-span' }),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { name: 'start-span' }), // matching start span
(0, createMockFactory_1.createMockSpanAndAnnotation)(400, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(500, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 250, // (500 + 50) - 300
startOffset: 300, // should use the second start-span
});
});
(0, vitest_1.it)('should select the correct start span using a negative matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({
name: 'start-span',
matchingIndex: -3,
}),
endSpan: (0, matchSpan_1.fromDefinition)({ name: 'end-span' }),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }), // starting span
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(500, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 450, // (500 + 50) - 100
startOffset: 100,
});
});
(0, vitest_1.it)('should select the correct end span using a positive matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({ name: 'start-span' }),
endSpan: (0, matchSpan_1.fromDefinition)({
name: 'end-span',
matchingIndex: 2,
}),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(150, { name: 'span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(400, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(600, {
// matching span
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(700, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 550, // (600 + 50) - 100
startOffset: 100,
});
});
(0, vitest_1.it)('should select the correct end span using a negative matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({ name: 'start-span' }),
endSpan: (0, matchSpan_1.fromDefinition)({
name: 'end-span',
matchingIndex: -1,
}),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(400, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(600, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(700, {
// matching span
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 650, // (700 + 50) - 100
startOffset: 100,
});
});
(0, vitest_1.it)('should not return any computed spans using a invalid matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({ name: 'start-span' }),
endSpan: (0, matchSpan_1.fromDefinition)({
name: 'end-span',
matchingIndex: -100,
}),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(400, {
// matching span
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(600, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(700, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result).toEqual({});
});
(0, vitest_1.it)('should work with span definition objects containing matchingIndex', () => {
const definition = {
...baseDefinitionFixture,
computedSpanDefinitions: {
'test-computed-span': {
startSpan: (0, matchSpan_1.fromDefinition)({
name: 'start-span',
matchingIndex: 1,
}),
endSpan: (0, matchSpan_1.fromDefinition)({ name: 'end-span', matchingIndex: -1 }),
},
},
};
const result = (0, recordingComputeUtils_1.getComputedSpans)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { name: 'start-span' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(400, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(500, {
name: 'end-span',
duration: 50,
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(600, {
name: 'end-span',
duration: 50,
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['test-computed-span']).toEqual({
duration: 450, // (600 + 50) - 200
startOffset: 200, // should use second start-span
});
});
});
});
(0, vitest_1.describe)('getComputedValues', () => {
const baseDefinition = {
...baseDefinitionFixture,
computedValueDefinitions: {
'error-count': {
matches: [({ span }) => span.status === 'error'],
computeValueFromMatches: (matches) => matches.length,
},
},
};
(0, vitest_1.it)('should compute values based on matching spans', () => {
const result = (0, recordingComputeUtils_1.getComputedValues)({
definition: baseDefinition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'error' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'ok' }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['error-count']).toBe(2);
});
(0, vitest_1.it)('should handle multiple matches in computeValueFromMatches', () => {
const definition = {
...baseDefinition,
computedValueDefinitions: {
'status-counts': {
matches: [
({ span }) => span.status === 'error',
({ span }) => span.status === 'ok',
],
computeValueFromMatches: (errors, oks) => errors.length + oks.length,
},
},
};
const result = (0, recordingComputeUtils_1.getComputedValues)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok' }),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'error' }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
});
(0, vitest_1.expect)(result['status-counts']).toEqual(3);
});
});
(0, vitest_1.describe)('getSpanSummaryAttributes', () => {
(0, vitest_1.it)('should merge attributes from spans with the same name', () => {
const result = (0, convertToRum_1.getSpanSummaryAttributes)([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'test-span',
attributes: { first: true },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'test-span',
attributes: { second: true },
}),
]);
(0, vitest_1.expect)(result['test-span']).toEqual({
first: true,
second: true,
});
});
});
(0, vitest_1.describe)('computedRenderBeaconSpans', () => {
(0, vitest_1.it)('should compute render beacon metrics correctly', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: baseDefinitionFixture,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'test-component',
type: 'component-render',
relatedTo: {},
duration: 50,
isIdle: true,
renderCount: 1,
renderedOutput: 'loading',
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'test-component',
type: 'component-render',
relatedTo: {},
duration: 50,
isIdle: true,
renderCount: 2,
renderedOutput: 'content',
}, { occurrence: 2 }),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.computedRenderBeaconSpans['test-component']).toEqual({
startOffset: 100,
firstRenderTillContent: 150,
firstRenderTillLoading: 50,
firstRenderTillData: 100,
renderCount: 2,
sumOfRenderDurations: 100,
});
});
});
(0, vitest_1.describe)('variant property', () => {
(0, vitest_1.it)('should include the variant in the recording', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: baseDefinitionFixture,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
status: 'ok',
name: 'test-span',
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
// Verify the variant is included in the recording
(0, vitest_1.expect)(recording.variant).toBe('origin');
});
});
(0, vitest_1.describe)('promoteSpanAttributesForTrace and attribute promotion', () => {
const promotedAttributesTraceDefinition = {
...baseDefinitionFixture,
promoteSpanAttributes: [
{
span: { name: 'foo-span' },
attributes: ['foo', 'bar'],
},
{
span: { name: 'baz-span' },
attributes: ['baz'],
},
],
};
(0, vitest_1.it)('should promote specified attributes from last matching spans to trace', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: promotedAttributesTraceDefinition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'foo-span',
attributes: { foo: 1, bar: 2, unused: 42 },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'foo-span',
attributes: { foo: 7, bar: 8 },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, {
name: 'baz-span',
attributes: { baz: 'hello' },
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
// Should select last foo-span (timestamp 200) for foo/bar, and baz-span for baz
(0, vitest_1.expect)(recording.attributes.foo).toBe(7);
(0, vitest_1.expect)(recording.attributes.bar).toBe(8);
(0, vitest_1.expect)(recording.attributes.baz).toBe('hello');
(0, vitest_1.expect)('unused' in recording.attributes).toBe(false);
});
(0, vitest_1.it)('should promote specified attributes from last matching spans when there is an attribute name collision to trace', () => {
const promotedAttributesTraceDefinitionWithOverrideAttributeNames = {
...baseDefinitionFixture,
promoteSpanAttributes: [
{
span: { name: 'foo-span' },
attributes: ['foo', 'bar'],
},
{
span: { name: 'baz-span' },
attributes: ['foo', 'bar'],
},
],
};
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: promotedAttributesTraceDefinitionWithOverrideAttributeNames,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'foo-span',
attributes: { foo: 7, bar: 8 },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(300, {
name: 'baz-span',
// should replace the trace attributes from 'foo-span'
attributes: { foo: 'hello', bar: 'world' },
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
// Should select attributes from baz-span (timestamp 300)
(0, vitest_1.expect)(recording.attributes.foo).toBe('hello');
(0, vitest_1.expect)(recording.attributes.bar).toBe('world');
(0, vitest_1.expect)('unused' in recording.attributes).toBe(false);
});
(0, vitest_1.it)('should not set unset promoted attributes if not found', () => {
const partialAttrDefinition = {
...baseDefinitionFixture,
promoteSpanAttributes: [
{
span: { name: 'foo-span' },
attributes: ['foo', 'bar'],
},
{
span: { name: 'no-match' },
attributes: ['baz', 'shouldNotBeSet'],
},
],
};
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: partialAttrDefinition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(111, {
name: 'foo-span',
attributes: { foo: 99 },
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.attributes.foo).toBe(99);
(0, vitest_1.expect)('bar' in recording.attributes).toBe(false);
(0, vitest_1.expect)('baz' in recording.attributes).toBe(false);
(0, vitest_1.expect)('shouldNotBeSet' in recording.attributes).toBe(false);
});
(0, vitest_1.it)('should allow attribute promotion on interruption', () => {
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition: promotedAttributesTraceDefinition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'foo-span',
attributes: { foo: 'z' },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'baz-span',
attributes: { baz: 10 },
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'interrupted',
interruptionReason: 'timeout',
lastRelevantSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.attributes.foo).toBe('z');
(0, vitest_1.expect)(recording.attributes.baz).toBe(10);
});
(0, vitest_1.it)('should allow original trace attributes to take precedence over promoted', () => {
const definition = {
...promotedAttributesTraceDefinition,
};
const recording = (0, recordingComputeUtils_1.createTraceRecording)({
definition,
recordedItems: new Set([
(0, createMockFactory_1.createMockSpanAndAnnotation)(100, {
name: 'foo-span',
attributes: { foo: 'notUsed' },
}),
(0, createMockFactory_1.createMockSpanAndAnnotation)(200, {
name: 'baz-span',
attributes: { baz: 111 },
}),
]),
input: {
id: 'test',
startTime: (0, createMockFactory_1.createTimestamp)(0),
relatedTo: {},
variant: 'origin',
attributes: { foo: 'owned', baz: 'shouldWin' },
},
recordedItemsByLabel: {},
}, {
transitionFromState: 'active',
transitionToState: 'complete',
lastRelevantSpanAndAnnotation: undefined,
completeSpanAndAnnotation: undefined,
cpuIdleSpanAndAnnotation: undefined,
lastRequiredSpanAndAnnotation: undefined,
});
(0, vitest_1.expect)(recording.attributes.foo).toBe('owned');
(0, vitest_1.expect)(recording.attributes.baz).toBe('shouldWin');
});
});
});
//# sourceMappingURL=recordingComputeUtils.test.js.map