exceptionMechanism.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import {Component} from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import forOwn from 'lodash/forOwn';
  5. import isNil from 'lodash/isNil';
  6. import isObject from 'lodash/isObject';
  7. import Hovercard from 'app/components/hovercard';
  8. import ExternalLink from 'app/components/links/externalLink';
  9. import Pill from 'app/components/pill';
  10. import Pills from 'app/components/pills';
  11. import {IconInfo, IconOpen} from 'app/icons';
  12. import {t} from 'app/locale';
  13. import space from 'app/styles/space';
  14. import {Mechanism} from 'app/types/stacktrace';
  15. import {isUrl} from 'app/utils';
  16. import {Theme} from 'app/utils/theme';
  17. type Props = {
  18. data: Mechanism;
  19. };
  20. class ExceptionMechanism extends Component<Props> {
  21. render() {
  22. const mechanism = this.props.data;
  23. const {type, description, help_link, handled, meta = {}, data = {}} = mechanism;
  24. const {errno, signal, mach_exception} = meta;
  25. const linkElement = help_link && isUrl(help_link) && (
  26. <StyledExternalLink href={help_link}>
  27. <IconOpen size="xs" />
  28. </StyledExternalLink>
  29. );
  30. const descriptionElement = description && (
  31. <Hovercard
  32. header={
  33. <span>
  34. <Details>{t('Details')}</Details> {linkElement}
  35. </span>
  36. }
  37. body={description}
  38. >
  39. <StyledIconInfo size="14px" />
  40. </Hovercard>
  41. );
  42. const pills = [
  43. <Pill key="mechanism" name="mechanism" value={type || 'unknown'}>
  44. {descriptionElement || linkElement}
  45. </Pill>,
  46. ];
  47. if (!isNil(handled)) {
  48. pills.push(<Pill key="handled" name="handled" value={handled} />);
  49. }
  50. if (errno) {
  51. const value = errno.name || errno.number;
  52. pills.push(<Pill key="errno" name="errno" value={value} />);
  53. }
  54. if (mach_exception) {
  55. const value = mach_exception.name || mach_exception.exception;
  56. pills.push(<Pill key="mach" name="mach exception" value={value} />);
  57. }
  58. if (signal) {
  59. const code = signal.code_name || `${t('code')} ${signal.code}`;
  60. const name = signal.name || signal.number;
  61. const value = isNil(signal.code) ? name : `${name} (${code})`;
  62. pills.push(<Pill key="signal" name="signal" value={value} />);
  63. }
  64. forOwn(data, (value, key) => {
  65. if (!isObject(value)) {
  66. pills.push(<Pill key={`data:${key}`} name={key} value={value} />);
  67. }
  68. });
  69. return (
  70. <Wrapper>
  71. <Pills>{pills}</Pills>
  72. </Wrapper>
  73. );
  74. }
  75. }
  76. export default ExceptionMechanism;
  77. const Wrapper = styled('div')`
  78. margin: ${space(2)} 0;
  79. `;
  80. const iconStyle = (p: {theme: Theme}) => css`
  81. transition: 0.1s linear color;
  82. color: ${p.theme.gray300};
  83. :hover {
  84. color: ${p.theme.gray500};
  85. }
  86. `;
  87. const StyledExternalLink = styled(ExternalLink)`
  88. display: inline-flex !important;
  89. ${iconStyle};
  90. `;
  91. const Details = styled('span')`
  92. margin-right: ${space(1)};
  93. `;
  94. const StyledIconInfo = styled(IconInfo)`
  95. display: flex;
  96. ${iconStyle};
  97. `;