|
@@ -1,4 +1,3 @@
|
|
|
-import {Component} from 'react';
|
|
|
import styled from '@emotion/styled';
|
|
|
import isFinite from 'lodash/isFinite';
|
|
|
|
|
@@ -13,7 +12,7 @@ import {pickBarColor} from 'sentry/components/performance/waterfall/utils';
|
|
|
import QuestionTooltip from 'sentry/components/questionTooltip';
|
|
|
import {t} from 'sentry/locale';
|
|
|
import {space} from 'sentry/styles/space';
|
|
|
-import {EntrySpans, EntryType, Event, EventTransaction} from 'sentry/types/event';
|
|
|
+import {EntrySpans, EntryType, Event} from 'sentry/types/event';
|
|
|
|
|
|
type StartTimestamp = number;
|
|
|
type EndTimestamp = number;
|
|
@@ -41,47 +40,33 @@ const TOP_N_SPANS = 4;
|
|
|
|
|
|
type OpBreakdownType = OpStats[];
|
|
|
|
|
|
-type DefaultProps = {
|
|
|
- hideHeader: boolean;
|
|
|
- topN: number;
|
|
|
-};
|
|
|
-
|
|
|
-type Props = DefaultProps & {
|
|
|
+type Props = {
|
|
|
event: Event;
|
|
|
operationNameFilters: ActiveOperationFilter;
|
|
|
+ hideHeader?: boolean;
|
|
|
+ topN?: number;
|
|
|
};
|
|
|
|
|
|
-class OpsBreakdown extends Component<Props> {
|
|
|
- static defaultProps: DefaultProps = {
|
|
|
- topN: TOP_N_SPANS,
|
|
|
- hideHeader: false,
|
|
|
- };
|
|
|
-
|
|
|
- getTransactionEvent(): EventTransaction | undefined {
|
|
|
- const {event} = this.props;
|
|
|
-
|
|
|
- if (event.type === 'transaction') {
|
|
|
- return event as EventTransaction;
|
|
|
- }
|
|
|
-
|
|
|
- return undefined;
|
|
|
- }
|
|
|
-
|
|
|
- generateStats(): OpBreakdownType {
|
|
|
- const {topN, operationNameFilters} = this.props;
|
|
|
- const event = this.getTransactionEvent();
|
|
|
+function OpsBreakdown({
|
|
|
+ event,
|
|
|
+ operationNameFilters,
|
|
|
+ hideHeader = false,
|
|
|
+ topN = TOP_N_SPANS,
|
|
|
+}: Props) {
|
|
|
+ const transactionEvent = event.type === 'transaction' ? event : undefined;
|
|
|
|
|
|
- if (!event) {
|
|
|
+ function generateStats(): OpBreakdownType {
|
|
|
+ if (!transactionEvent) {
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
- const traceContext: TraceContextType | undefined = event?.contexts?.trace;
|
|
|
+ const traceContext: TraceContextType | undefined = transactionEvent?.contexts?.trace;
|
|
|
|
|
|
if (!traceContext) {
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
- const spanEntry = event.entries.find(
|
|
|
+ const spanEntry = transactionEvent.entries.find(
|
|
|
(entry: EntrySpans | any): entry is EntrySpans => {
|
|
|
return entry.type === EntryType.SPANS;
|
|
|
}
|
|
@@ -91,8 +76,8 @@ class OpsBreakdown extends Component<Props> {
|
|
|
|
|
|
const rootSpan = {
|
|
|
op: traceContext.op,
|
|
|
- timestamp: event.endTimestamp,
|
|
|
- start_timestamp: event.startTimestamp,
|
|
|
+ timestamp: transactionEvent.endTimestamp,
|
|
|
+ start_timestamp: transactionEvent.startTimestamp,
|
|
|
trace_id: traceContext.trace_id || '',
|
|
|
span_id: traceContext.span_id || '',
|
|
|
data: {},
|
|
@@ -242,62 +227,56 @@ class OpsBreakdown extends Component<Props> {
|
|
|
return breakdown;
|
|
|
}
|
|
|
|
|
|
- render() {
|
|
|
- const {hideHeader} = this.props;
|
|
|
-
|
|
|
- const event = this.getTransactionEvent();
|
|
|
-
|
|
|
- if (!event) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- const breakdown = this.generateStats();
|
|
|
-
|
|
|
- const contents = breakdown.map(currOp => {
|
|
|
- const {name, percentage, totalInterval} = currOp;
|
|
|
-
|
|
|
- const isOther = name === OtherOperation;
|
|
|
- const operationName = typeof name === 'string' ? name : t('Other');
|
|
|
-
|
|
|
- const durLabel = Math.round(totalInterval * 1000 * 100) / 100;
|
|
|
- const pctLabel = isFinite(percentage) ? Math.round(percentage * 100) : '∞';
|
|
|
- const opsColor: string = pickBarColor(operationName);
|
|
|
-
|
|
|
- return (
|
|
|
- <OpsLine key={operationName}>
|
|
|
- <OpsNameContainer>
|
|
|
- <OpsDot style={{backgroundColor: isOther ? 'transparent' : opsColor}} />
|
|
|
- <OpsName>{operationName}</OpsName>
|
|
|
- </OpsNameContainer>
|
|
|
- <OpsContent>
|
|
|
- <Dur>{durLabel}ms</Dur>
|
|
|
- <Pct>{pctLabel}%</Pct>
|
|
|
- </OpsContent>
|
|
|
- </OpsLine>
|
|
|
- );
|
|
|
- });
|
|
|
+ if (!transactionEvent) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- if (!hideHeader) {
|
|
|
- return (
|
|
|
- <StyledBreakdown>
|
|
|
- <SectionHeading>
|
|
|
- {t('Operation Breakdown')}
|
|
|
- <QuestionTooltip
|
|
|
- position="top"
|
|
|
- size="sm"
|
|
|
- containerDisplayMode="block"
|
|
|
- title={t(
|
|
|
- 'Span durations are summed over the course of an entire transaction. Any overlapping spans are only counted once. Percentages are calculated by dividing the summed span durations by the total of all span durations.'
|
|
|
- )}
|
|
|
- />
|
|
|
- </SectionHeading>
|
|
|
- {contents}
|
|
|
- </StyledBreakdown>
|
|
|
- );
|
|
|
- }
|
|
|
+ const breakdown = generateStats();
|
|
|
+
|
|
|
+ const contents = breakdown.map(currOp => {
|
|
|
+ const {name, percentage, totalInterval} = currOp;
|
|
|
+
|
|
|
+ const isOther = name === OtherOperation;
|
|
|
+ const operationName = typeof name === 'string' ? name : t('Other');
|
|
|
+
|
|
|
+ const durLabel = Math.round(totalInterval * 1000 * 100) / 100;
|
|
|
+ const pctLabel = isFinite(percentage) ? Math.round(percentage * 100) : '∞';
|
|
|
+ const opsColor: string = pickBarColor(operationName);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <OpsLine key={operationName}>
|
|
|
+ <OpsNameContainer>
|
|
|
+ <OpsDot style={{backgroundColor: isOther ? 'transparent' : opsColor}} />
|
|
|
+ <OpsName>{operationName}</OpsName>
|
|
|
+ </OpsNameContainer>
|
|
|
+ <OpsContent>
|
|
|
+ <Dur>{durLabel}ms</Dur>
|
|
|
+ <Pct>{pctLabel}%</Pct>
|
|
|
+ </OpsContent>
|
|
|
+ </OpsLine>
|
|
|
+ );
|
|
|
+ });
|
|
|
|
|
|
- return <StyledBreakdownNoHeader>{contents}</StyledBreakdownNoHeader>;
|
|
|
+ if (!hideHeader) {
|
|
|
+ return (
|
|
|
+ <StyledBreakdown>
|
|
|
+ <SectionHeading>
|
|
|
+ {t('Operation Breakdown')}
|
|
|
+ <QuestionTooltip
|
|
|
+ position="top"
|
|
|
+ size="sm"
|
|
|
+ containerDisplayMode="block"
|
|
|
+ title={t(
|
|
|
+ 'Span durations are summed over the course of an entire transaction. Any overlapping spans are only counted once. Percentages are calculated by dividing the summed span durations by the total of all span durations.'
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ </SectionHeading>
|
|
|
+ {contents}
|
|
|
+ </StyledBreakdown>
|
|
|
+ );
|
|
|
}
|
|
|
+
|
|
|
+ return <StyledBreakdownNoHeader>{contents}</StyledBreakdownNoHeader>;
|
|
|
}
|
|
|
|
|
|
const StyledBreakdown = styled('div')`
|