mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
135 lines
4.0 KiB
TypeScript
135 lines
4.0 KiB
TypeScript
import {Fragment} from 'react';
|
|
import {browserHistory} from 'react-router';
|
|
import styled from '@emotion/styled';
|
|
import type {Location} from 'history';
|
|
|
|
import {Button} from 'sentry/components/button';
|
|
import {SectionHeading} from 'sentry/components/charts/styles';
|
|
import type {CursorHandler} from 'sentry/components/pagination';
|
|
import Pagination from 'sentry/components/pagination';
|
|
import {t} from 'sentry/locale';
|
|
import {space} from 'sentry/styles/space';
|
|
import type {Organization} from 'sentry/types';
|
|
import type EventView from 'sentry/utils/discover/eventView';
|
|
import SuspectSpansQuery from 'sentry/utils/performance/suspectSpans/suspectSpansQuery';
|
|
import {decodeScalar} from 'sentry/utils/queryString';
|
|
import useProjects from 'sentry/utils/useProjects';
|
|
|
|
import SuspectSpansTable from '../transactionSpans/suspectSpansTable';
|
|
import type {SpansTotalValues} from '../transactionSpans/types';
|
|
import {SpanSortOthers, SpanSortPercentiles} from '../transactionSpans/types';
|
|
import {
|
|
getSuspectSpanSortFromLocation,
|
|
SPAN_SORT_TO_FIELDS,
|
|
spansRouteWithQuery,
|
|
} from '../transactionSpans/utils';
|
|
|
|
const SPANS_CURSOR_NAME = 'spansCursor';
|
|
|
|
type Props = {
|
|
eventView: EventView;
|
|
location: Location;
|
|
organization: Organization;
|
|
projectId: string;
|
|
totals: SpansTotalValues | null;
|
|
transactionName: string;
|
|
};
|
|
|
|
export default function SuspectSpans(props: Props) {
|
|
const {location, organization, eventView, totals, projectId, transactionName} = props;
|
|
const sort = getSuspectSpanSortFromLocation(location, 'spanSort');
|
|
const cursor = decodeScalar(location.query?.[SPANS_CURSOR_NAME]);
|
|
|
|
const sortedEventView = eventView
|
|
.withColumns(
|
|
[...Object.values(SpanSortOthers), ...Object.values(SpanSortPercentiles)].map(
|
|
field => ({kind: 'field', field})
|
|
)
|
|
)
|
|
.withSorts([{kind: 'desc', field: sort.field}]);
|
|
const fields = SPAN_SORT_TO_FIELDS[sort.field];
|
|
sortedEventView.fields = fields ? fields.map(field => ({field})) : [];
|
|
|
|
const {projects} = useProjects();
|
|
|
|
return (
|
|
<SuspectSpansQuery
|
|
location={location}
|
|
orgSlug={organization.slug}
|
|
eventView={sortedEventView}
|
|
limit={4}
|
|
perSuspect={0}
|
|
cursor={cursor}
|
|
>
|
|
{({suspectSpans, isLoading, pageLinks}) => (
|
|
<Fragment>
|
|
<SuspectSpansHeader
|
|
location={location}
|
|
organization={organization}
|
|
projectId={projectId}
|
|
transactionName={transactionName}
|
|
pageLinks={pageLinks}
|
|
/>
|
|
<SuspectSpansTable
|
|
location={location}
|
|
organization={organization}
|
|
transactionName={transactionName}
|
|
project={projects.find(p => p.id === projectId)}
|
|
isLoading={isLoading}
|
|
suspectSpans={suspectSpans ?? []}
|
|
totals={totals}
|
|
sort={SpanSortOthers.SUM_EXCLUSIVE_TIME}
|
|
/>
|
|
</Fragment>
|
|
)}
|
|
</SuspectSpansQuery>
|
|
);
|
|
}
|
|
|
|
type HeaderProps = {
|
|
location: Location;
|
|
organization: Organization;
|
|
pageLinks: string | null;
|
|
projectId: string;
|
|
transactionName: string;
|
|
};
|
|
|
|
function SuspectSpansHeader(props: HeaderProps) {
|
|
const {location, organization, projectId, transactionName, pageLinks} = props;
|
|
|
|
const viewAllTarget = spansRouteWithQuery({
|
|
orgSlug: organization.slug,
|
|
transaction: transactionName,
|
|
projectID: projectId,
|
|
query: location.query,
|
|
});
|
|
|
|
const handleCursor: CursorHandler = (cursor, pathname, query) => {
|
|
browserHistory.push({
|
|
pathname,
|
|
query: {...query, [SPANS_CURSOR_NAME]: cursor},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Header>
|
|
<SectionHeading>{t('Suspect Spans')}</SectionHeading>
|
|
<Button to={viewAllTarget} size="xs" data-test-id="suspect-spans-open-tab">
|
|
{t('View All Spans')}
|
|
</Button>
|
|
<StyledPagination pageLinks={pageLinks} onCursor={handleCursor} size="xs" />
|
|
</Header>
|
|
);
|
|
}
|
|
|
|
const Header = styled('div')`
|
|
display: grid;
|
|
grid-template-columns: 1fr auto auto;
|
|
margin-bottom: ${space(1)};
|
|
align-items: center;
|
|
`;
|
|
|
|
const StyledPagination = styled(Pagination)`
|
|
margin: 0 0 0 ${space(1)};
|
|
`;
|