Skip to content

Commit e67baf1

Browse files
authored
Flamechart crash fix (#6336)
* Revert the previous fix that didn't work * Type tags checks instead of instanceof checks
1 parent ec31633 commit e67baf1

4 files changed

Lines changed: 37 additions & 10 deletions

File tree

ui/packages/shared/profile/src/ProfileFlameChart/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ import {TimeUnits, formatDate, formatDuration} from '@parca/utilities';
2222

2323
import ProfileFlameGraph, {validateFlameChartQuery} from '../ProfileFlameGraph';
2424
import {boundsFromProfileSource} from '../ProfileFlameGraph/FlameGraphArrow/utils';
25-
import {MergedProfileSource, ProfileSource, timeFormat} from '../ProfileSource';
25+
import {
26+
MergedProfileSource,
27+
ProfileSource,
28+
isMergedProfileSource,
29+
timeFormat,
30+
} from '../ProfileSource';
2631
import {useProfileFilters} from '../ProfileView/components/ProfileFilters/useProfileFilters';
2732
import type {SamplesData} from '../ProfileView/types/visualization';
2833
import {flamechartDimensionParser} from '../hooks/urlParsers';
@@ -83,7 +88,7 @@ const createFilteredProfileSource = (
8388
profileSource: ProfileSource,
8489
selectedTimeframe: {labels: LabelSet; bounds: NumberDuo}
8590
): ProfileSource | null => {
86-
if (!(profileSource instanceof MergedProfileSource)) {
91+
if (!isMergedProfileSource(profileSource)) {
8792
return null;
8893
}
8994

ui/packages/shared/profile/src/ProfileFlameGraph/FlameGraphArrow/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from '@parca/store';
2323
import {divide, getLastItem, valueFormatter} from '@parca/utilities';
2424

25-
import {MergedProfileSource, ProfileSource} from '../../ProfileSource';
25+
import {ProfileSource, isMergedProfileSource} from '../../ProfileSource';
2626
import {BigIntDuo, hexifyAddress} from '../../utils';
2727
import {
2828
FIELD_DEPTH,
@@ -115,7 +115,7 @@ export const boundsFromProfileSource = (profileSource?: ProfileSource): BigIntDu
115115
return [0n, 1n];
116116
}
117117

118-
if (!(profileSource instanceof MergedProfileSource)) {
118+
if (!isMergedProfileSource(profileSource)) {
119119
return [0n, 1n];
120120
}
121121

ui/packages/shared/profile/src/ProfileSource.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,32 @@ export class MergedProfileSelection implements ProfileSelection {
120120
}
121121
}
122122

123+
// Type tag carried on instances so we can identify them reliably even when the
124+
// class gets duplicated across bundle chunks (prod builds sometimes end up with
125+
// two copies of the same class, making `instanceof` unreliable).
126+
export const PROFILE_SOURCE_TYPE_MERGED = 'merged' as const;
127+
export const PROFILE_SOURCE_TYPE_DIFF = 'diff' as const;
128+
129+
const getProfileSourceType = (source: ProfileSource | null | undefined): string | undefined => {
130+
if (source == null) return undefined;
131+
const tag = (source as {profileSourceType?: unknown}).profileSourceType;
132+
return typeof tag === 'string' ? tag : undefined;
133+
};
134+
135+
export const isMergedProfileSource = (
136+
source: ProfileSource | null | undefined
137+
): source is MergedProfileSource => {
138+
return getProfileSourceType(source) === PROFILE_SOURCE_TYPE_MERGED;
139+
};
140+
141+
export const isProfileDiffSource = (
142+
source: ProfileSource | null | undefined
143+
): source is ProfileDiffSource => {
144+
return getProfileSourceType(source) === PROFILE_SOURCE_TYPE_DIFF;
145+
};
146+
123147
export class ProfileDiffSource implements ProfileSource {
148+
readonly profileSourceType = PROFILE_SOURCE_TYPE_DIFF;
124149
a: ProfileSource;
125150
b: ProfileSource;
126151
profileType: ProfileType;
@@ -194,6 +219,7 @@ function nanosToTimestamp(nanos: bigint): Timestamp {
194219
}
195220

196221
export class MergedProfileSource implements ProfileSource {
222+
readonly profileSourceType = PROFILE_SOURCE_TYPE_MERGED;
197223
mergeFrom: bigint;
198224
mergeTo: bigint;
199225
query: Query;

ui/packages/shared/utilities/src/bigint.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ export const scaleLinear = (
5555
console.log('domainRange', domainRange, rangeRange, divide(rangeRange, domainRange));
5656
}
5757

58-
// guard 0n to avoid BigInt(Infinity).
59-
const rate =
60-
domainRange === 0n ? 0n : BigInt(Math.round(divide(rangeRange, domainRange) * MULTIPLE));
58+
// rate * MULTIPLE to retain the decimal places in BigInt format, then divide by MULTIPLE to get the final result
59+
const rate = BigInt(Math.round(divide(rangeRange, domainRange) * MULTIPLE));
6160

6261
const func = (x: bigint): number => {
6362
if (debugLog) {
@@ -75,9 +74,6 @@ export const scaleLinear = (
7574
};
7675

7776
func.ticks = (count = 5): bigint[] => {
78-
if (count <= 1 || domainRange === 0n) {
79-
return [domainMin];
80-
}
8177
const step = domainRange / BigInt(count - 1);
8278
const ticks: bigint[] = [];
8379
for (let i = 0; i < count; i++) {

0 commit comments

Comments
 (0)