Browse Source

ref(perf): Add browser to transaction details (#44258)

### Summary
This adds the browser to the context at the top of transaction details
along with it's icon so it's more noticeable.

Only appears if applicable for that transaction.

### Screenshots
![Screen Shot 2023-02-07 at 4 06 10
PM](https://user-images.githubusercontent.com/6111995/217365740-7604b2d3-0322-4d96-bdd8-03807f899ec0.png)
Kev 2 years ago
parent
commit
105832a5f8

+ 7 - 0
static/app/types/event.tsx

@@ -583,9 +583,15 @@ export interface ProfileContext {
   [ProfileContextKey.PROFILE_ID]?: string;
 }
 
+export interface BrowserContext {
+  name: string;
+  version: string;
+}
+
 type EventContexts = {
   'Memory Info'?: MemoryInfoContext;
   'ThreadPool Info'?: ThreadPoolInfoContext;
+  browser?: BrowserContext;
   client_os?: OSContext;
   device?: DeviceContext;
   feedback?: Record<string, any>;
@@ -704,6 +710,7 @@ interface EventBase {
 }
 
 interface TraceEventContexts extends EventContexts {
+  browser?: BrowserContext;
   profile?: ProfileContext;
 }
 

+ 43 - 2
static/app/views/performance/transactionDetails/eventMetas.tsx

@@ -5,6 +5,8 @@ import {Location} from 'history';
 import {Button} from 'sentry/components/button';
 import Clipboard from 'sentry/components/clipboard';
 import DateTime from 'sentry/components/dateTime';
+import ContextIcon from 'sentry/components/events/contextSummary/contextIcon';
+import {generateIconName} from 'sentry/components/events/contextSummary/utils';
 import ProjectBadge from 'sentry/components/idBadge/projectBadge';
 import TimeSince from 'sentry/components/timeSince';
 import {Tooltip} from 'sentry/components/tooltip';
@@ -169,6 +171,14 @@ class EventMetas extends Component<Props, State> {
                   subtext={httpStatus}
                 />
               )}
+              {isTransaction(event) && event.contexts.browser && (
+                <MetaData
+                  headingText={t('Browser')}
+                  tooltipText={t('The browser used in this transaction.')}
+                  bodyText={<BrowserDisplay event={event} />}
+                  subtext={event.contexts.browser?.version}
+                />
+              )}
               {hasReplay && (
                 <ReplayButtonContainer>
                   <Button href="#breadcrumbs" size="sm" icon={<IconPlay size="xs" />}>
@@ -196,6 +206,37 @@ class EventMetas extends Component<Props, State> {
   }
 }
 
+const BrowserCenter = styled('span')`
+  display: flex;
+  align-items: flex-start;
+  gap: ${space(1)};
+`;
+
+const IconContainer = styled('div')`
+  width: 20px;
+  height: 20px;
+  display: flex;
+  flex-shrink: 0;
+  align-items: center;
+  justify-content: center;
+  margin-top: ${space(0.25)};
+`;
+
+const BrowserDisplay = ({event}: {event: Event}) => {
+  const icon = generateIconName(
+    event.contexts.browser?.name,
+    event.contexts.browser?.version
+  );
+  return (
+    <BrowserCenter>
+      <IconContainer>
+        <ContextIcon name={icon} />
+      </IconContainer>
+      <span>{event.contexts.browser?.name}</span>
+    </BrowserCenter>
+  );
+};
+
 type EventDetailHeaderProps = {
   hasReplay: boolean;
   type?: 'transaction' | 'event';
@@ -204,8 +245,8 @@ type EventDetailHeaderProps = {
 function getEventDetailHeaderCols({hasReplay, type}: EventDetailHeaderProps): string {
   if (type === 'transaction') {
     return hasReplay
-      ? 'grid-template-columns: minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr) 5fr minmax(325px, 1fr);'
-      : 'grid-template-columns: minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr) 6fr;';
+      ? 'grid-template-columns: minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr)  5fr minmax(325px, 1fr);'
+      : 'grid-template-columns: minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr)  6fr;';
   }
   return hasReplay
     ? 'grid-template-columns: minmax(160px, 1fr) minmax(200px, 1fr) 5fr minmax(325px, 1fr);'