-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
ref(insights): Refactor PerformanceScoreBreakdownChart
#89632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Move into its own component and parse location query itself Part of #88560
...ic/app/views/insights/browser/webVitals/components/charts/performanceScoreBreakdownChart.tsx
Outdated
Show resolved
Hide resolved
const { | ||
transaction, | ||
[SpanIndexedField.BROWSER_NAME]: browserTypes, | ||
[SpanIndexedField.USER_GEO_SUBREGION]: subregions, | ||
} = useLocationQuery({ | ||
fields: { | ||
[SpanIndexedField.BROWSER_NAME]: decodeBrowserTypes, | ||
[SpanIndexedField.USER_GEO_SUBREGION]: decodeList, | ||
transaction: decodeList, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated this to use useLocationQuery
browserTypes={browserTypes} | ||
subregions={subregions} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new widget grabs these itself from query params
@@ -33,10 +28,7 @@ export const ORDER: WebVitals[] = ['lcp', 'fcp', 'inp', 'cls', 'ttfb']; | |||
export function PerformanceScoreChart({ | |||
projectScore, | |||
webVital, | |||
transaction, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only pageOverview
passes transaction
, and it comes from query params, so this was moved into the new widget
browserTypes, | ||
subregions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto re: query params and moving to new widget
@codecov-ai-reviewer review |
On it! We are reviewing the PR and will provide feedback shortly. |
import {SpanIndexedField, SpanMetricsField} from 'sentry/views/insights/types'; | ||
|
||
export function PerformanceScoreBreakdownChartWidget(props: LoadableChartWidgetProps) { | ||
const { | ||
transaction, | ||
[SpanIndexedField.BROWSER_NAME]: browserTypes, | ||
[SpanIndexedField.USER_GEO_SUBREGION]: subregions, | ||
} = useLocationQuery({ | ||
fields: { | ||
[SpanIndexedField.BROWSER_NAME]: decodeBrowserTypes, | ||
[SpanIndexedField.USER_GEO_SUBREGION]: decodeList, | ||
transaction: decodeList, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new component could benefit from proper TypeScript interfaces for better type safety and documentation. Consider extracting the type definition for the decoded query parameters into a separate interface. Additionally, the useLocationQuery
hook's fields object could be moved to a constant to avoid recreating it on every render.
import {SpanIndexedField, SpanMetricsField} from 'sentry/views/insights/types'; | |
export function PerformanceScoreBreakdownChartWidget(props: LoadableChartWidgetProps) { | |
const { | |
transaction, | |
[SpanIndexedField.BROWSER_NAME]: browserTypes, | |
[SpanIndexedField.USER_GEO_SUBREGION]: subregions, | |
} = useLocationQuery({ | |
fields: { | |
[SpanIndexedField.BROWSER_NAME]: decodeBrowserTypes, | |
[SpanIndexedField.USER_GEO_SUBREGION]: decodeList, | |
transaction: decodeList, | |
interface QueryParams { | |
[SpanIndexedField.BROWSER_NAME]: ReturnType<typeof decodeBrowserTypes>; | |
[SpanIndexedField.USER_GEO_SUBREGION]: string[]; | |
transaction: string[]; | |
} | |
const QUERY_FIELDS = { | |
[SpanIndexedField.BROWSER_NAME]: decodeBrowserTypes, | |
[SpanIndexedField.USER_GEO_SUBREGION]: decodeList, | |
transaction: decodeList, | |
}; | |
export function PerformanceScoreBreakdownChartWidget(props: LoadableChartWidgetProps) { | |
const { | |
transaction, | |
[SpanIndexedField.BROWSER_NAME]: browserTypes, | |
[SpanIndexedField.USER_GEO_SUBREGION]: subregions, | |
} = useLocationQuery<QueryParams>({ | |
fields: QUERY_FIELDS, | |
}); |
const weights = getWeights(webVitalsThatHaveData); | ||
|
||
const allSeries: DiscoverSeries[] = vitalScoresData | ||
? ORDER.map((webVital, index) => { | ||
const key = `performance_score(measurements.score.${webVital})` as const; | ||
const series = vitalScoresData[key]; | ||
|
||
const scaledSeries: DiscoverSeries = { | ||
...series, | ||
data: series.data.map(datum => { | ||
return { | ||
...datum, | ||
value: datum.value * weights[webVital], | ||
}; | ||
}), | ||
color: segmentColors[index], | ||
meta: { | ||
// TODO: The backend doesn't return these score fields with the "score" type yet. Fill this in manually for now. | ||
fields: { | ||
...series.meta?.fields, | ||
[key]: 'score', | ||
}, | ||
units: series.meta?.units, | ||
}, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The series transformation logic is quite complex and could be extracted into a separate utility function for better maintainability and testability. Also consider adding memoization for the allSeries
calculation to prevent unnecessary recalculations on re-renders.
const weights = getWeights(webVitalsThatHaveData); | |
const allSeries: DiscoverSeries[] = vitalScoresData | |
? ORDER.map((webVital, index) => { | |
const key = `performance_score(measurements.score.${webVital})` as const; | |
const series = vitalScoresData[key]; | |
const scaledSeries: DiscoverSeries = { | |
...series, | |
data: series.data.map(datum => { | |
return { | |
...datum, | |
value: datum.value * weights[webVital], | |
}; | |
}), | |
color: segmentColors[index], | |
meta: { | |
// TODO: The backend doesn't return these score fields with the "score" type yet. Fill this in manually for now. | |
fields: { | |
...series.meta?.fields, | |
[key]: 'score', | |
}, | |
units: series.meta?.units, | |
}, | |
}; | |
const transformVitalScores = useCallback((vitalScoresData: any, segmentColors: string[], weights: Record<string, number>): DiscoverSeries[] => { | |
return ORDER.map((webVital, index) => { | |
const key = `performance_score(measurements.score.${webVital})` as const; | |
const series = vitalScoresData[key]; | |
return { | |
...series, | |
data: series.data.map(datum => ({ | |
...datum, | |
value: datum.value * weights[webVital], | |
})), | |
color: segmentColors[index], | |
meta: { | |
fields: { | |
...series.meta?.fields, | |
[key]: 'score', | |
}, | |
units: series.meta?.units, | |
}, | |
}; | |
}); | |
}, []); | |
const allSeries = useMemo( | |
() => (vitalScoresData ? transformVitalScores(vitalScoresData, segmentColors, weights) : []), | |
[vitalScoresData, segmentColors, weights, transformVitalScores] | |
); |
static/app/views/insights/browser/webVitals/views/pageOverview.tsx
Outdated
Show resolved
Hide resolved
- remove shallow unneeded chart wrapper - rename helper-only file to match the function inside
Move into its own component and parse location query itself Part of #88560 --------- Co-authored-by: George Gritsouk <989898+gggritso@users.noreply.github.com>
Move into its own component and parse location query itself
Part of #88560