123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- import {Component, Fragment} from 'react';
- import type {Location} from 'history';
- import Panel from 'sentry/components/panels/panel';
- import type {Organization} from 'sentry/types';
- import type EventView from 'sentry/utils/discover/eventView';
- import type {WebVital} from 'sentry/utils/fields';
- import HistogramQuery from 'sentry/utils/performance/histogram/histogramQuery';
- import type {DataFilter, HistogramData} from 'sentry/utils/performance/histogram/types';
- import {WEB_VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
- import type {VitalGroup} from 'sentry/utils/performance/vitals/types';
- import type {VitalData} from 'sentry/utils/performance/vitals/vitalsCardsDiscoverQuery';
- import {decodeScalar} from 'sentry/utils/queryString';
- import {NUM_BUCKETS, VITAL_GROUPS} from './constants';
- import VitalCard from './vitalCard';
- type Props = {
- eventView: EventView;
- location: Location;
- organization: Organization;
- results: object;
- dataFilter?: DataFilter;
- };
- class VitalsPanel extends Component<Props> {
- renderVitalCard(
- vital: WebVital,
- isLoading: boolean,
- error: boolean,
- data: VitalData | null,
- histogram: HistogramData,
- color: [string],
- min?: number,
- max?: number,
- precision?: number
- ) {
- const {location, organization, eventView, dataFilter} = this.props;
- const vitalDetails = WEB_VITAL_DETAILS[vital];
- const zoomed = min !== undefined || max !== undefined;
- return (
- <HistogramQuery
- location={location}
- orgSlug={organization.slug}
- eventView={eventView}
- numBuckets={NUM_BUCKETS}
- fields={zoomed ? [vital] : []}
- min={min}
- max={max}
- precision={precision}
- dataFilter={dataFilter}
- >
- {results => {
- const loading = zoomed ? results.isLoading : isLoading;
- const errored = zoomed ? results.error !== null : error;
- const chartData = zoomed ? results.histograms?.[vital] ?? histogram : histogram;
- return (
- <VitalCard
- location={location}
- isLoading={loading}
- error={errored}
- vital={vital}
- vitalDetails={vitalDetails}
- summaryData={data}
- chartData={chartData}
- colors={color}
- eventView={eventView}
- organization={organization}
- min={min}
- max={max}
- precision={precision}
- dataFilter={dataFilter}
- />
- );
- }}
- </HistogramQuery>
- );
- }
- renderVitalGroup(group: VitalGroup, summaryResults) {
- const {location, organization, eventView, dataFilter} = this.props;
- const {vitals, colors, min, max, precision} = group;
- const bounds = vitals.reduce(
- (
- allBounds: Partial<
- Record<WebVital, {end: string | undefined; start: string | undefined}>
- >,
- vital: WebVital
- ) => {
- const slug = WEB_VITAL_DETAILS[vital].slug;
- allBounds[vital] = {
- start: decodeScalar(location.query[`${slug}Start`]),
- end: decodeScalar(location.query[`${slug}End`]),
- };
- return allBounds;
- },
- {}
- );
- return (
- <HistogramQuery
- location={location}
- orgSlug={organization.slug}
- eventView={eventView}
- numBuckets={NUM_BUCKETS}
- fields={vitals}
- min={min}
- max={max}
- precision={precision}
- dataFilter={dataFilter}
- >
- {multiHistogramResults => {
- const isLoading = summaryResults.isLoading || multiHistogramResults.isLoading;
- const error =
- summaryResults.error !== null || multiHistogramResults.error !== null;
- return (
- <Fragment>
- {vitals.map((vital, index) => {
- const data = summaryResults?.vitalsData?.[vital] ?? null;
- const histogram = multiHistogramResults.histograms?.[vital] ?? [];
- const {start, end} = bounds[vital] ?? {};
- return (
- <Fragment key={vital}>
- {this.renderVitalCard(
- vital,
- isLoading,
- error,
- data,
- histogram,
- [colors[index]],
- parseBound(start, precision),
- parseBound(end, precision),
- precision
- )}
- </Fragment>
- );
- })}
- </Fragment>
- );
- }}
- </HistogramQuery>
- );
- }
- render() {
- const {results} = this.props;
- return (
- <Panel>
- <Fragment>
- {VITAL_GROUPS.map(vitalGroup => (
- <Fragment key={vitalGroup.vitals.join('')}>
- {this.renderVitalGroup(vitalGroup, results)}
- </Fragment>
- ))}
- </Fragment>
- </Panel>
- );
- }
- }
- function parseBound(
- boundString: string | undefined,
- precision: number | undefined
- ): number | undefined {
- if (boundString === undefined) {
- return undefined;
- }
- if (precision === undefined || precision === 0) {
- return parseInt(boundString, 10);
- }
- return parseFloat(boundString);
- }
- export default VitalsPanel;
|