[8.x] [APM] Fix entry item in waterfall shouldn't be orphan (#214700) (#214927)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[APM] Fix entry item in waterfall shouldn't be orphan
(#214700)](https://github.com/elastic/kibana/pull/214700)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Sergi
Romeu","email":"sergi.romeu@elastic.co"},"sourceCommit":{"committedDate":"2025-03-18T10:02:30Z","message":"[APM]
Fix entry item in waterfall shouldn't be orphan (#214700)\n\n##
Summary\n\nCloses #213074\n\nThis PR fixes the scenario where the entry
waterfall transaction is\ntreated as an orphan, causing it to reparent
itself and be duplicated\nmultiple
times.\n\n---------\n\nCo-authored-by: Cauê Marcondes
<55978943+cauemarcondes@users.noreply.github.com>","sha":"dbb2aeda4d422a6a03a74f437cd25f515309654a","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","v9.0.0","Team:obs-ux-infra_services","backport:version","v9.1.0","v8.19.0","v9.0.1"],"title":"[APM]
Fix entry item in waterfall shouldn't be
orphan","number":214700,"url":"https://github.com/elastic/kibana/pull/214700","mergeCommit":{"message":"[APM]
Fix entry item in waterfall shouldn't be orphan (#214700)\n\n##
Summary\n\nCloses #213074\n\nThis PR fixes the scenario where the entry
waterfall transaction is\ntreated as an orphan, causing it to reparent
itself and be duplicated\nmultiple
times.\n\n---------\n\nCo-authored-by: Cauê Marcondes
<55978943+cauemarcondes@users.noreply.github.com>","sha":"dbb2aeda4d422a6a03a74f437cd25f515309654a"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214700","number":214700,"mergeCommit":{"message":"[APM]
Fix entry item in waterfall shouldn't be orphan (#214700)\n\n##
Summary\n\nCloses #213074\n\nThis PR fixes the scenario where the entry
waterfall transaction is\ntreated as an orphan, causing it to reparent
itself and be duplicated\nmultiple
times.\n\n---------\n\nCo-authored-by: Cauê Marcondes
<55978943+cauemarcondes@users.noreply.github.com>","sha":"dbb2aeda4d422a6a03a74f437cd25f515309654a"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Sergi Romeu <sergi.romeu@elastic.co>
This commit is contained in:
Kibana Machine 2025-03-18 12:58:24 +01:00 committed by GitHub
parent ca298aa875
commit ccc2c36864
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 6 deletions

View file

@ -749,7 +749,39 @@ describe('waterfall_helpers', () => {
parentId: 'myTransactionId1',
} as IWaterfallSpan,
];
expect(getOrphanItemsIds(traceItems).length).toBe(0);
expect(getOrphanItemsIds(traceItems, traceItems[0].id).length).toBe(0);
});
it('should return missing items count: 0 if first item is orphan', () => {
const traceItems: IWaterfallSpanOrTransaction[] = [
{
doc: {
processor: { event: 'transaction' },
trace: { id: 'myTrace' },
transaction: {
id: 'myTransactionId1',
},
} as WaterfallTransaction,
docType: 'transaction',
id: 'myTransactionId1',
parentId: 'myNotExistingTransactionId0',
} as IWaterfallTransaction,
{
doc: {
processor: { event: 'span' },
span: {
id: 'myOrphanSpanId',
},
parent: {
id: 'myTransactionId1',
},
} as WaterfallSpan,
docType: 'span',
id: 'myOrphanSpanId',
parentId: 'myTransactionId1',
} as IWaterfallSpan,
];
expect(getOrphanItemsIds(traceItems, traceItems[0].id).length).toBe(0);
});
it('should return missing items count if there are orphan items', () => {
@ -770,7 +802,7 @@ describe('waterfall_helpers', () => {
parentId: 'myNotExistingTransactionId1',
} as IWaterfallSpan,
];
expect(getOrphanItemsIds(traceItems).length).toBe(1);
expect(getOrphanItemsIds(traceItems, traceItems[0].id).length).toBe(1);
});
});

View file

@ -340,7 +340,7 @@ function reparentSpans(waterfallItems: IWaterfallSpanOrTransaction[]) {
}
const getChildrenGroupedByParentId = (waterfallItems: IWaterfallSpanOrTransaction[]) =>
groupBy(waterfallItems, (item) => (item.parentId ? item.parentId : ROOT_ID));
groupBy(waterfallItems, (item) => item.parentId ?? ROOT_ID);
const getEntryWaterfallTransaction = (
entryTransactionId: string,
@ -403,10 +403,19 @@ function getErrorCountByParentId(errorDocs: TraceAPIResponse['traceItems']['erro
}, {});
}
export function getOrphanItemsIds(waterfall: IWaterfallSpanOrTransaction[]) {
export function getOrphanItemsIds(
waterfall: IWaterfallSpanOrTransaction[],
entryWaterfallTransactionId?: string
) {
const waterfallItemsIds = new Set(waterfall.map((item) => item.id));
return waterfall
.filter((item) => item.parentId && !waterfallItemsIds.has(item.parentId))
.filter(
(item) =>
// the root transaction should never be orphan
entryWaterfallTransactionId !== item.id &&
item.parentId &&
!waterfallItemsIds.has(item.parentId)
)
.map((item) => item.id);
}
@ -455,7 +464,7 @@ export function getWaterfall(apiResponse: TraceAPIResponse): IWaterfall {
waterfallItems
);
const orphanItemsIds = getOrphanItemsIds(waterfallItems);
const orphanItemsIds = getOrphanItemsIds(waterfallItems, entryWaterfallTransaction?.id);
const childrenByParentId = getChildrenGroupedByParentId(
reparentOrphanItems(
orphanItemsIds,