Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function AISpanList({
const nodesByTransaction = useMemo(() => {
const result: Map<TransactionNode | EapSpanNode, AITraceSpanNode[]> = new Map();
for (const node of nodes) {
const transaction = node.findParentEapTransaction() ?? node.findParentTransaction();
const transaction = node.findClosestParentTransaction();
if (!transaction) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function useNodeDetailsLink({
const location = useLocation();

const spanId: string | undefined = node?.id;
const targetId: string | undefined = node?.transactionId ?? undefined;
const targetId: string | undefined = node?.transactionId;
const timestamp: number | undefined = node?.startTimestamp;

return getTraceDetailsUrl({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,8 @@ export function ProfilePreview({
}, [profileGroup.profiles, profileGroup.activeProfileIndex, spanThreadId]);

const transactionHasProfile = useMemo(() => {
const parentTransaction =
missingInstrumentationNode.findParentEapTransaction() ??
missingInstrumentationNode.findParentTransaction();
return (parentTransaction?.profiles?.size ?? 0) > 0;
const parentTransaction = missingInstrumentationNode.findClosestParentTransaction();
return !!parentTransaction?.hasProfiles;
}, [missingInstrumentationNode]);

const flamegraph = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,10 @@ export function SpanNodeDetails(
const {projects} = useProjects();
const issues = node.uniqueIssues;

const parentTransaction = isEAPSpanNode(node)
? node.value.is_transaction
? node
: node.findParentEapTransaction()
: node.findParentTransaction();
const profileId = parentTransaction?.value.profile_id;
const profilerId = parentTransaction?.value.profiler_id;
const profileId = node.profileId;
const profilerId = node.profilerId;

const parentTransaction = node.findClosestParentTransaction();
const profilerStart = parentTransaction?.startTimestamp;
const profilerEnd = parentTransaction?.endTimestamp;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function useSpanAncestryAndGroupingItems({
onParentClick: (node: BaseNode) => void;
organization: Organization;
}): SectionCardKeyValueList {
const parentTransaction = useMemo(() => node.findParentTransaction(), [node]);
const parentTransaction = useMemo(() => node.findClosestParentTransaction(), [node]);
const childTransactions = useMemo(() => {
const transactions: TransactionNode[] = [];
node.forEachChild(c => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ function TransactionNodeDetailHeader({
{!hideNodeActions && (
<TraceDrawerComponents.NodeActions
node={node}
profileId={node.value.profile_id}
profilerId={node.value.profiler_id}
profileId={node.profileId}
profilerId={node.profilerId}
threadId={event?.contexts?.trace?.data?.['thread.id']}
organization={organization}
onTabScrollToNode={onTabScrollToNode}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function GeneralInfo(props: GeneralInfoProps) {
endTimestamp / 1e3
);

const parentTransaction = node.findParentTransaction();
const parentTransaction = node.findClosestParentTransaction();

const items: SectionCardKeyValueList = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export function TraceProfiles({tree}: {tree: TraceTree}) {
);

const onProfileLinkClick = useCallback(
(profile: TraceTree.Profile) => {
if ('profiler_id' in profile) {
(type: 'continuous' | 'transaction') => {
if (type === 'continuous') {
traceAnalytics.trackViewContinuousProfile(organization);
} else {
traceAnalytics.trackViewTransactionProfile(organization);
Expand All @@ -54,9 +54,10 @@ export function TraceProfiles({tree}: {tree: TraceTree}) {
</ProfilesTableRow>

{profiles.map((node, index) => {
const profile = Array.from(node.profiles)?.[0];
const profileId = node.profileId;
const profilerId = node.profilerId;

if (!profile) {
if (!profileId && !profilerId) {
return null;
}

Expand All @@ -66,25 +67,23 @@ export function TraceProfiles({tree}: {tree: TraceTree}) {
}
: {};

const link =
'profiler_id' in profile
? generateContinuousProfileFlamechartRouteWithQuery({
organization,
profilerId: profile.profiler_id,
start: new Date(node.space[0]).toISOString(),
end: new Date(node.space[0] + node.space[1]).toISOString(),
projectSlug: node.projectSlug ?? '',
query,
})
: generateProfileFlamechartRouteWithQuery({
organization,
projectSlug: node.projectSlug ?? '',
profileId: profile.profile_id,
query,
});

const profileOrProfilerId =
'profiler_id' in profile ? profile.profiler_id : profile.profile_id;
const link = profilerId
? generateContinuousProfileFlamechartRouteWithQuery({
organization,
profilerId,
start: new Date(node.space[0]).toISOString(),
end: new Date(node.space[0] + node.space[1]).toISOString(),
projectSlug: node.projectSlug ?? '',
query,
})
: generateProfileFlamechartRouteWithQuery({
organization,
projectSlug: node.projectSlug ?? '',
profileId: profileId!,
query,
});

const profileOrProfilerId = profilerId || profileId;

const event = (
<Fragment>
Expand All @@ -103,8 +102,13 @@ export function TraceProfiles({tree}: {tree: TraceTree}) {
<ProfilesTableRow key={index}>
<div>{event}</div>
<div>
<Link to={link} onClick={() => onProfileLinkClick(profile)}>
{profileOrProfilerId.substring(0, 8)}
<Link
to={link}
onClick={() =>
onProfileLinkClick(profilerId ? 'continuous' : 'transaction')
}
>
{profileOrProfilerId!.substring(0, 8)}
</Link>
</div>
</ProfilesTableRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function getEventId(node: BaseNode): string | undefined {
if (isTransactionNode(node)) {
return node.value.event_id;
}
return node.findParentTransaction()?.value?.event_id;
return node.findParentNodeStoreTransaction()?.value?.event_id;
}

export function makeTransactionProfilingLink(
Expand Down Expand Up @@ -69,7 +69,9 @@ export function makeTraceContinuousProfilingLink(

// We compute a time offset based on the duration of the span so that
// users can see some context of things that occurred before and after the span.
const transaction = isTransactionNode(node) ? node : node.findParentTransaction();
const transaction = isTransactionNode(node)
? node
: node.findParentNodeStoreTransaction();
if (!transaction) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ export class IssuesTraceTree extends TraceTree {
const preserveNodes = new Set(preserveLeafNodes);

for (const node of preserveLeafNodes) {
const parentTransaction =
node.findParentTransaction() ?? node.findParentEapTransaction();
const parentTransaction = node.findClosestParentTransaction();
if (parentTransaction) {
preserveNodes.add(parentTransaction);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ export class TraceTree extends TraceTreeEventDispatcher {
tree.eap_spans_count++;

// We only want to add transactions as profiled events.
if ((node as EapSpanNode).value.is_transaction && node.profiles.size > 0) {
if ((node as EapSpanNode).value.is_transaction && node.hasProfiles) {
tree.profiled_events.add(node);
}
} else if (isUptimeCheck(value)) {
Expand All @@ -482,7 +482,7 @@ export class TraceTree extends TraceTreeEventDispatcher {
});

// We only want to add transactions as profiled events.
if (node.profiles.size > 0) {
if (node.hasProfiles) {
tree.profiled_events.add(node);
}
}
Expand Down Expand Up @@ -517,10 +517,6 @@ export class TraceTree extends TraceTreeEventDispatcher {
traceNode.occurrences.add(occurrence);
}

if (c.profiles.size > 0) {
tree.profiled_events.add(c);
}

if (c.value && 'measurements' in c.value) {
tree.indicators = tree.indicators.concat(
collectTraceMeasurements(
Expand Down Expand Up @@ -662,8 +658,8 @@ export class TraceTree extends TraceTreeEventDispatcher {
baseTraceNode.occurrences.add(occurrence);
}

for (const profile of additionalTraceNode.profiles) {
baseTraceNode.profiles.add(profile);
for (const profiledEvent of tree.profiled_events) {
this.profiled_events.add(profiledEvent);
}

for (const [node, vitals] of tree.vitals) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ describe('BaseNode', () => {
expect(node.children).toEqual([]);
expect(node.errors).toBeInstanceOf(Set);
expect(node.occurrences).toBeInstanceOf(Set);
expect(node.profiles).toBeInstanceOf(Set);
expect(node.isEAPEvent).toBe(false);
expect(node.canShowDetails).toBe(true);
expect(node.searchPriority).toBe(0);
Expand Down Expand Up @@ -518,8 +517,7 @@ describe('BaseNode', () => {

const node = new TestNode(null, value, extra);

expect(node.profiles.size).toBe(1);
expect(Array.from(node.profiles)).toEqual([{profile_id: 'profile-123'}]);
expect(node.profileId).toBe('profile-123');
});

it('should collect profile from profiler_id during construction', () => {
Expand All @@ -530,22 +528,19 @@ describe('BaseNode', () => {
});

const node = new TestNode(null, value, extra);

expect(node.profiles.size).toBe(1);
expect(Array.from(node.profiles)).toEqual([{profiler_id: 'profiler-456'}]);
expect(node.profilerId).toBe('profiler-456');
});

it('should ignore empty profile IDs', () => {
const extra = createMockExtra();
const value = createMockValue({
event_id: 'test-id',
profile_id: '',
profiler_id: ' ',
});

const node = new TestNode(null, value, extra);

expect(node.profiles.size).toBe(0);
expect(node.profileId).toBeUndefined();
});

it('should collect both profile_id and profiler_id', () => {
Expand All @@ -558,10 +553,8 @@ describe('BaseNode', () => {

const node = new TestNode(null, value, extra);

expect(node.profiles.size).toBe(2);
const profilesArray = Array.from(node.profiles);
expect(profilesArray).toContainEqual({profile_id: 'profile-123'});
expect(profilesArray).toContainEqual({profiler_id: 'profiler-456'});
expect(node.profileId).toBe('profile-123');
expect(node.profilerId).toBe('profiler-456');
});
});

Expand Down Expand Up @@ -1568,7 +1561,7 @@ describe('BaseNode', () => {
const extra = createMockExtra();
const node = new TestNode(null, createMockValue({event_id: 'test'}), extra);

expect(node.findParentTransaction()).toBeNull();
expect(node.findParentNodeStoreTransaction()).toBeNull();
});

it('should find parent transaction node', () => {
Expand All @@ -1581,7 +1574,7 @@ describe('BaseNode', () => {
const child = new TestNode(null, createMockValue({event_id: 'child'}), extra);
jest.spyOn(child, 'findParent').mockReturnValue(mockTransactionParent as any);

const result = child.findParentTransaction();
const result = child.findParentNodeStoreTransaction();
expect(result).toBe(mockTransactionParent);
expect(child.findParent).toHaveBeenCalledWith(expect.any(Function));
});
Expand Down Expand Up @@ -1657,36 +1650,4 @@ describe('BaseNode', () => {
expect(node.hasOccurrences).toBe(true);
});
});

describe('transactionId getter', () => {
it('should return null when no parent transaction or EAP transaction exists', () => {
const extra = createMockExtra();
const node = new TestNode(null, createMockValue({event_id: 'test'}), extra);

expect(node.transactionId).toBeNull();
});

it('should return transaction ID from parent transaction node', () => {
const extra = createMockExtra();
const child = new TestNode(null, createMockValue({event_id: 'child'}), extra);

jest.spyOn(child, 'findParentTransaction').mockReturnValue({
transactionId: 'txn-123',
} as any);

expect(child.transactionId).toBe('txn-123');
});

it('should return transaction ID from parent EAP transaction when no regular transaction parent exists', () => {
const extra = createMockExtra();
const child = new TestNode(null, createMockValue({event_id: 'child'}), extra);

jest.spyOn(child, 'findParentTransaction').mockReturnValue(null);
jest.spyOn(child, 'findParentEapTransaction').mockReturnValue({
transactionId: 'eap-txn-456',
} as any);

expect(child.transactionId).toBe('eap-txn-456');
});
});
});
Loading
Loading