Browse Source

ref(mep): Add thresholds to allow more null/unparam (#40850)

This allows more unparameterized and null transaction names to show up
in lists when on the processed events side of the landing page etc.

Other:
- Changed the target for some of the widgets when unparam appears.
Kev 2 years ago
parent
commit
8cb38c7157

+ 24 - 8
static/app/utils/performance/contexts/metricsCardinality.tsx

@@ -14,6 +14,9 @@ import MetricsCompatibilitySumsQuery, {
 
 import {createDefinedContext} from './utils';
 
+const UNPARAM_THRESHOLD = 0.01;
+const NULL_THRESHOLD = 0.01;
+
 export interface MetricDataSwitcherOutcome {
   forceTransactionsOnly: boolean;
   compatibleProjects?: number[];
@@ -120,10 +123,9 @@ function getMetricsOutcome(
   const successOutcome: MetricDataSwitcherOutcome = {
     forceTransactionsOnly: false,
   };
-
-  if (organization.features.includes('organizations:performance-mep-bannerless-ui')) {
-    return successOutcome;
-  }
+  const isOnFallbackThresolds = organization.features.includes(
+    'performance-mep-bannerless-ui'
+  );
 
   if (!dataCounts) {
     return fallbackOutcome;
@@ -142,7 +144,7 @@ function getMetricsOutcome(
     return fallbackOutcome;
   }
 
-  if (checkIncompatibleData(dataCounts)) {
+  if (checkIncompatibleData(dataCounts, isOnFallbackThresolds)) {
     return {
       shouldWarnIncompatibleSDK: true,
       forceTransactionsOnly: true,
@@ -158,7 +160,7 @@ function getMetricsOutcome(
     };
   }
 
-  if (checkIfPartialOtherData(dataCounts)) {
+  if (checkIfPartialOtherData(dataCounts, isOnFallbackThresolds)) {
     return {
       shouldNotifyUnnamedTransactions: true,
       compatibleProjects,
@@ -180,8 +182,15 @@ function checkNoDataFallback(dataCounts: MergedMetricsData) {
 /**
  * Fallback and warn if incompatible data found (old specific SDKs).
  */
-function checkIncompatibleData(dataCounts: MergedMetricsData) {
+function checkIncompatibleData(
+  dataCounts: MergedMetricsData,
+  isOnFallbackThresolds: boolean
+) {
   const counts = normalizeCounts(dataCounts);
+  if (isOnFallbackThresolds) {
+    const ratio = counts.nullCount / counts.metricsCount;
+    return ratio > NULL_THRESHOLD;
+  }
   return counts.nullCount > 0;
 }
 
@@ -196,8 +205,15 @@ function checkIfAllOtherData(dataCounts: MergedMetricsData) {
 /**
  * Show metrics but warn about unnamed transactions.
  */
-function checkIfPartialOtherData(dataCounts: MergedMetricsData) {
+function checkIfPartialOtherData(
+  dataCounts: MergedMetricsData,
+  isOnFallbackThresolds: boolean
+) {
   const counts = normalizeCounts(dataCounts);
+  if (isOnFallbackThresolds) {
+    const ratio = counts.unparamCount / counts.metricsCount;
+    return ratio > UNPARAM_THRESHOLD;
+  }
   return counts.unparamCount > 0;
 }
 

+ 8 - 0
static/app/views/performance/landing/metricsDataSwitcherAlert.tsx

@@ -57,6 +57,10 @@ const UNSUPPORTED_TRANSACTION_NAME_DOCS = [
 export function MetricsDataSwitcherAlert(
   props: MetricEnhancedDataAlertProps
 ): React.ReactElement | null {
+  const isOnFallbackThresolds = props.organization.features.includes(
+    'performance-mep-bannerless-ui'
+  );
+
   const handleReviewUpdatesClick = useCallback(() => {
     SidebarPanelStore.activatePanel(SidebarPanelKey.Broadcasts);
   }, []);
@@ -94,6 +98,10 @@ export function MetricsDataSwitcherAlert(
 
   const discoverTarget = createUnnamedTransactionsDiscoverTarget(props);
 
+  if (isOnFallbackThresolds) {
+    return null;
+  }
+
   if (props.shouldWarnIncompatibleSDK) {
     const updateSDK = (
       <Link to="" onClick={handleReviewUpdatesClick}>

+ 14 - 7
static/app/views/performance/landing/widgets/widgets/lineChartListWidget.tsx

@@ -22,6 +22,7 @@ import withApi from 'sentry/utils/withApi';
 import _DurationChart from 'sentry/views/performance/charts/chart';
 import {transactionSummaryRouteWithQuery} from 'sentry/views/performance/transactionSummary/utils';
 import {
+  createUnnamedTransactionsDiscoverTarget,
   getPerformanceDuration,
   UNPARAMETERIZED_TRANSACTION,
 } from 'sentry/views/performance/utils';
@@ -269,13 +270,19 @@ export function LineChartListWidget(props: PerformanceWidgetProps) {
                   additionalQuery.display = 'latency';
                 }
 
-                const transactionTarget = transactionSummaryRouteWithQuery({
-                  orgSlug: props.organization.slug,
-                  projectID: listItem['project.id'] as string,
-                  transaction,
-                  query: props.eventView.getPageFiltersQuery(),
-                  additionalQuery,
-                });
+                const isUnparameterizedRow = transaction === UNPARAMETERIZED_TRANSACTION;
+                const transactionTarget = isUnparameterizedRow
+                  ? createUnnamedTransactionsDiscoverTarget({
+                      organization,
+                      location: props.location,
+                    })
+                  : transactionSummaryRouteWithQuery({
+                      orgSlug: props.organization.slug,
+                      projectID: listItem['project.id'] as string,
+                      transaction,
+                      query: props.eventView.getPageFiltersQuery(),
+                      additionalQuery,
+                    });
 
                 const fieldString = useEvents ? field : getAggregateAlias(field);
 

+ 16 - 7
static/app/views/performance/landing/widgets/widgets/vitalWidget.tsx

@@ -21,7 +21,10 @@ import {VitalData} from 'sentry/utils/performance/vitals/vitalsCardsDiscoverQuer
 import {decodeList} from 'sentry/utils/queryString';
 import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import withApi from 'sentry/utils/withApi';
-import {UNPARAMETERIZED_TRANSACTION} from 'sentry/views/performance/utils';
+import {
+  createUnnamedTransactionsDiscoverTarget,
+  UNPARAMETERIZED_TRANSACTION,
+} from 'sentry/views/performance/utils';
 import {vitalDetailRouteWithQuery} from 'sentry/views/performance/vitalDetail/utils';
 import {_VitalChart} from 'sentry/views/performance/vitalDetail/vitalChart';
 
@@ -293,12 +296,18 @@ export function VitalWidget(props: PerformanceWidgetProps) {
 
                 _eventView.query = initialConditions.formatString();
 
-                const target = vitalDetailRouteWithQuery({
-                  orgSlug: organization.slug,
-                  query: _eventView.generateQueryStringObject(),
-                  vitalName: vital,
-                  projectID: decodeList(location.query.project),
-                });
+                const isUnparameterizedRow = transaction === UNPARAMETERIZED_TRANSACTION;
+                const target = isUnparameterizedRow
+                  ? createUnnamedTransactionsDiscoverTarget({
+                      organization,
+                      location,
+                    })
+                  : vitalDetailRouteWithQuery({
+                      orgSlug: organization.slug,
+                      query: _eventView.generateQueryStringObject(),
+                      vitalName: vital,
+                      projectID: decodeList(location.query.project),
+                    });
 
                 const data = {
                   [settingToVital[props.chartSetting]]: getVitalDataForListItem(