Browse Source

ref(breadcrumbs): Replace getMeta (proxy) with _meta object - [TET-144] (#37105)

Priscila Oliveira 2 years ago
parent
commit
e43e01626a

+ 24 - 19
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/default.tsx

@@ -1,10 +1,10 @@
 import AnnotatedText from 'sentry/components/events/meta/annotatedText';
-import {getMeta} from 'sentry/components/events/meta/metaProxy';
 import Highlight from 'sentry/components/highlight';
 import Link from 'sentry/components/links/link';
 import {Organization, Project} from 'sentry/types';
 import {BreadcrumbTypeDefault, BreadcrumbTypeNavigation} from 'sentry/types/breadcrumbs';
 import {Event} from 'sentry/types/event';
+import {defined} from 'sentry/utils';
 import {generateEventSlug} from 'sentry/utils/discover/urls';
 import {getTransactionDetailsUrl} from 'sentry/utils/performance/urls';
 import withProjects from 'sentry/utils/withProjects';
@@ -17,33 +17,38 @@ type Props = {
   searchTerm: string;
   event?: Event;
   linkedEvent?: React.ReactElement;
+  meta?: Record<any, any>;
 };
 
-function Default({breadcrumb, event, orgSlug, searchTerm, linkedEvent}: Props) {
-  const {message} = breadcrumb;
+export function Default({
+  meta,
+  breadcrumb,
+  event,
+  orgSlug,
+  searchTerm,
+  linkedEvent,
+}: Props) {
+  const {message, data} = breadcrumb;
   return (
-    <Summary kvData={breadcrumb.data}>
+    <Summary kvData={data} meta={meta}>
       {linkedEvent}
-      {message && (
-        <AnnotatedText
-          value={
-            <FormatMessage
-              searchTerm={searchTerm}
-              event={event}
-              orgSlug={orgSlug}
-              breadcrumb={breadcrumb}
-              message={message}
-            />
-          }
-          meta={getMeta(breadcrumb, 'message')}
-        />
+      {meta?.message?.[''] ? (
+        <AnnotatedText value={message} meta={meta?.message?.['']} />
+      ) : (
+        defined(message) && (
+          <FormatMessage
+            searchTerm={searchTerm}
+            event={event}
+            orgSlug={orgSlug}
+            breadcrumb={breadcrumb}
+            message={message}
+          />
+        )
       )}
     </Summary>
   );
 }
 
-export default Default;
-
 function isEventId(maybeEventId: string): boolean {
   // maybeEventId is an event id if it's a hex string of 32 characters long
   return /^[a-fA-F0-9]{32}$/.test(maybeEventId);

+ 23 - 29
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/exception.tsx

@@ -1,7 +1,6 @@
 import omit from 'lodash/omit';
 
 import AnnotatedText from 'sentry/components/events/meta/annotatedText';
-import {getMeta} from 'sentry/components/events/meta/metaProxy';
 import Highlight from 'sentry/components/highlight';
 import {BreadcrumbTypeDefault} from 'sentry/types/breadcrumbs';
 import {defined} from 'sentry/utils';
@@ -12,43 +11,38 @@ type Props = {
   breadcrumb: BreadcrumbTypeDefault;
   searchTerm: string;
   linkedEvent?: React.ReactElement;
+  meta?: Record<any, any>;
 };
 
-function Exception({breadcrumb, searchTerm, linkedEvent}: Props) {
+export function Exception({breadcrumb, searchTerm, meta, linkedEvent}: Props) {
   const {data, message} = breadcrumb;
-  const dataValue = data?.value;
 
   return (
-    <Summary kvData={omit(data, ['type', 'value'])}>
+    <Summary kvData={!data ? data : omit(data, ['type', 'value'])} meta={meta}>
       {linkedEvent}
-      {data?.type && (
-        <AnnotatedText
-          value={
-            <strong>
-              <Highlight text={searchTerm}>{`${data.type}: `}</Highlight>
-            </strong>
-          }
-          meta={getMeta(data, 'type')}
-        />
+      {meta?.type?.[''] ? (
+        <AnnotatedText value={data?.type} meta={meta?.type?.['']} />
+      ) : (
+        defined(data?.type) && (
+          <strong>
+            <Highlight text={searchTerm}>{`${data?.type}: `}</Highlight>
+          </strong>
+        )
       )}
-      {defined(dataValue) && (
-        <AnnotatedText
-          value={
-            <Highlight text={searchTerm}>
-              {breadcrumb?.message ? `${dataValue}. ` : dataValue}
-            </Highlight>
-          }
-          meta={getMeta(data, 'value')}
-        />
+      {meta?.data?.value?.[''] ? (
+        <AnnotatedText value={data?.value} meta={meta?.data?.value?.['']} />
+      ) : (
+        defined(data?.value) && (
+          <Highlight text={searchTerm}>
+            {breadcrumb?.message ? `${data?.value}. ` : data?.value}
+          </Highlight>
+        )
       )}
-      {message && (
-        <AnnotatedText
-          value={<Highlight text={searchTerm}>{message}</Highlight>}
-          meta={getMeta(breadcrumb, 'message')}
-        />
+      {meta?.message?.[''] ? (
+        <AnnotatedText value={message} meta={meta?.message?.['']} />
+      ) : (
+        defined(message) && <Highlight text={searchTerm}>{message}</Highlight>
       )}
     </Summary>
   );
 }
-
-export default Exception;

+ 27 - 28
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/http.tsx

@@ -1,7 +1,6 @@
 import omit from 'lodash/omit';
 
 import AnnotatedText from 'sentry/components/events/meta/annotatedText';
-import {getMeta} from 'sentry/components/events/meta/metaProxy';
 import Highlight from 'sentry/components/highlight';
 import ExternalLink from 'sentry/components/links/externalLink';
 import {t} from 'sentry/locale';
@@ -14,9 +13,10 @@ type Props = {
   breadcrumb: BreadcrumbTypeHTTP;
   searchTerm: string;
   linkedEvent?: React.ReactElement;
+  meta?: Record<any, any>;
 };
 
-function Http({breadcrumb, searchTerm, linkedEvent}: Props) {
+export function Http({breadcrumb, searchTerm, meta, linkedEvent}: Props) {
   const {data} = breadcrumb;
 
   const renderUrl = (url: any) => {
@@ -38,37 +38,36 @@ function Http({breadcrumb, searchTerm, linkedEvent}: Props) {
     }
   };
 
-  const statusCode = data?.status_code;
-
   return (
-    <Summary kvData={omit(data, ['method', 'url', 'status_code'])}>
+    <Summary
+      kvData={!data ? data : omit(data, ['method', 'url', 'status_code'])}
+      meta={meta}
+    >
       {linkedEvent}
-      {data?.method && (
-        <AnnotatedText
-          value={
-            <strong>
-              <Highlight text={searchTerm}>{`${data.method} `}</Highlight>
-            </strong>
-          }
-          meta={getMeta(data, 'method')}
-        />
+      {meta?.data?.method?.[''] ? (
+        <AnnotatedText value={data?.method} meta={meta?.data?.method?.['']} />
+      ) : (
+        defined(data?.method) && (
+          <strong>
+            <Highlight text={searchTerm}>{`${data?.method} `}</Highlight>
+          </strong>
+        )
       )}
-      {data?.url && (
-        <AnnotatedText value={renderUrl(data.url)} meta={getMeta(data, 'url')} />
+      {meta?.data?.url?.[''] ? (
+        <AnnotatedText value={data?.url} meta={meta?.data?.url?.['']} />
+      ) : (
+        defined(data?.url) && renderUrl(data?.url)
       )}
-      {defined(statusCode) && (
-        <AnnotatedText
-          value={
-            <Highlight
-              data-test-id="http-renderer-status-code"
-              text={searchTerm}
-            >{` [${statusCode}]`}</Highlight>
-          }
-          meta={getMeta(data, 'status_code')}
-        />
+      {meta?.data?.status_code?.[''] ? (
+        <AnnotatedText value={data?.status_code} meta={meta?.data?.status_code?.['']} />
+      ) : (
+        defined(data?.status_code) && (
+          <Highlight
+            data-test-id="http-renderer-status-code"
+            text={searchTerm}
+          >{` [${data?.status_code}]`}</Highlight>
+        )
       )}
     </Summary>
   );
 }
-
-export default Http;

+ 22 - 8
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/index.tsx

@@ -2,19 +2,28 @@ import {Organization} from 'sentry/types';
 import {BreadcrumbType, RawCrumb} from 'sentry/types/breadcrumbs';
 import {Event} from 'sentry/types/event';
 
-import Default from './default';
-import Exception from './exception';
-import Http from './http';
-import LinkedEvent from './linkedEvent';
+import {Default} from './default';
+import {Exception} from './exception';
+import {Http} from './http';
+import {LinkedEvent} from './linkedEvent';
 
 type Props = Pick<React.ComponentProps<typeof LinkedEvent>, 'route' | 'router'> & {
   breadcrumb: RawCrumb;
   event: Event;
   organization: Organization;
   searchTerm: string;
+  meta?: Record<any, any>;
 };
 
-function Data({breadcrumb, event, organization, searchTerm, route, router}: Props) {
+export function Data({
+  breadcrumb,
+  event,
+  organization,
+  searchTerm,
+  meta,
+  route,
+  router,
+}: Props) {
   const orgSlug = organization.slug;
 
   const linkedEvent =
@@ -30,7 +39,12 @@ function Data({breadcrumb, event, organization, searchTerm, route, router}: Prop
 
   if (breadcrumb.type === BreadcrumbType.HTTP) {
     return (
-      <Http breadcrumb={breadcrumb} searchTerm={searchTerm} linkedEvent={linkedEvent} />
+      <Http
+        breadcrumb={breadcrumb}
+        searchTerm={searchTerm}
+        linkedEvent={linkedEvent}
+        meta={meta}
+      />
     );
   }
 
@@ -43,6 +57,7 @@ function Data({breadcrumb, event, organization, searchTerm, route, router}: Prop
         breadcrumb={breadcrumb}
         searchTerm={searchTerm}
         linkedEvent={linkedEvent}
+        meta={meta}
       />
     );
   }
@@ -54,8 +69,7 @@ function Data({breadcrumb, event, organization, searchTerm, route, router}: Prop
       breadcrumb={breadcrumb}
       searchTerm={searchTerm}
       linkedEvent={linkedEvent}
+      meta={meta}
     />
   );
 }
-
-export default Data;

+ 1 - 3
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/linkedEvent.tsx

@@ -31,7 +31,7 @@ const errorMessage = t(
   'An error occurred while fetching the data of the breadcrumb event link'
 );
 
-function LinkedEvent({orgSlug, eventId, route, router}: Props) {
+export function LinkedEvent({orgSlug, eventId, route, router}: Props) {
   const [storedLinkedEvent, setStoredLinkedEvent, removeStoredLinkedEvent] =
     useSessionStorage<undefined | StoredLinkedEvent>(eventId);
 
@@ -124,8 +124,6 @@ function LinkedEvent({orgSlug, eventId, route, router}: Props) {
   );
 }
 
-export default LinkedEvent;
-
 const StyledShortId = styled(ShortId)`
   font-weight: 700;
   display: inline-grid;

+ 15 - 2
static/app/components/events/interfaces/breadcrumbs/breadcrumb/data/summary.tsx

@@ -1,14 +1,27 @@
 import styled from '@emotion/styled';
 
 import ContextData from 'sentry/components/contextData';
+import AnnotatedText from 'sentry/components/events/meta/annotatedText';
 import space from 'sentry/styles/space';
 
 type Props = {
   children: React.ReactNode;
-  kvData?: Record<string, any>;
+  kvData?: Record<string, any> | null;
+  meta?: Record<any, any>;
 };
 
-function Summary({kvData, children}: Props) {
+function Summary({kvData, children, meta}: Props) {
+  if (meta?.data?.['']) {
+    return (
+      <Wrapper>
+        {children && <StyledCode>{children}</StyledCode>}
+        <ContextDataWrapper>
+          <AnnotatedText value={kvData} meta={meta?.data?.['']} />
+        </ContextDataWrapper>
+      </Wrapper>
+    );
+  }
+
   if (!kvData || !Object.keys(kvData).length) {
     if (!children) {
       return <div />;

+ 5 - 4
static/app/components/events/interfaces/breadcrumbs/breadcrumb/index.tsx

@@ -8,7 +8,7 @@ import {BreadcrumbType, Crumb} from 'sentry/types/breadcrumbs';
 import {Event} from 'sentry/types/event';
 
 import Category from './category';
-import Data from './data';
+import {Data} from './data';
 import Level from './level';
 import Time from './time';
 import Type from './type';
@@ -25,9 +25,10 @@ type Props = Pick<React.ComponentProps<typeof Data>, 'route' | 'router'> & {
   searchTerm: string;
   style: React.CSSProperties;
   height?: string;
+  meta?: Record<any, any>;
 };
 
-const Breadcrumb = memo(function Breadcrumb({
+export const Breadcrumb = memo(function Breadcrumb({
   organization,
   event,
   breadcrumb,
@@ -39,6 +40,7 @@ const Breadcrumb = memo(function Breadcrumb({
   style,
   route,
   router,
+  meta,
   ['data-test-id']: dataTestId,
 }: Props) {
   const {type, description, color, level, category, timestamp} = breadcrumb;
@@ -61,6 +63,7 @@ const Breadcrumb = memo(function Breadcrumb({
         searchTerm={searchTerm}
         route={route}
         router={router}
+        meta={meta}
       />
       <div>
         <Level level={level} searchTerm={searchTerm} />
@@ -75,8 +78,6 @@ const Breadcrumb = memo(function Breadcrumb({
   );
 });
 
-export default Breadcrumb;
-
 const Wrapper = styled('div')<{error: boolean; scrollbarSize: number}>`
   display: grid;
   grid-template-columns: 64px 140px 1fr 106px 100px ${p => p.scrollbarSize}px;

+ 6 - 1
static/app/components/events/interfaces/breadcrumbs/breadcrumbs.tsx

@@ -13,9 +13,10 @@ import Tooltip from 'sentry/components/tooltip';
 import {IconSort} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import space from 'sentry/styles/space';
+import {EntryType} from 'sentry/types';
 import {Crumb} from 'sentry/types/breadcrumbs';
 
-import Breadcrumb from './breadcrumb';
+import {Breadcrumb} from './breadcrumb';
 
 const PANEL_MAX_HEIGHT = 400;
 
@@ -56,6 +57,9 @@ function Breadcrumbs({
 }: Props) {
   const [scrollToIndex, setScrollToIndex] = useState<number | undefined>(undefined);
   const [scrollbarSize, setScrollbarSize] = useState(0);
+  const breadcrumbEntryIndex = event.entries.findIndex(
+    entry => entry.type === EntryType.BREADCRUMBS
+  );
 
   let listRef: List | null = null;
   const contentRef = useRef<HTMLDivElement>(null);
@@ -106,6 +110,7 @@ function Breadcrumbs({
             organization={organization}
             searchTerm={searchTerm}
             breadcrumb={breadcrumb}
+            meta={event._meta?.entries?.[breadcrumbEntryIndex]?.data?.values?.[index]}
             event={event}
             relativeTime={relativeTime}
             displayRelativeTime={displayRelativeTime}

+ 3 - 3
static/app/types/breadcrumbs.tsx

@@ -52,7 +52,7 @@ export type BreadcrumbTypeSession = {
 
 export type BreadcrumbTypeNavigation = {
   type: BreadcrumbType.NAVIGATION;
-  data?: {
+  data?: null | {
     from?: string;
     to?: string;
   };
@@ -60,7 +60,7 @@ export type BreadcrumbTypeNavigation = {
 
 export type BreadcrumbTypeHTTP = {
   type: BreadcrumbType.HTTP;
-  data?: {
+  data?: null | {
     method?:
       | 'POST'
       | 'PUT'
@@ -92,7 +92,7 @@ export type BreadcrumbTypeDefault = {
     | BreadcrumbType.SESSION
     | BreadcrumbType.SYSTEM
     | BreadcrumbType.TRANSACTION;
-  data?: Record<string, any>;
+  data?: Record<string, any> | null;
 } & BreadcrumbTypeBase;
 
 export type RawCrumb =

+ 85 - 0
tests/js/spec/components/events/interfaces/breadcrumbs/breadcrumb/data/default.spec.tsx

@@ -0,0 +1,85 @@
+import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
+
+import {Default} from 'sentry/components/events/interfaces/breadcrumbs/breadcrumb/data/default';
+import {BreadcrumbLevelType, BreadcrumbType} from 'sentry/types/breadcrumbs';
+
+describe('Breadcrumb Data Default', function () {
+  it('display redacted message', async function () {
+    render(
+      <Default
+        meta={{
+          message: {
+            '': {
+              rem: [['project:1', 's', 0, 0]],
+              len: 19,
+              chunks: [
+                {
+                  type: 'redaction',
+                  text: '',
+                  rule_id: 'project:1',
+                  remark: 's',
+                },
+              ],
+            },
+          },
+        }}
+        event={TestStubs.Event()}
+        orgSlug="org-slug"
+        searchTerm=""
+        breadcrumb={{
+          type: BreadcrumbType.DEBUG,
+          timestamp: '2017-08-04T07:52:11Z',
+          level: BreadcrumbLevelType.INFO,
+          message: '',
+          category: 'started',
+          data: {
+            controller: '<sentry_ios_cocoapods.ViewController: 0x100e09ec0>',
+          },
+          event_id: null,
+        }}
+      />
+    );
+
+    expect(
+      screen.getByText('<sentry_ios_cocoapods.ViewController: 0x100e09ec0>')
+    ).toBeInTheDocument();
+    userEvent.hover(screen.getByText(/redacted/));
+    expect(
+      await screen.findByText('Replaced because of PII rule "project:1"')
+    ).toBeInTheDocument(); // tooltip description
+  });
+
+  it('display redacted data', async function () {
+    render(
+      <Default
+        meta={{
+          data: {
+            '': {
+              rem: [['project:2', 'x']],
+            },
+          },
+        }}
+        event={TestStubs.Event()}
+        orgSlug="org-slug"
+        searchTerm=""
+        breadcrumb={{
+          type: BreadcrumbType.DEBUG,
+          timestamp: '2017-08-04T07:52:11Z',
+          level: BreadcrumbLevelType.INFO,
+          message: '',
+          category: 'started',
+          data: null,
+          event_id: null,
+        }}
+      />
+    );
+
+    expect(
+      screen.queryByText('<sentry_ios_cocoapods.ViewController: 0x100e09ec0>')
+    ).not.toBeInTheDocument();
+    userEvent.hover(screen.getByText(/redacted/));
+    expect(
+      await screen.findByText('Removed because of PII rule "project:2"')
+    ).toBeInTheDocument(); // tooltip description
+  });
+});

Some files were not shown because too many files changed in this diff