import * as qs from 'query-string';
import {getInterval} from 'sentry/components/charts/utils';
import Duration from 'sentry/components/duration';
import Link from 'sentry/components/links/link';
import {t} from 'sentry/locale';
import type {NewQuery} from 'sentry/types/organization';
import EventView from 'sentry/utils/discover/eventView';
import {NumberContainer} from 'sentry/utils/discover/styles';
import {DiscoverDatasets} from 'sentry/utils/discover/types';
import {decodeScalar} from 'sentry/utils/queryString';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import {useLocation} from 'sentry/utils/useLocation';
import usePageFilters from 'sentry/utils/usePageFilters';
import {
PRIMARY_RELEASE_ALIAS,
SECONDARY_RELEASE_ALIAS,
} from 'sentry/views/insights/common/components/releaseSelector';
import {OverflowEllipsisTextContainer} from 'sentry/views/insights/common/components/textAlign';
import {STARFISH_CHART_INTERVAL_FIDELITY} from 'sentry/views/insights/common/utils/constants';
import {appendReleaseFilters} from 'sentry/views/insights/common/utils/releaseComparison';
import {useModuleURL} from 'sentry/views/insights/common/utils/useModuleURL';
import {APP_START_SPANS} from 'sentry/views/insights/mobile/appStarts/components/spanOpSelector';
import type {SpanOperationTableProps} from 'sentry/views/insights/mobile/common/components/tables/samplesTables';
import {ScreensTable} from 'sentry/views/insights/mobile/common/components/tables/screensTable';
import {useTableQuery} from 'sentry/views/insights/mobile/screenload/components/tables/screensTable';
import {MobileCursors} from 'sentry/views/insights/mobile/screenload/constants';
import {Referrer} from 'sentry/views/insights/mobile/ui/referrers';
import {ModuleName, SpanMetricsField} from 'sentry/views/insights/types';
const {SPAN_DESCRIPTION, SPAN_GROUP, SPAN_OP, PROJECT_ID} = SpanMetricsField;
const VALID_SPAN_OPS = APP_START_SPANS;
export function SpanOperationTable({
transaction,
primaryRelease,
secondaryRelease,
}: SpanOperationTableProps) {
const moduleURL = useModuleURL('mobile-ui');
const location = useLocation();
const {selection} = usePageFilters();
const cursor = decodeScalar(location.query?.[MobileCursors.SPANS_TABLE]);
const spanOp = decodeScalar(location.query[SpanMetricsField.SPAN_OP]) ?? '';
const deviceClass = decodeScalar(location.query[SpanMetricsField.DEVICE_CLASS]) ?? '';
// TODO: These filters seem to be too aggressive, check that they are ingesting properly
const searchQuery = new MutableSearch([
// 'has:span.description',
// 'transaction.op:ui.load',
`transaction:${transaction}`,
`${SpanMetricsField.SPAN_OP}:${spanOp ? spanOp : `[${VALID_SPAN_OPS.join(',')}]`}`,
...(spanOp ? [`${SpanMetricsField.SPAN_OP}:${spanOp}`] : []),
...(deviceClass ? [`${SpanMetricsField.DEVICE_CLASS}:${deviceClass}`] : []),
]);
const queryStringPrimary = appendReleaseFilters(
searchQuery,
primaryRelease,
secondaryRelease
);
const orderby = decodeScalar(location.query.sort, '');
const newQuery: NewQuery = {
name: '',
fields: [
PROJECT_ID,
SPAN_OP,
SPAN_GROUP,
SPAN_DESCRIPTION,
`division_if(mobile.slow_frames,mobile.total_frames,release,${primaryRelease})`,
`division_if(mobile.slow_frames,mobile.total_frames,release,${secondaryRelease})`,
`division_if(mobile.frozen_frames,mobile.total_frames,release,${primaryRelease})`,
`division_if(mobile.frozen_frames,mobile.total_frames,release,${secondaryRelease})`,
`avg_if(mobile.frames_delay,release,${primaryRelease})`,
`avg_if(mobile.frames_delay,release,${secondaryRelease})`,
`avg_compare(mobile.frames_delay,release,${primaryRelease},${secondaryRelease})`,
],
query: queryStringPrimary,
orderby,
dataset: DiscoverDatasets.SPANS_METRICS,
version: 2,
projects: selection.projects,
interval: getInterval(selection.datetime, STARFISH_CHART_INTERVAL_FIDELITY),
};
const eventView = EventView.fromNewQueryWithLocation(newQuery, location);
const {data, isPending, pageLinks} = useTableQuery({
eventView,
enabled: true,
referrer: Referrer.SPAN_OPERATION_TABLE,
cursor,
});
const columnNameMap = {
[SPAN_OP]: t('Operation'),
[SPAN_DESCRIPTION]: t('Span Description'),
[`division_if(mobile.slow_frames,mobile.total_frames,release,${primaryRelease})`]: t(
'Slow (%s)',
PRIMARY_RELEASE_ALIAS
),
[`division_if(mobile.slow_frames,mobile.total_frames,release,${secondaryRelease})`]:
t('Slow (%s)', SECONDARY_RELEASE_ALIAS),
[`division_if(mobile.frozen_frames,mobile.total_frames,release,${primaryRelease})`]:
t('Frozen (%s)', PRIMARY_RELEASE_ALIAS),
[`division_if(mobile.frozen_frames,mobile.total_frames,release,${secondaryRelease})`]:
t('Frozen (%s)', SECONDARY_RELEASE_ALIAS),
[`avg_if(mobile.frames_delay,release,${primaryRelease})`]: t(
'Delay (%s)',
PRIMARY_RELEASE_ALIAS
),
[`avg_if(mobile.frames_delay,release,${secondaryRelease})`]: t(
'Delay (%s)',
SECONDARY_RELEASE_ALIAS
),
[`avg_compare(mobile.frames_delay,release,${primaryRelease},${secondaryRelease})`]:
t('Change'),
};
const columnTooltipMap = {
[`division_if(mobile.slow_frames,mobile.total_frames,release,${primaryRelease})`]: t(
'The number of slow frames divided by total frames (%s)',
PRIMARY_RELEASE_ALIAS
),
[`division_if(mobile.slow_frames,mobile.total_frames,release,${secondaryRelease})`]:
t(
'The number of slow frames divided by total frames (%s)',
SECONDARY_RELEASE_ALIAS
),
[`division_if(mobile.frozen_frames,mobile.total_frames,release,${primaryRelease})`]:
t(
'The number of frozen frames divided by total frames (%s)',
PRIMARY_RELEASE_ALIAS
),
[`division_if(mobile.frozen_frames,mobile.total_frames,release,${secondaryRelease})`]:
t(
'The number of frozen frames divided by total frames (%s)',
SECONDARY_RELEASE_ALIAS
),
};
function renderBodyCell(column, row) {
if (column.key === SPAN_DESCRIPTION) {
const label = row[SpanMetricsField.SPAN_DESCRIPTION];
const pathname = `${moduleURL}/spans/`;
const query = {
...location.query,
transaction,
spanOp: row[SpanMetricsField.SPAN_OP],
spanGroup: row[SpanMetricsField.SPAN_GROUP],
spanDescription: row[SpanMetricsField.SPAN_DESCRIPTION],
};
return (
{label}
);
}
if (column.key.startsWith('avg_if(mobile.frames_delay')) {
return (
{typeof row[column.key] === 'number' ? (
) : (
'-'
)}
);
}
return null;
}
return (
);
}