|
@@ -4,11 +4,10 @@ import styled from '@emotion/styled';
|
|
|
import {LinkButton} from 'sentry/components/button';
|
|
|
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
|
|
|
import Link from 'sentry/components/links/link';
|
|
|
-import LoadingIndicator from 'sentry/components/loadingIndicator';
|
|
|
-import {ROW_HEIGHT, ROW_PADDING} from 'sentry/components/performance/waterfall/constants';
|
|
|
import {RowRectangle} from 'sentry/components/performance/waterfall/rowBar';
|
|
|
import {pickBarColor} from 'sentry/components/performance/waterfall/utils';
|
|
|
import PerformanceDuration from 'sentry/components/performanceDuration';
|
|
|
+import TimeSince from 'sentry/components/timeSince';
|
|
|
import {Tooltip} from 'sentry/components/tooltip';
|
|
|
import {IconIssues} from 'sentry/icons';
|
|
|
import {t} from 'sentry/locale';
|
|
@@ -27,6 +26,7 @@ import {transactionSummaryRouteWithQuery} from 'sentry/views/performance/transac
|
|
|
|
|
|
import type {TraceResult} from './content';
|
|
|
import type {Field} from './data';
|
|
|
+import {getStylingSliceName} from './utils';
|
|
|
|
|
|
interface ProjectRendererProps {
|
|
|
projectSlug: string;
|
|
@@ -55,8 +55,8 @@ export function ProjectRenderer({projectSlug, hideName}: ProjectRendererProps) {
|
|
|
export const TraceBreakdownContainer = styled('div')`
|
|
|
position: relative;
|
|
|
display: flex;
|
|
|
- min-width: 150px;
|
|
|
- height: ${ROW_HEIGHT - 2 * ROW_PADDING}px;
|
|
|
+ min-width: 200px;
|
|
|
+ height: 15px;
|
|
|
background-color: ${p => p.theme.gray100};
|
|
|
`;
|
|
|
|
|
@@ -67,6 +67,7 @@ const RectangleTraceBreakdown = styled(RowRectangle)<{
|
|
|
background-color: ${p => p.sliceColor};
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
+ height: 15px;
|
|
|
${p => `
|
|
|
opacity: var(--highlightedSlice-${p.sliceName ?? ''}-opacity, var(--defaultSlice-opacity, 1.0));
|
|
|
`}
|
|
@@ -95,10 +96,15 @@ export function TraceBreakdownRenderer({
|
|
|
sliceName={breakdown.project}
|
|
|
sliceStart={breakdown.start}
|
|
|
sliceEnd={breakdown.end}
|
|
|
+ sliceSecondaryName={breakdown.sdkName}
|
|
|
trace={trace}
|
|
|
theme={theme}
|
|
|
onMouseEnter={() =>
|
|
|
- breakdown.project ? setHighlightedSliceName(breakdown.project) : null
|
|
|
+ breakdown.project
|
|
|
+ ? setHighlightedSliceName(
|
|
|
+ getStylingSliceName(breakdown.project, breakdown.sdkName) ?? ''
|
|
|
+ )
|
|
|
+ : null
|
|
|
}
|
|
|
/>
|
|
|
);
|
|
@@ -107,19 +113,22 @@ export function TraceBreakdownRenderer({
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-const BREAKDOWN_BAR_SIZE = 150;
|
|
|
-const BREAKDOWN_QUANTIZE_STEP = 3;
|
|
|
+const BREAKDOWN_BAR_SIZE = 200;
|
|
|
+const BREAKDOWN_QUANTIZE_STEP = 5;
|
|
|
+
|
|
|
export function SpanBreakdownSliceRenderer({
|
|
|
trace,
|
|
|
theme,
|
|
|
sliceName,
|
|
|
sliceStart,
|
|
|
sliceEnd,
|
|
|
+ sliceSecondaryName,
|
|
|
onMouseEnter,
|
|
|
}: {
|
|
|
onMouseEnter: () => void;
|
|
|
sliceEnd: number;
|
|
|
sliceName: string | null;
|
|
|
+ sliceSecondaryName: string | null;
|
|
|
sliceStart: number;
|
|
|
theme: Theme;
|
|
|
trace: TraceResult<Field>;
|
|
@@ -131,7 +140,10 @@ export function SpanBreakdownSliceRenderer({
|
|
|
if (sliceDuration <= 0) {
|
|
|
return null;
|
|
|
}
|
|
|
- const sliceColor = sliceName ? pickBarColor(sliceName) : theme.gray100;
|
|
|
+
|
|
|
+ const stylingSliceName = getStylingSliceName(sliceName, sliceSecondaryName);
|
|
|
+ const sliceColor = stylingSliceName ? pickBarColor(stylingSliceName) : theme.gray100;
|
|
|
+
|
|
|
const sliceWidth =
|
|
|
BREAKDOWN_QUANTIZE_STEP *
|
|
|
Math.ceil(
|
|
@@ -143,7 +155,7 @@ export function SpanBreakdownSliceRenderer({
|
|
|
Math.floor(
|
|
|
((BREAKDOWN_BAR_SIZE / BREAKDOWN_QUANTIZE_STEP) * relativeSliceStart) /
|
|
|
traceDuration
|
|
|
- ); // 150px wide breakdown.
|
|
|
+ );
|
|
|
return (
|
|
|
<BreakdownSlice
|
|
|
sliceName={sliceName}
|
|
@@ -156,7 +168,15 @@ export function SpanBreakdownSliceRenderer({
|
|
|
<div>
|
|
|
<FlexContainer>
|
|
|
{sliceName ? <ProjectRenderer projectSlug={sliceName} hideName /> : null}
|
|
|
- <div>{sliceName}</div>
|
|
|
+ <strong>{sliceName}</strong>
|
|
|
+
|
|
|
+ {sliceSecondaryName ? (
|
|
|
+ <span>
|
|
|
+ {'\u2014'}
|
|
|
+
|
|
|
+ {sliceSecondaryName}
|
|
|
+ </span>
|
|
|
+ ) : null}
|
|
|
</FlexContainer>
|
|
|
<div>
|
|
|
<PerformanceDuration milliseconds={sliceDuration} abbreviation />
|
|
@@ -165,7 +185,7 @@ export function SpanBreakdownSliceRenderer({
|
|
|
}
|
|
|
containerDisplayMode="block"
|
|
|
>
|
|
|
- <RectangleTraceBreakdown sliceColor={sliceColor} sliceName={sliceName} />
|
|
|
+ <RectangleTraceBreakdown sliceColor={sliceColor} sliceName={stylingSliceName} />
|
|
|
</Tooltip>
|
|
|
</BreakdownSlice>
|
|
|
);
|
|
@@ -249,7 +269,11 @@ export function TraceIdRenderer({
|
|
|
transactionId
|
|
|
);
|
|
|
|
|
|
- return <Link to={target}>{getShortEventId(traceId)}</Link>;
|
|
|
+ return (
|
|
|
+ <Link to={target} style={{minWidth: '66px', textAlign: 'right'}}>
|
|
|
+ {getShortEventId(traceId)}
|
|
|
+ </Link>
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
interface TransactionRendererProps {
|
|
@@ -283,6 +307,8 @@ export function TraceIssuesRenderer({trace}: {trace: TraceResult<Field>}) {
|
|
|
|
|
|
const issueCount = trace.numErrors + trace.numOccurrences;
|
|
|
|
|
|
+ const issueText = issueCount >= 100 ? '99+' : issueCount === 0 ? '\u2014' : issueCount;
|
|
|
+
|
|
|
return (
|
|
|
<LinkButton
|
|
|
to={normalizeUrl({
|
|
@@ -293,18 +319,27 @@ export function TraceIssuesRenderer({trace}: {trace: TraceResult<Field>}) {
|
|
|
})}
|
|
|
size="xs"
|
|
|
icon={<IconIssues size="xs" />}
|
|
|
- style={{minHeight: '20px', height: '20px'}}
|
|
|
+ disabled={issueCount === 0}
|
|
|
+ style={{minHeight: '24px', height: '24px', minWidth: '44px'}}
|
|
|
>
|
|
|
- {issueCount !== undefined ? (
|
|
|
- issueCount
|
|
|
- ) : (
|
|
|
- <LoadingIndicator
|
|
|
- size={12}
|
|
|
- mini
|
|
|
- style={{height: '12px', width: '12px', margin: 0, marginRight: 0}}
|
|
|
- />
|
|
|
- )}
|
|
|
- {issueCount === 100 && '+'}
|
|
|
+ {issueText}
|
|
|
</LinkButton>
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+export function SpanTimeRenderer({
|
|
|
+ timestamp,
|
|
|
+ tooltipShowSeconds,
|
|
|
+}: {
|
|
|
+ timestamp: number;
|
|
|
+ tooltipShowSeconds?: boolean;
|
|
|
+}) {
|
|
|
+ const date = new Date(timestamp);
|
|
|
+ return (
|
|
|
+ <TimeSince
|
|
|
+ unitStyle="extraShort"
|
|
|
+ date={date}
|
|
|
+ tooltipShowSeconds={tooltipShowSeconds}
|
|
|
+ />
|
|
|
+ );
|
|
|
+}
|