Browse Source

feat(spans): Dynamically recalculate ops breakdown based on current filters (#26020)

Alberto Leal 3 years ago
parent
commit
b8f9e05c3e

+ 8 - 1
static/app/components/events/interfaces/spans/header.tsx

@@ -28,6 +28,7 @@ import {
 import * as CursorGuideHandler from './cursorGuideHandler';
 import * as DividerHandlerManager from './dividerHandlerManager';
 import {DragManagerChildrenProps} from './dragManager';
+import {ActiveOperationFilter} from './filter';
 import MeasurementsPanel from './measurementsPanel';
 import * as ScrollbarManager from './scrollbarManager';
 import {
@@ -51,6 +52,7 @@ type PropType = {
   dragProps: DragManagerChildrenProps;
   trace: ParsedTraceType;
   event: EventTransaction;
+  operationNameFilters: ActiveOperationFilter;
 };
 
 type State = {
@@ -419,7 +421,12 @@ class TraceViewHeader extends React.Component<PropType, State> {
                   }}
                 >
                   {this.props.event && (
-                    <OpsBreakdown event={this.props.event} topN={3} hideHeader />
+                    <OpsBreakdown
+                      operationNameFilters={this.props.operationNameFilters}
+                      event={this.props.event}
+                      topN={3}
+                      hideHeader
+                    />
                   )}
                 </OperationsBreakdown>
                 <DividerSpacer

+ 1 - 0
static/app/components/events/interfaces/spans/traceView.tsx

@@ -176,6 +176,7 @@ class TraceView extends PureComponent<Props, State> {
       trace={parsedTrace}
       event={this.props.event}
       virtualScrollBarContainerRef={this.virtualScrollBarContainerRef}
+      operationNameFilters={this.props.operationNameFilters}
     />
   );
 

+ 28 - 11
static/app/components/events/opsBreakdown.tsx

@@ -3,11 +3,13 @@ import styled from '@emotion/styled';
 import isFinite from 'lodash/isFinite';
 
 import {SectionHeading} from 'app/components/charts/styles';
+import {ActiveOperationFilter} from 'app/components/events/interfaces/spans/filter';
 import {
   RawSpanType,
   SpanEntry,
   TraceContextType,
 } from 'app/components/events/interfaces/spans/types';
+import {getSpanOperation} from 'app/components/events/interfaces/spans/utils';
 import {pickBarColour} from 'app/components/performance/waterfall/utils';
 import QuestionTooltip from 'app/components/questionTooltip';
 import {t} from 'app/locale';
@@ -46,6 +48,7 @@ type DefaultProps = {
 };
 
 type Props = DefaultProps & {
+  operationNameFilters: ActiveOperationFilter;
   event: Event;
 };
 
@@ -66,7 +69,7 @@ class OpsBreakdown extends Component<Props> {
   }
 
   generateStats(): OpBreakdownType {
-    const {topN} = this.props;
+    const {topN, operationNameFilters} = this.props;
     const event = this.getTransactionEvent();
 
     if (!event) {
@@ -85,20 +88,34 @@ class OpsBreakdown extends Component<Props> {
 
     let spans: RawSpanType[] = spanEntry?.data ?? [];
 
+    const rootSpan = {
+      op: traceContext.op,
+      timestamp: event.endTimestamp,
+      start_timestamp: event.startTimestamp,
+      trace_id: traceContext.trace_id || '',
+      span_id: traceContext.span_id || '',
+      data: {},
+    };
+
     spans =
       spans.length > 0
         ? spans
         : // if there are no descendent spans, then use the transaction root span
-          [
-            {
-              op: traceContext.op,
-              timestamp: event.endTimestamp,
-              start_timestamp: event.startTimestamp,
-              trace_id: traceContext.trace_id || '',
-              span_id: traceContext.span_id || '',
-              data: {},
-            },
-          ];
+          [rootSpan];
+
+    // Filter spans by operation name
+    if (operationNameFilters.type === 'active_filter') {
+      spans = [...spans, rootSpan];
+      spans = spans.filter(span => {
+        const operationName = getSpanOperation(span);
+
+        const shouldFilterOut =
+          typeof operationName === 'string' &&
+          !operationNameFilters.operationNames.has(operationName);
+
+        return !shouldFilterOut;
+      });
+    }
 
     const operationNameIntervals = spans.reduce(
       (intervals: Partial<OperationNameIntervals>, span: RawSpanType) => {

+ 0 - 2
static/app/views/performance/transactionDetails/content.tsx

@@ -10,7 +10,6 @@ import {BorderlessEventEntries} from 'app/components/events/eventEntries';
 import EventMetadata from 'app/components/events/eventMetadata';
 import EventVitals from 'app/components/events/eventVitals';
 import * as SpanEntryContext from 'app/components/events/interfaces/spans/context';
-import OpsBreakdown from 'app/components/events/opsBreakdown';
 import RootSpanStatus from 'app/components/events/rootSpanStatus';
 import FileSize from 'app/components/fileSize';
 import * as Layout from 'app/components/layouts/thirds';
@@ -215,7 +214,6 @@ class EventDetailsContent extends AsyncComponent<Props, State> {
                             projectId={this.projectId}
                           />
                           <RootSpanStatus event={event} />
-                          <OpsBreakdown event={event} />
                         </Fragment>
                       )}
                       <EventVitals event={event} />