customMetricsEventData.spec.tsx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen} from 'sentry-test/reactTestingLibrary';
  3. import {textWithMarkupMatcher} from 'sentry-test/utils';
  4. import type {MetricsSummary} from 'sentry/components/events/interfaces/spans/types';
  5. import type {
  6. MetricsQueryApiResponse,
  7. MetricsQueryApiResponseLastMeta,
  8. } from 'sentry/types/metrics';
  9. import {CustomMetricsEventData} from 'sentry/views/metrics/customMetricsEventData';
  10. const organization = OrganizationFixture({features: ['custom-metrics']});
  11. describe('CustomMetricsEventData', () => {
  12. beforeEach(() => {
  13. MockApiClient.addMockResponse({
  14. url: `/organizations/${organization.slug}/metrics/query/`,
  15. method: 'POST',
  16. body: {
  17. data: [[{by: {}, series: [], totals: 2}]],
  18. meta: [
  19. [
  20. {
  21. unit: 'nanoseconds',
  22. scaling_factor: 1000000,
  23. group_bys: {},
  24. limit: null,
  25. order: 'asc',
  26. } as MetricsQueryApiResponseLastMeta,
  27. ],
  28. ],
  29. end: '2023-09-01T01:00:00Z',
  30. intervals: [],
  31. start: '2023-09-01T00:00:00Z',
  32. } satisfies MetricsQueryApiResponse,
  33. });
  34. });
  35. it('renders empty (no feature flag)', () => {
  36. const metricsSummary: MetricsSummary = {
  37. 'd:custom/my.metric@second': [
  38. {
  39. count: 2,
  40. min: 1,
  41. max: 2,
  42. sum: 3,
  43. tags: {
  44. foo: 'bar',
  45. },
  46. },
  47. ],
  48. };
  49. const {container} = render(
  50. <CustomMetricsEventData
  51. metricsSummary={metricsSummary}
  52. startTimestamp={1706189398.176}
  53. projectId="1"
  54. />
  55. );
  56. expect(container).toBeEmptyDOMElement();
  57. });
  58. it('renders empty (no data)', () => {
  59. const {container} = render(
  60. <CustomMetricsEventData
  61. metricsSummary={{}}
  62. startTimestamp={1706189398.176}
  63. projectId="1"
  64. />,
  65. {
  66. organization,
  67. }
  68. );
  69. expect(container).toBeEmptyDOMElement();
  70. });
  71. it('renders (all information)', () => {
  72. const metricsSummary: MetricsSummary = {
  73. 'd:custom/my.metric@second': [
  74. {
  75. count: 2,
  76. min: 1,
  77. max: 2,
  78. sum: 3,
  79. tags: {
  80. foo: 'bar',
  81. },
  82. },
  83. ],
  84. };
  85. render(
  86. <CustomMetricsEventData
  87. metricsSummary={metricsSummary}
  88. startTimestamp={1706189398.176}
  89. projectId="1"
  90. />,
  91. {
  92. organization,
  93. }
  94. );
  95. expect(screen.getByText('Emitted Metrics')).toBeInTheDocument();
  96. expect(screen.getByText('my.metric')).toBeInTheDocument();
  97. expect(screen.getByRole('link', {name: 'View Metric'})).toBeInTheDocument();
  98. expect(screen.getByText(textWithMarkupMatcher(/Value: 1\.5s/))).toBeInTheDocument();
  99. expect(screen.getByText(/Tags: foo:bar/)).toBeInTheDocument();
  100. });
  101. it('renders (counter metric)', () => {
  102. const metricsSummary: MetricsSummary = {
  103. 'c:custom/my.metric@second': [
  104. {
  105. count: 1,
  106. min: 1,
  107. max: 1,
  108. sum: 1,
  109. tags: {
  110. foo: 'bar',
  111. },
  112. },
  113. ],
  114. };
  115. render(
  116. <CustomMetricsEventData
  117. metricsSummary={metricsSummary}
  118. startTimestamp={1706189398.176}
  119. projectId="1"
  120. />,
  121. {organization}
  122. );
  123. expect(screen.getByText('Emitted Metrics')).toBeInTheDocument();
  124. expect(screen.getByText('my.metric')).toBeInTheDocument();
  125. expect(screen.getByRole('link', {name: 'View Metric'})).toBeInTheDocument();
  126. expect(screen.getByText(textWithMarkupMatcher(/Count: 1/))).toBeInTheDocument();
  127. expect(screen.getByText(/Tags: foo:bar/)).toBeInTheDocument();
  128. });
  129. it('renders (no tags)', async () => {
  130. const metricsSummary: MetricsSummary = {
  131. 'c:custom/my.metric@second': [
  132. {
  133. count: 1,
  134. min: 1,
  135. max: 1,
  136. sum: 1,
  137. tags: null,
  138. },
  139. ],
  140. };
  141. render(
  142. <CustomMetricsEventData
  143. metricsSummary={metricsSummary}
  144. startTimestamp={1706189398.176}
  145. projectId="1"
  146. />,
  147. {
  148. organization,
  149. }
  150. );
  151. expect(screen.getByText('Emitted Metrics')).toBeInTheDocument();
  152. expect(screen.getByText('my.metric')).toBeInTheDocument();
  153. expect(screen.getByRole('link', {name: 'View Metric'})).toBeInTheDocument();
  154. expect(screen.getByText(textWithMarkupMatcher(/Count: 1/))).toBeInTheDocument();
  155. expect(
  156. await screen.findByText(textWithMarkupMatcher(/Tags: \(none\)/))
  157. ).toBeInTheDocument();
  158. });
  159. it('renders (empty tags)', async () => {
  160. const metricsSummary: MetricsSummary = {
  161. 'c:custom/my.metric@second': [
  162. {
  163. count: 1,
  164. min: 1,
  165. max: 1,
  166. sum: 1,
  167. tags: {},
  168. },
  169. ],
  170. };
  171. render(
  172. <CustomMetricsEventData
  173. metricsSummary={metricsSummary}
  174. startTimestamp={1706189398.176}
  175. projectId="1"
  176. />,
  177. {
  178. organization,
  179. }
  180. );
  181. expect(screen.getByText('Emitted Metrics')).toBeInTheDocument();
  182. expect(screen.getByText('my.metric')).toBeInTheDocument();
  183. expect(screen.getByRole('link', {name: 'View Metric'})).toBeInTheDocument();
  184. expect(screen.getByText(textWithMarkupMatcher(/Count: 1/))).toBeInTheDocument();
  185. expect(
  186. await screen.findByText(textWithMarkupMatcher(/Tags: \(none\)/))
  187. ).toBeInTheDocument();
  188. });
  189. it('renders (multiple)', () => {
  190. MockApiClient.addMockResponse({
  191. url: `/organizations/${organization.slug}/metrics/query/`,
  192. method: 'POST',
  193. body: {
  194. data: [
  195. [{by: {}, series: [], totals: 2}],
  196. [{by: {}, series: [], totals: 2}],
  197. [{by: {}, series: [], totals: 2}],
  198. ],
  199. meta: [
  200. [
  201. {
  202. unit: 'nanoseconds',
  203. scaling_factor: 1000000,
  204. group_bys: {},
  205. limit: null,
  206. order: 'asc',
  207. } as MetricsQueryApiResponseLastMeta,
  208. ],
  209. [
  210. {
  211. unit: 'nanoseconds',
  212. scaling_factor: null,
  213. group_bys: {},
  214. limit: null,
  215. order: 'asc',
  216. } as MetricsQueryApiResponseLastMeta,
  217. ],
  218. [
  219. {
  220. unit: 'nanoseconds',
  221. scaling_factor: 1000000,
  222. group_bys: {},
  223. limit: null,
  224. order: 'asc',
  225. } as MetricsQueryApiResponseLastMeta,
  226. ],
  227. ],
  228. end: '2023-09-01T01:00:00Z',
  229. intervals: [],
  230. start: '2023-09-01T00:00:00Z',
  231. } satisfies MetricsQueryApiResponse,
  232. });
  233. const metricsSummary: MetricsSummary = {
  234. 'd:custom/my.distribution@second': [
  235. {
  236. count: 2,
  237. min: 1,
  238. max: 2,
  239. sum: 3,
  240. tags: {
  241. foo: 'bar',
  242. },
  243. },
  244. {
  245. count: 1,
  246. min: 1,
  247. max: 1,
  248. sum: 1,
  249. tags: null,
  250. },
  251. ],
  252. 'c:custom/my.counter@second': [
  253. {
  254. count: 2,
  255. min: 1,
  256. max: 2,
  257. sum: 3,
  258. tags: {
  259. foo: 'bar',
  260. },
  261. },
  262. ],
  263. };
  264. render(
  265. <CustomMetricsEventData
  266. metricsSummary={metricsSummary}
  267. startTimestamp={1706189398.176}
  268. projectId="1"
  269. />,
  270. {
  271. organization,
  272. }
  273. );
  274. expect(screen.getByText('Emitted Metrics')).toBeInTheDocument();
  275. expect(screen.getByText('my.counter')).toBeInTheDocument();
  276. expect(screen.getAllByText('my.distribution')).toHaveLength(2);
  277. expect(screen.getAllByRole('link', {name: 'View Metric'})).toHaveLength(3);
  278. });
  279. });