nativeV2.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import {useContext} from 'react';
  2. import styled from '@emotion/styled';
  3. import scrollToElement from 'scroll-to-element';
  4. import {TraceEventDataSectionContext} from 'sentry/components/events/traceEventDataSection';
  5. import {t} from 'sentry/locale';
  6. import {DebugMetaActions} from 'sentry/stores/debugMetaStore';
  7. import space from 'sentry/styles/space';
  8. import {Frame} from 'sentry/types';
  9. import DebugImage from '../../debugMeta/debugImage';
  10. import {combineStatus} from '../../debugMeta/utils';
  11. import {SymbolicatorStatus} from '../../types';
  12. import PackageLink from '../packageLink';
  13. import PackageStatus from '../packageStatus';
  14. import Symbol from '../symbol';
  15. import TogglableAddress from '../togglableAddress';
  16. import {getPlatform} from '../utils';
  17. import Expander from './expander';
  18. import LeadHint from './leadHint';
  19. import Wrapper from './wrapper';
  20. type Props = React.ComponentProps<typeof Expander> &
  21. React.ComponentProps<typeof LeadHint> & {
  22. frame: Frame;
  23. isUsedForGrouping: boolean;
  24. image?: React.ComponentProps<typeof DebugImage>['image'];
  25. includeSystemFrames?: boolean;
  26. isFrameAfterLastNonApp?: boolean;
  27. maxLengthOfRelativeAddress?: number;
  28. onClick?: () => void;
  29. onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
  30. prevFrame?: Frame;
  31. };
  32. function Native({
  33. frame,
  34. isFrameAfterLastNonApp,
  35. isExpanded,
  36. isHoverPreviewed,
  37. image,
  38. includeSystemFrames,
  39. maxLengthOfRelativeAddress,
  40. platform,
  41. prevFrame,
  42. isUsedForGrouping,
  43. nextFrame,
  44. leadsToApp,
  45. onMouseDown,
  46. onClick,
  47. ...props
  48. }: Props) {
  49. const traceEventDataSectionContext = useContext(TraceEventDataSectionContext);
  50. if (!traceEventDataSectionContext) {
  51. return null;
  52. }
  53. const {instructionAddr, trust, addrMode, symbolicatorStatus} = frame ?? {};
  54. function packageStatus() {
  55. // this is the status of image that belongs to this frame
  56. if (!image) {
  57. return 'empty';
  58. }
  59. const combinedStatus = combineStatus(image.debug_status, image.unwind_status);
  60. switch (combinedStatus) {
  61. case 'unused':
  62. return 'empty';
  63. case 'found':
  64. return 'success';
  65. default:
  66. return 'error';
  67. }
  68. }
  69. function makeFilter(addr: string): string {
  70. if (!(!addrMode || addrMode === 'abs') && image) {
  71. return `${image.debug_id}!${addr}`;
  72. }
  73. return addr;
  74. }
  75. function scrollToImage(event: React.MouseEvent<HTMLAnchorElement>) {
  76. event.stopPropagation(); // to prevent collapsing if collapsible
  77. if (instructionAddr) {
  78. DebugMetaActions.updateFilter(makeFilter(instructionAddr));
  79. }
  80. scrollToElement('#images-loaded');
  81. }
  82. const shouldShowLinkToImage =
  83. !!symbolicatorStatus &&
  84. symbolicatorStatus !== SymbolicatorStatus.UNKNOWN_IMAGE &&
  85. !isHoverPreviewed;
  86. const isInlineFrame =
  87. prevFrame &&
  88. getPlatform(frame.platform, platform ?? 'other') ===
  89. (prevFrame.platform || platform) &&
  90. instructionAddr === prevFrame.instructionAddr;
  91. const isFoundByStackScanning = trust === 'scan' || trust === 'cfi-scan';
  92. return (
  93. <Wrapper className="title as-table" onMouseDown={onMouseDown} onClick={onClick}>
  94. <NativeLineContent isFrameAfterLastNonApp={!!isFrameAfterLastNonApp}>
  95. <PackageInfo>
  96. <LeadHint
  97. isExpanded={isExpanded}
  98. nextFrame={nextFrame}
  99. leadsToApp={leadsToApp}
  100. />
  101. <PackageLink
  102. includeSystemFrames={!!includeSystemFrames}
  103. withLeadHint={!(isExpanded || !leadsToApp)}
  104. packagePath={frame.package}
  105. onClick={scrollToImage}
  106. isClickable={shouldShowLinkToImage}
  107. isHoverPreviewed={isHoverPreviewed}
  108. >
  109. {!isHoverPreviewed && (
  110. <PackageStatus
  111. status={packageStatus()}
  112. tooltip={t('Go to Images Loaded')}
  113. />
  114. )}
  115. </PackageLink>
  116. </PackageInfo>
  117. {instructionAddr && (
  118. <TogglableAddress
  119. address={instructionAddr}
  120. startingAddress={image ? image.image_addr : null}
  121. isAbsolute={traceEventDataSectionContext.display.includes(
  122. 'absolute-addresses'
  123. )}
  124. isFoundByStackScanning={isFoundByStackScanning}
  125. isInlineFrame={!!isInlineFrame}
  126. relativeAddressMaxlength={maxLengthOfRelativeAddress}
  127. isHoverPreviewed={isHoverPreviewed}
  128. />
  129. )}
  130. <Symbol
  131. frame={frame}
  132. showCompleteFunctionName={traceEventDataSectionContext.display.includes(
  133. 'verbose-function-names'
  134. )}
  135. absoluteFilePaths={traceEventDataSectionContext.display.includes(
  136. 'absolute-file-paths'
  137. )}
  138. isHoverPreviewed={isHoverPreviewed}
  139. isUsedForGrouping={isUsedForGrouping}
  140. nativeStackTraceV2
  141. />
  142. </NativeLineContent>
  143. <Expander
  144. isExpanded={isExpanded}
  145. isHoverPreviewed={isHoverPreviewed}
  146. platform={platform}
  147. {...props}
  148. />
  149. </Wrapper>
  150. );
  151. }
  152. export default Native;
  153. const PackageInfo = styled('span')`
  154. display: grid;
  155. grid-template-columns: auto 1fr;
  156. order: 2;
  157. align-items: flex-start;
  158. @media (min-width: ${props => props.theme.breakpoints.small}) {
  159. order: 0;
  160. }
  161. `;
  162. const NativeLineContent = styled('div')<{isFrameAfterLastNonApp: boolean}>`
  163. display: grid;
  164. flex: 1;
  165. gap: ${space(0.5)};
  166. grid-template-columns: auto 1fr;
  167. align-items: center;
  168. justify-content: flex-start;
  169. @media (min-width: ${props => props.theme.breakpoints.small}) {
  170. grid-template-columns:
  171. ${p => (p.isFrameAfterLastNonApp ? '200px' : '150px')} minmax(117px, auto)
  172. 1fr;
  173. }
  174. @media (min-width: ${props => props.theme.breakpoints.large}) and (max-width: ${props =>
  175. props.theme.breakpoints.xlarge}) {
  176. grid-template-columns:
  177. ${p => (p.isFrameAfterLastNonApp ? '180px' : '140px')} minmax(117px, auto)
  178. 1fr;
  179. }
  180. `;