metricsDataSwitcher.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import {Fragment, useEffect} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {Location} from 'history';
  5. import LoadingIndicator from 'sentry/components/loadingIndicator';
  6. import {Organization} from 'sentry/types';
  7. import EventView from 'sentry/utils/discover/eventView';
  8. import {
  9. MetricDataSwitcherOutcome,
  10. useMetricsCardinalityContext,
  11. } from 'sentry/utils/performance/contexts/metricsCardinality';
  12. import {
  13. canUseMetricsData,
  14. MEPState,
  15. METRIC_SEARCH_SETTING_PARAM,
  16. } from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
  17. import {decodeScalar} from 'sentry/utils/queryString';
  18. interface MetricDataSwitchProps {
  19. children: (props: MetricDataSwitcherOutcome) => React.ReactNode;
  20. eventView: EventView;
  21. location: Location;
  22. organization: Organization;
  23. hideLoadingIndicator?: boolean;
  24. }
  25. /**
  26. * This component decides based on some stats about current projects whether to show certain views of the landing page.
  27. * It is primarily needed for the rollout during which time users, despite having the flag enabled,
  28. * may or may not have sampling rules, compatible sdk's etc. This can be simplified post rollout.
  29. */
  30. export function MetricsDataSwitcher(props: MetricDataSwitchProps) {
  31. const isUsingMetrics = canUseMetricsData(props.organization);
  32. const metricsCardinality = useMetricsCardinalityContext();
  33. if (!isUsingMetrics) {
  34. return (
  35. <Fragment>
  36. {props.children({
  37. forceTransactionsOnly: true,
  38. })}
  39. </Fragment>
  40. );
  41. }
  42. if (metricsCardinality.isLoading && !props.hideLoadingIndicator) {
  43. return (
  44. <Fragment>
  45. <LoadingContainer>
  46. <LoadingIndicator />
  47. </LoadingContainer>
  48. </Fragment>
  49. );
  50. }
  51. if (!metricsCardinality.outcome) {
  52. return (
  53. <Fragment>
  54. {props.children({
  55. forceTransactionsOnly: true,
  56. })}
  57. </Fragment>
  58. );
  59. }
  60. return (
  61. <Fragment>
  62. <MetricsSwitchHandler
  63. eventView={props.eventView}
  64. location={props.location}
  65. outcome={metricsCardinality.outcome}
  66. switcherChildren={props.children}
  67. />
  68. </Fragment>
  69. );
  70. }
  71. interface SwitcherHandlerProps {
  72. eventView: EventView;
  73. location: Location;
  74. outcome: MetricDataSwitcherOutcome;
  75. switcherChildren: MetricDataSwitchProps['children'];
  76. }
  77. function MetricsSwitchHandler({
  78. switcherChildren,
  79. outcome,
  80. location,
  81. eventView,
  82. }: SwitcherHandlerProps) {
  83. const {query} = location;
  84. const mepSearchState = decodeScalar(query[METRIC_SEARCH_SETTING_PARAM], '');
  85. const hasQuery = decodeScalar(query.query, '');
  86. const queryIsTransactionsBased = mepSearchState === MEPState.transactionsOnly;
  87. const shouldAdjustQuery =
  88. hasQuery && queryIsTransactionsBased && !outcome.forceTransactionsOnly;
  89. useEffect(() => {
  90. if (shouldAdjustQuery) {
  91. browserHistory.push({
  92. pathname: location.pathname,
  93. query: {
  94. ...location.query,
  95. cursor: undefined,
  96. query: undefined,
  97. [METRIC_SEARCH_SETTING_PARAM]: undefined,
  98. },
  99. });
  100. }
  101. }, [shouldAdjustQuery, location]);
  102. if (hasQuery && queryIsTransactionsBased && !outcome.forceTransactionsOnly) {
  103. eventView.query = ''; // TODO: Create switcher provider and move it to the route level to remove the need for this.
  104. }
  105. return <Fragment>{switcherChildren(outcome)}</Fragment>;
  106. }
  107. const LoadingContainer = styled('div')`
  108. display: flex;
  109. justify-content: center;
  110. `;