|
@@ -5,11 +5,9 @@ import {Observer} from 'mobx-react';
|
|
|
|
|
|
import Alert from 'sentry/components/alert';
|
|
|
import GuideAnchor from 'sentry/components/assistant/guideAnchor';
|
|
|
-import List from 'sentry/components/list';
|
|
|
-import ListItem from 'sentry/components/list/listItem';
|
|
|
import {Panel} from 'sentry/components/panels';
|
|
|
import SearchBar from 'sentry/components/searchBar';
|
|
|
-import {t, tct, tn} from 'sentry/locale';
|
|
|
+import {t, tn} from 'sentry/locale';
|
|
|
import space from 'sentry/styles/space';
|
|
|
import {Organization} from 'sentry/types';
|
|
|
import {EventTransaction} from 'sentry/types/event';
|
|
@@ -21,9 +19,10 @@ import withOrganization from 'sentry/utils/withOrganization';
|
|
|
|
|
|
import * as AnchorLinkManager from './anchorLinkManager';
|
|
|
import Filter from './filter';
|
|
|
+import TraceErrorList from './traceErrorList';
|
|
|
import TraceView from './traceView';
|
|
|
import {FocusedSpanIDMap, ParsedTraceType} from './types';
|
|
|
-import {parseTrace, scrollToSpan} from './utils';
|
|
|
+import {getCumulativeAlertLevelFromErrors, parseTrace, scrollToSpan} from './utils';
|
|
|
import WaterfallModel from './waterfallModel';
|
|
|
|
|
|
type Props = {
|
|
@@ -92,64 +91,25 @@ class SpansInterface extends PureComponent<Props, State> {
|
|
|
errors.length
|
|
|
);
|
|
|
|
|
|
- // mapping from span ids to the span op and the number of errors in that span
|
|
|
- const errorsMap: {
|
|
|
- [spanId: string]: {errorsCount: number; operation: string};
|
|
|
- } = {};
|
|
|
-
|
|
|
- errors.forEach(error => {
|
|
|
- if (!errorsMap[error.span]) {
|
|
|
- // first check of the error belongs to the root span
|
|
|
- if (parsedTrace.rootSpanID === error.span) {
|
|
|
- errorsMap[error.span] = {
|
|
|
- operation: parsedTrace.op,
|
|
|
- errorsCount: 0,
|
|
|
- };
|
|
|
- } else {
|
|
|
- // since it does not belong to the root span, check if it belongs
|
|
|
- // to one of the other spans in the transaction
|
|
|
- const span = parsedTrace.spans.find(s => s.span_id === error.span);
|
|
|
- if (!span?.op) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- errorsMap[error.span] = {
|
|
|
- operation: span.op,
|
|
|
- errorsCount: 0,
|
|
|
- };
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- errorsMap[error.span].errorsCount++;
|
|
|
- });
|
|
|
-
|
|
|
return (
|
|
|
<AlertContainer>
|
|
|
- <Alert type="error">
|
|
|
+ <Alert type={getCumulativeAlertLevelFromErrors(errors)}>
|
|
|
<ErrorLabel>{label}</ErrorLabel>
|
|
|
+
|
|
|
<AnchorLinkManager.Consumer>
|
|
|
{({scrollToHash}) => (
|
|
|
- <List symbol="bullet">
|
|
|
- {Object.entries(errorsMap).map(([spanId, {operation, errorsCount}]) => (
|
|
|
- <ListItem key={spanId}>
|
|
|
- {tct('[errors] [link]', {
|
|
|
- errors: tn('%s error in ', '%s errors in ', errorsCount),
|
|
|
- link: (
|
|
|
- <ErrorLink
|
|
|
- onClick={scrollToSpan(
|
|
|
- spanId,
|
|
|
- scrollToHash,
|
|
|
- this.props.location,
|
|
|
- this.props.organization
|
|
|
- )}
|
|
|
- >
|
|
|
- {operation}
|
|
|
- </ErrorLink>
|
|
|
- ),
|
|
|
- })}
|
|
|
- </ListItem>
|
|
|
- ))}
|
|
|
- </List>
|
|
|
+ <TraceErrorList
|
|
|
+ trace={parsedTrace}
|
|
|
+ errors={errors}
|
|
|
+ onClickSpan={(event, spanId) => {
|
|
|
+ return scrollToSpan(
|
|
|
+ spanId,
|
|
|
+ scrollToHash,
|
|
|
+ this.props.location,
|
|
|
+ this.props.organization
|
|
|
+ )(event);
|
|
|
+ }}
|
|
|
+ />
|
|
|
)}
|
|
|
</AnchorLinkManager.Consumer>
|
|
|
</Alert>
|
|
@@ -233,13 +193,6 @@ const Container = styled('div')<{hasErrors: boolean}>`
|
|
|
`}
|
|
|
`;
|
|
|
|
|
|
-const ErrorLink = styled('a')`
|
|
|
- color: ${p => p.theme.textColor};
|
|
|
- :hover {
|
|
|
- color: ${p => p.theme.textColor};
|
|
|
- }
|
|
|
-`;
|
|
|
-
|
|
|
const Search = styled('div')`
|
|
|
display: grid;
|
|
|
gap: ${space(2)};
|