@kylincloud/flamegraph 0.35.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/CHANGELOG.md +1211 -0
  2. package/LICENSE +202 -0
  3. package/README.md +251 -0
  4. package/dist/FlameGraph/FlameGraphComponent/CheckIcon.d.ts +2 -0
  5. package/dist/FlameGraph/FlameGraphComponent/CheckIcon.d.ts.map +1 -0
  6. package/dist/FlameGraph/FlameGraphComponent/ContextMenu.d.ts +17 -0
  7. package/dist/FlameGraph/FlameGraphComponent/ContextMenu.d.ts.map +1 -0
  8. package/dist/FlameGraph/FlameGraphComponent/ContextMenuHighlight.d.ts +14 -0
  9. package/dist/FlameGraph/FlameGraphComponent/ContextMenuHighlight.d.ts.map +1 -0
  10. package/dist/FlameGraph/FlameGraphComponent/DiffLegend.d.ts +9 -0
  11. package/dist/FlameGraph/FlameGraphComponent/DiffLegend.d.ts.map +1 -0
  12. package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts +8 -0
  13. package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts.map +1 -0
  14. package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts +96 -0
  15. package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts.map +1 -0
  16. package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts +27 -0
  17. package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts.map +1 -0
  18. package/dist/FlameGraph/FlameGraphComponent/GraphVizPane.d.ts +7 -0
  19. package/dist/FlameGraph/FlameGraphComponent/GraphVizPane.d.ts.map +1 -0
  20. package/dist/FlameGraph/FlameGraphComponent/Header.d.ts +12 -0
  21. package/dist/FlameGraph/FlameGraphComponent/Header.d.ts.map +1 -0
  22. package/dist/FlameGraph/FlameGraphComponent/Highlight.d.ts +18 -0
  23. package/dist/FlameGraph/FlameGraphComponent/Highlight.d.ts.map +1 -0
  24. package/dist/FlameGraph/FlameGraphComponent/LogoLink.d.ts +2 -0
  25. package/dist/FlameGraph/FlameGraphComponent/LogoLink.d.ts.map +1 -0
  26. package/dist/FlameGraph/FlameGraphComponent/color.d.ts +20 -0
  27. package/dist/FlameGraph/FlameGraphComponent/color.d.ts.map +1 -0
  28. package/dist/FlameGraph/FlameGraphComponent/colorPalette.d.ts +11 -0
  29. package/dist/FlameGraph/FlameGraphComponent/colorPalette.d.ts.map +1 -0
  30. package/dist/FlameGraph/FlameGraphComponent/constants.d.ts +6 -0
  31. package/dist/FlameGraph/FlameGraphComponent/constants.d.ts.map +1 -0
  32. package/dist/FlameGraph/FlameGraphComponent/index.d.ts +37 -0
  33. package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -0
  34. package/dist/FlameGraph/FlameGraphComponent/murmur3.d.ts +2 -0
  35. package/dist/FlameGraph/FlameGraphComponent/murmur3.d.ts.map +1 -0
  36. package/dist/FlameGraph/FlameGraphComponent/testData.d.ts +53 -0
  37. package/dist/FlameGraph/FlameGraphComponent/testData.d.ts.map +1 -0
  38. package/dist/FlameGraph/FlameGraphComponent/utils.d.ts +6 -0
  39. package/dist/FlameGraph/FlameGraphComponent/utils.d.ts.map +1 -0
  40. package/dist/FlameGraph/FlameGraphComponent/viewTypes.d.ts +2 -0
  41. package/dist/FlameGraph/FlameGraphComponent/viewTypes.d.ts.map +1 -0
  42. package/dist/FlameGraph/FlameGraphRenderer.d.ts +86 -0
  43. package/dist/FlameGraph/FlameGraphRenderer.d.ts.map +1 -0
  44. package/dist/FlameGraph/decode.d.ts +27 -0
  45. package/dist/FlameGraph/decode.d.ts.map +1 -0
  46. package/dist/FlameGraph/normalize.d.ts +6 -0
  47. package/dist/FlameGraph/normalize.d.ts.map +1 -0
  48. package/dist/FlameGraph/uniqueness.d.ts +3 -0
  49. package/dist/FlameGraph/uniqueness.d.ts.map +1 -0
  50. package/dist/FlamegraphRenderer.d.ts +19 -0
  51. package/dist/FlamegraphRenderer.d.ts.map +1 -0
  52. package/dist/Icons.d.ts +9 -0
  53. package/dist/Icons.d.ts.map +1 -0
  54. package/dist/ProfilerTable.d.ts +21 -0
  55. package/dist/ProfilerTable.d.ts.map +1 -0
  56. package/dist/SharedQueryInput.d.ts +10 -0
  57. package/dist/SharedQueryInput.d.ts.map +1 -0
  58. package/dist/Toolbar.d.ts +31 -0
  59. package/dist/Toolbar.d.ts.map +1 -0
  60. package/dist/Tooltip/FlamegraphTooltip.d.ts +59 -0
  61. package/dist/Tooltip/FlamegraphTooltip.d.ts.map +1 -0
  62. package/dist/Tooltip/LeftClickIcon.d.ts +2 -0
  63. package/dist/Tooltip/LeftClickIcon.d.ts.map +1 -0
  64. package/dist/Tooltip/RightClickIcon.d.ts +2 -0
  65. package/dist/Tooltip/RightClickIcon.d.ts.map +1 -0
  66. package/dist/Tooltip/TableTooltip.d.ts +12 -0
  67. package/dist/Tooltip/TableTooltip.d.ts.map +1 -0
  68. package/dist/Tooltip/Tooltip.d.ts +29 -0
  69. package/dist/Tooltip/Tooltip.d.ts.map +1 -0
  70. package/dist/convert/convertJaegerTraceToProfile.d.ts +3 -0
  71. package/dist/convert/convertJaegerTraceToProfile.d.ts.map +1 -0
  72. package/dist/convert/diffTwoProfiles.d.ts +3 -0
  73. package/dist/convert/diffTwoProfiles.d.ts.map +1 -0
  74. package/dist/convert/flamebearersToTree.d.ts +11 -0
  75. package/dist/convert/flamebearersToTree.d.ts.map +1 -0
  76. package/dist/convert/sandwichViewProfiles.d.ts +14 -0
  77. package/dist/convert/sandwichViewProfiles.d.ts.map +1 -0
  78. package/dist/convert/subtract.d.ts +3 -0
  79. package/dist/convert/subtract.d.ts.map +1 -0
  80. package/dist/convert/testData.d.ts +50 -0
  81. package/dist/convert/testData.d.ts.map +1 -0
  82. package/dist/convert/toGraphviz.d.ts +3 -0
  83. package/dist/convert/toGraphviz.d.ts.map +1 -0
  84. package/dist/fitMode/fitMode.d.ts +42 -0
  85. package/dist/fitMode/fitMode.d.ts.map +1 -0
  86. package/dist/format/format.d.ts +42 -0
  87. package/dist/format/format.d.ts.map +1 -0
  88. package/dist/i18n.d.ts +55 -0
  89. package/dist/i18n.d.ts.map +1 -0
  90. package/dist/index.cjs.css +792 -0
  91. package/dist/index.cjs.js +5087 -0
  92. package/dist/index.d.ts +4 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.esm.css +792 -0
  95. package/dist/index.esm.js +5079 -0
  96. package/dist/index.node.d.ts +9 -0
  97. package/dist/index.node.d.ts.map +1 -0
  98. package/dist/logo-v3-small-T5VXIMRR.svg +32 -0
  99. package/dist/models/decode.d.ts +3 -0
  100. package/dist/models/decode.d.ts.map +1 -0
  101. package/dist/models/flamebearer.d.ts +63 -0
  102. package/dist/models/flamebearer.d.ts.map +1 -0
  103. package/dist/models/groups.d.ts +37 -0
  104. package/dist/models/groups.d.ts.map +1 -0
  105. package/dist/models/index.d.ts +8 -0
  106. package/dist/models/index.d.ts.map +1 -0
  107. package/dist/models/profile.d.ts +152 -0
  108. package/dist/models/profile.d.ts.map +1 -0
  109. package/dist/models/spyName.d.ts +8 -0
  110. package/dist/models/spyName.d.ts.map +1 -0
  111. package/dist/models/trace.d.ts +357 -0
  112. package/dist/models/trace.d.ts.map +1 -0
  113. package/dist/models/units.d.ts +6 -0
  114. package/dist/models/units.d.ts.map +1 -0
  115. package/dist/search.d.ts +2 -0
  116. package/dist/search.d.ts.map +1 -0
  117. package/dist/shims/Box.d.ts +38 -0
  118. package/dist/shims/Box.d.ts.map +1 -0
  119. package/dist/shims/Button.d.ts +26 -0
  120. package/dist/shims/Button.d.ts.map +1 -0
  121. package/dist/shims/Dropdown.d.ts +30 -0
  122. package/dist/shims/Dropdown.d.ts.map +1 -0
  123. package/dist/shims/Input.d.ts +19 -0
  124. package/dist/shims/Input.d.ts.map +1 -0
  125. package/dist/shims/LoadingSpinner.d.ts +7 -0
  126. package/dist/shims/LoadingSpinner.d.ts.map +1 -0
  127. package/dist/shims/Menu.d.ts +4 -0
  128. package/dist/shims/Menu.d.ts.map +1 -0
  129. package/dist/shims/NoData.d.ts +2 -0
  130. package/dist/shims/NoData.d.ts.map +1 -0
  131. package/dist/shims/Table.d.ts +52 -0
  132. package/dist/shims/Table.d.ts.map +1 -0
  133. package/dist/shims/Tooltip.d.ts +9 -0
  134. package/dist/shims/Tooltip.d.ts.map +1 -0
  135. package/package.json +84 -0
  136. package/src/FlameGraph/FlameGraphComponent/CheckIcon.tsx +27 -0
  137. package/src/FlameGraph/FlameGraphComponent/ContextMenu.module.scss +10 -0
  138. package/src/FlameGraph/FlameGraphComponent/ContextMenu.spec.tsx +84 -0
  139. package/src/FlameGraph/FlameGraphComponent/ContextMenu.tsx +86 -0
  140. package/src/FlameGraph/FlameGraphComponent/ContextMenuHighlight.module.css +8 -0
  141. package/src/FlameGraph/FlameGraphComponent/ContextMenuHighlight.tsx +47 -0
  142. package/src/FlameGraph/FlameGraphComponent/DiffLegend.module.css +21 -0
  143. package/src/FlameGraph/FlameGraphComponent/DiffLegend.tsx +52 -0
  144. package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.module.css +40 -0
  145. package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx +129 -0
  146. package/src/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts +552 -0
  147. package/src/FlameGraph/FlameGraphComponent/Flamegraph.ts +446 -0
  148. package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx +233 -0
  149. package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.ts +478 -0
  150. package/src/FlameGraph/FlameGraphComponent/GraphVizPane.tsx +56 -0
  151. package/src/FlameGraph/FlameGraphComponent/GraphVizPanel.module.scss +55 -0
  152. package/src/FlameGraph/FlameGraphComponent/Header.module.css +27 -0
  153. package/src/FlameGraph/FlameGraphComponent/Header.tsx +71 -0
  154. package/src/FlameGraph/FlameGraphComponent/Highlight.module.css +7 -0
  155. package/src/FlameGraph/FlameGraphComponent/Highlight.spec.tsx +53 -0
  156. package/src/FlameGraph/FlameGraphComponent/Highlight.tsx +94 -0
  157. package/src/FlameGraph/FlameGraphComponent/LogoLink.module.scss +10 -0
  158. package/src/FlameGraph/FlameGraphComponent/LogoLink.tsx +101 -0
  159. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-collapses-small-blocks-into-one-1-snap.png +0 -0
  160. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-diff-mode-1-snap.png +0 -0
  161. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-highlighted-flamegraph-1-snap.png +0 -0
  162. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-normal-flamegraph-1-snap.png +0 -0
  163. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-selected-node-1-snap.png +0 -0
  164. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-also-zooms-1-snap.png +0 -0
  165. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-in-the-beginning-1-snap.png +0 -0
  166. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-when-node-is-not-in-the-beginning-1-snap.png +0 -0
  167. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-zoom-top-level-1-snap.png +0 -0
  168. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-complex-flamegraph-1-snap.png +0 -0
  169. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-double-diff-flamegraph-1-snap.png +0 -0
  170. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-double-flamegraph-1-snap.png +0 -0
  171. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-flamegraph-1-snap.png +0 -0
  172. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-simple-flamegraph-1-snap.png +0 -0
  173. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-simple-tree-1-snap.png +0 -0
  174. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-zoomed-flamegraph-1-snap.png +0 -0
  175. package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-zoomed-with-fit-mode-tail-1-snap.png +0 -0
  176. package/src/FlameGraph/FlameGraphComponent/canvas.module.css +6 -0
  177. package/src/FlameGraph/FlameGraphComponent/color.spec.ts +308 -0
  178. package/src/FlameGraph/FlameGraphComponent/color.ts +167 -0
  179. package/src/FlameGraph/FlameGraphComponent/colorPalette.ts +58 -0
  180. package/src/FlameGraph/FlameGraphComponent/constants.ts +5 -0
  181. package/src/FlameGraph/FlameGraphComponent/index.spec.tsx +291 -0
  182. package/src/FlameGraph/FlameGraphComponent/index.tsx +411 -0
  183. package/src/FlameGraph/FlameGraphComponent/murmur3.ts +97 -0
  184. package/src/FlameGraph/FlameGraphComponent/styles.module.scss +10 -0
  185. package/src/FlameGraph/FlameGraphComponent/testData.ts +427 -0
  186. package/src/FlameGraph/FlameGraphComponent/utils.ts +31 -0
  187. package/src/FlameGraph/FlameGraphComponent/viewTypes.ts +6 -0
  188. package/src/FlameGraph/FlameGraphRenderer.tsx +603 -0
  189. package/src/FlameGraph/FlamegraphRenderer.module.scss +93 -0
  190. package/src/FlameGraph/decode.ts +78 -0
  191. package/src/FlameGraph/normalize.spec.ts +76 -0
  192. package/src/FlameGraph/normalize.ts +60 -0
  193. package/src/FlameGraph/testData.json +423 -0
  194. package/src/FlameGraph/uniqueness.spec.ts +16 -0
  195. package/src/FlameGraph/uniqueness.ts +84 -0
  196. package/src/FlamegraphRenderer.tsx +61 -0
  197. package/src/Icons.tsx +74 -0
  198. package/src/ProfilerTable.tsx +527 -0
  199. package/src/SharedQueryInput.module.scss +82 -0
  200. package/src/SharedQueryInput.tsx +127 -0
  201. package/src/Toolbar.module.scss +117 -0
  202. package/src/Toolbar.spec.tsx +217 -0
  203. package/src/Toolbar.tsx +471 -0
  204. package/src/Tooltip/FlamegraphTooltip.spec.tsx +81 -0
  205. package/src/Tooltip/FlamegraphTooltip.tsx +257 -0
  206. package/src/Tooltip/LeftClickIcon.tsx +18 -0
  207. package/src/Tooltip/RightClickIcon.tsx +18 -0
  208. package/src/Tooltip/TableTooltip.spec.tsx +44 -0
  209. package/src/Tooltip/TableTooltip.tsx +145 -0
  210. package/src/Tooltip/Tooltip.module.scss +71 -0
  211. package/src/Tooltip/Tooltip.spec.tsx +395 -0
  212. package/src/Tooltip/Tooltip.tsx +336 -0
  213. package/src/__snapshots__/Toolbar.spec.tsx.snap +297 -0
  214. package/src/convert/convertJaegerTraceToProfile.ts +97 -0
  215. package/src/convert/diffTwoProfiles.ts +81 -0
  216. package/src/convert/flamebearersToTree.ts +78 -0
  217. package/src/convert/sandwichViewProfiles.spec.ts +65 -0
  218. package/src/convert/sandwichViewProfiles.ts +191 -0
  219. package/src/convert/subtract.ts +87 -0
  220. package/src/convert/testData.ts +145 -0
  221. package/src/convert/toGraphviz.ts +485 -0
  222. package/src/fitMode/fitMode.spec.ts +93 -0
  223. package/src/fitMode/fitMode.ts +122 -0
  224. package/src/format/format.spec.ts +291 -0
  225. package/src/format/format.ts +303 -0
  226. package/src/globals.d.ts +13 -0
  227. package/src/i18n.tsx +293 -0
  228. package/src/index.node.ts +19 -0
  229. package/src/index.spec.tsx +383 -0
  230. package/src/index.tsx +10 -0
  231. package/src/logo-v3-small.svg +32 -0
  232. package/src/models/decode.ts +45 -0
  233. package/src/models/flamebearer.ts +86 -0
  234. package/src/models/groups.ts +14 -0
  235. package/src/models/index.ts +7 -0
  236. package/src/models/profile.spec.ts +32 -0
  237. package/src/models/profile.ts +48 -0
  238. package/src/models/spyName.spec.ts +18 -0
  239. package/src/models/spyName.ts +32 -0
  240. package/src/models/trace.ts +45 -0
  241. package/src/models/units.spec.ts +21 -0
  242. package/src/models/units.ts +24 -0
  243. package/src/sass/_common.scss +206 -0
  244. package/src/sass/_css-variables.scss +201 -0
  245. package/src/sass/_mixins.scss +15 -0
  246. package/src/sass/_sanitize.scss +407 -0
  247. package/src/sass/_variables.scss +53 -0
  248. package/src/sass/flamegraph.scss +18 -0
  249. package/src/search.spec.ts +11 -0
  250. package/src/search.ts +4 -0
  251. package/src/shameful-any.d.ts +2 -0
  252. package/src/shims/Box.module.scss +57 -0
  253. package/src/shims/Box.tsx +105 -0
  254. package/src/shims/Button.module.scss +129 -0
  255. package/src/shims/Button.tsx +128 -0
  256. package/src/shims/Dropdown.module.scss +63 -0
  257. package/src/shims/Dropdown.tsx +96 -0
  258. package/src/shims/Input.module.scss +15 -0
  259. package/src/shims/Input.tsx +55 -0
  260. package/src/shims/LoadingSpinner.tsx +19 -0
  261. package/src/shims/Menu.tsx +9 -0
  262. package/src/shims/NoData.module.scss +6 -0
  263. package/src/shims/NoData.tsx +11 -0
  264. package/src/shims/Table.module.scss +82 -0
  265. package/src/shims/Table.spec.tsx +121 -0
  266. package/src/shims/Table.tsx +252 -0
  267. package/src/shims/Tooltip.tsx +51 -0
@@ -0,0 +1,303 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ import { Units } from '../models/units';
3
+
4
+ export function numberWithCommas(x: number): string {
5
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
6
+ }
7
+
8
+ export function formatPercent(ratio: number) {
9
+ const percent = ratioToPercent(ratio);
10
+ return `${percent}%`;
11
+ }
12
+
13
+ export function ratioToPercent(ratio: number) {
14
+ return Math.round(10000 * ratio) / 100;
15
+ }
16
+
17
+ export function diffPercent(leftPercent: number, rightPercent: number): number {
18
+ // difference between 2 percents
19
+ // https://en.wikipedia.org/wiki/Relative_change_and_difference
20
+ return ((rightPercent - leftPercent) / leftPercent) * 100;
21
+ }
22
+
23
+ export function getFormatter(max: number, sampleRate: number, unit: Units) {
24
+ switch (unit) {
25
+ case 'samples':
26
+ return new DurationFormatter(max / sampleRate);
27
+ case 'objects':
28
+ return new ObjectsFormatter(max);
29
+ case 'goroutines':
30
+ return new ObjectsFormatter(max);
31
+ case 'bytes':
32
+ return new BytesFormatter(max);
33
+ case 'lock_nanoseconds':
34
+ return new NanosecondsFormatter(max);
35
+ case 'lock_samples':
36
+ return new ObjectsFormatter(max);
37
+ case 'trace_samples':
38
+ return new DurationFormatter(max / sampleRate, '', true);
39
+ case 'exceptions':
40
+ return new ObjectsFormatter(max);
41
+ default:
42
+ console.warn(`Unsupported unit: '${unit}'. Defaulting to ''`);
43
+ return new DurationFormatter(max / sampleRate, ' ');
44
+ }
45
+ }
46
+
47
+ // this is a class and not a function because we can save some time by
48
+ // precalculating divider and suffix and not doing it on each iteration
49
+ export class DurationFormatter {
50
+ divider = 1;
51
+
52
+ enableSubsecondPrecision = false;
53
+
54
+ suffix = 'second';
55
+
56
+ durations: [number, string][] = [
57
+ [60, 'minute'],
58
+ [60, 'hour'],
59
+ [24, 'day'],
60
+ [30, 'month'],
61
+ [12, 'year'],
62
+ ];
63
+
64
+ units = '';
65
+
66
+ constructor(
67
+ maxDur: number,
68
+ units?: string,
69
+ enableSubsecondPrecision?: boolean
70
+ ) {
71
+ if (enableSubsecondPrecision) {
72
+ this.enableSubsecondPrecision = enableSubsecondPrecision;
73
+ this.durations = [[1000, 'ms'], [1000, 'second'], ...this.durations];
74
+ this.suffix = `μs`;
75
+ maxDur *= 1e6; // Converting seconds to μs
76
+ }
77
+ this.units = units || '';
78
+ // eslint-disable-next-line no-plusplus
79
+ for (let i = 0; i < this.durations.length; i++) {
80
+ const level = this.durations[i];
81
+ if (!level) {
82
+ console.warn('Could not calculate level');
83
+ break;
84
+ }
85
+
86
+ if (maxDur >= level[0]) {
87
+ this.divider *= level[0];
88
+ maxDur /= level[0];
89
+ // eslint-disable-next-line prefer-destructuring
90
+ this.suffix = level[1];
91
+ } else {
92
+ break;
93
+ }
94
+ }
95
+ }
96
+
97
+ format(samples: number, sampleRate: number, withUnits = true): string {
98
+ if (this.enableSubsecondPrecision) {
99
+ sampleRate /= 1e6;
100
+ }
101
+ const n = samples / sampleRate / this.divider;
102
+ let nStr = n.toFixed(2);
103
+
104
+ if (n === 0) {
105
+ nStr = '0.00';
106
+ } else if (n >= 0 && n < 0.01) {
107
+ nStr = '< 0.01';
108
+ } else if (n <= 0 && n > -0.01) {
109
+ nStr = '< 0.01';
110
+ }
111
+
112
+ return withUnits
113
+ ? `${nStr} ${
114
+ this.units ||
115
+ `${this.suffix}${n === 1 || this.suffix.length === 2 ? '' : 's'}`
116
+ }`
117
+ : nStr;
118
+ }
119
+
120
+ formatPrecise(samples: number, sampleRate: number) {
121
+ if (this.enableSubsecondPrecision) {
122
+ sampleRate /= 1e6;
123
+ }
124
+ const n = samples / sampleRate / this.divider;
125
+
126
+ return `${parseFloat(n.toFixed(5))} ${
127
+ this.units ||
128
+ `${this.suffix}${n === 1 || this.suffix.length === 2 ? '' : 's'}`
129
+ }`;
130
+ }
131
+ }
132
+
133
+ // this is a class and not a function because we can save some time by
134
+ // precalculating divider and suffix and not doing it on each iteration
135
+ export class NanosecondsFormatter {
136
+ divider = 1;
137
+
138
+ multiplier = 1;
139
+
140
+ suffix = 'second';
141
+
142
+ durations: [number, string][] = [
143
+ [60, 'minute'],
144
+ [60, 'hour'],
145
+ [24, 'day'],
146
+ [30, 'month'],
147
+ [12, 'year'],
148
+ ];
149
+
150
+ constructor(maxDur: number) {
151
+ maxDur /= 1000000000;
152
+ // eslint-disable-next-line no-plusplus
153
+ for (let i = 0; i < this.durations.length; i++) {
154
+ const level = this.durations[i];
155
+ if (!level) {
156
+ console.warn('Could not calculate level');
157
+ break;
158
+ }
159
+
160
+ if (maxDur >= level[0]) {
161
+ this.divider *= level[0];
162
+ maxDur /= level[0];
163
+ // eslint-disable-next-line prefer-destructuring
164
+ this.suffix = level[1];
165
+ } else {
166
+ break;
167
+ }
168
+ }
169
+ }
170
+
171
+ format(samples: number) {
172
+ const n = samples / 1000000000 / this.divider;
173
+ let nStr = n.toFixed(2);
174
+
175
+ if (n >= 0 && n < 0.01) {
176
+ nStr = '< 0.01';
177
+ } else if (n <= 0 && n > -0.01) {
178
+ nStr = '< 0.01';
179
+ }
180
+
181
+ return `${nStr} ${this.suffix}${n === 1 ? '' : 's'}`;
182
+ }
183
+
184
+ formatPrecise(samples: number) {
185
+ const n = samples / 1000000000 / this.divider;
186
+
187
+ return `${parseFloat(n.toFixed(5))} ${this.suffix}${n === 1 ? '' : 's'}`;
188
+ }
189
+ }
190
+
191
+ export class ObjectsFormatter {
192
+ divider = 1;
193
+
194
+ suffix = '';
195
+
196
+ objects: [number, string][] = [
197
+ [1000, 'K'],
198
+ [1000, 'M'],
199
+ [1000, 'G'],
200
+ [1000, 'T'],
201
+ [1000, 'P'],
202
+ ];
203
+
204
+ constructor(maxObjects: number) {
205
+ // eslint-disable-next-line no-plusplus
206
+ for (let i = 0; i < this.objects.length; i++) {
207
+ const level = this.objects[i];
208
+ if (!level) {
209
+ console.warn('Could not calculate level');
210
+ break;
211
+ }
212
+
213
+ if (maxObjects >= level[0]) {
214
+ this.divider *= level[0];
215
+ maxObjects /= level[0];
216
+ // eslint-disable-next-line prefer-destructuring
217
+ this.suffix = level[1];
218
+ } else {
219
+ break;
220
+ }
221
+ }
222
+ }
223
+
224
+ // TODO:
225
+ // how to indicate that sampleRate doesn't matter?
226
+ format(samples: number) {
227
+ const n = samples / this.divider;
228
+ let nStr = n.toFixed(2);
229
+
230
+ if (n >= 0 && n < 0.01) {
231
+ nStr = '< 0.01';
232
+ } else if (n <= 0 && n > -0.01) {
233
+ nStr = '< 0.01';
234
+ }
235
+ return `${nStr} ${this.suffix}`;
236
+ }
237
+
238
+ formatPrecise(samples: number) {
239
+ const n = samples / this.divider;
240
+
241
+ return `${parseFloat(n.toFixed(5))} ${this.suffix}`;
242
+ }
243
+ }
244
+
245
+ export class BytesFormatter {
246
+ divider = 1;
247
+
248
+ suffix = 'bytes';
249
+
250
+ bytes: [number, string][] = [
251
+ [1024, 'KB'],
252
+ [1024, 'MB'],
253
+ [1024, 'GB'],
254
+ [1024, 'TB'],
255
+ [1024, 'PB'],
256
+ ];
257
+
258
+ constructor(maxBytes: number) {
259
+ // eslint-disable-next-line no-plusplus
260
+ for (let i = 0; i < this.bytes.length; i++) {
261
+ const level = this.bytes[i];
262
+ if (!level) {
263
+ console.warn('Could not calculate level');
264
+ break;
265
+ }
266
+
267
+ if (maxBytes >= level[0]) {
268
+ this.divider *= level[0];
269
+ maxBytes /= level[0];
270
+
271
+ // eslint-disable-next-line prefer-destructuring
272
+ const suffix = level[1];
273
+ if (!suffix) {
274
+ console.warn('Could not calculate suffix');
275
+ this.suffix = '';
276
+ } else {
277
+ this.suffix = suffix;
278
+ }
279
+ } else {
280
+ break;
281
+ }
282
+ }
283
+ }
284
+
285
+ format(samples: number) {
286
+ const n = samples / this.divider;
287
+ let nStr = n.toFixed(2);
288
+
289
+ if (n >= 0 && n < 0.01) {
290
+ nStr = '< 0.01';
291
+ } else if (n <= 0 && n > -0.01) {
292
+ nStr = '< 0.01';
293
+ }
294
+
295
+ return `${nStr} ${this.suffix}`;
296
+ }
297
+
298
+ formatPrecise(samples: number) {
299
+ const n = samples / this.divider;
300
+
301
+ return `${parseFloat(n.toFixed(5))} ${this.suffix}`;
302
+ }
303
+ }
@@ -0,0 +1,13 @@
1
+ // src/globals.d.ts
2
+ declare module '*.module.scss';
3
+ declare module '*.module.css';
4
+ declare module '*.scss';
5
+ declare module '*.css';
6
+
7
+ declare module '*.svg' {
8
+ import * as React from 'react';
9
+ const ReactComponent: React.FunctionComponent<
10
+ React.SVGProps<SVGSVGElement>
11
+ >;
12
+ export default ReactComponent;
13
+ }
package/src/i18n.tsx ADDED
@@ -0,0 +1,293 @@
1
+ // src/i18n.tsx
2
+ import React, { createContext, useContext } from 'react';
3
+ import type { Units } from './models';
4
+
5
+ export type TooltipUnitMessages = {
6
+ percent: string;
7
+ formattedValue: string;
8
+ total: string;
9
+ };
10
+
11
+ export type FlamegraphMessages = {
12
+ // 表格列
13
+ location: string;
14
+ self: string;
15
+ total: string;
16
+ baseline: string;
17
+ comparison: string;
18
+ diff: string;
19
+
20
+ // 表格空状态
21
+ noItemsFound: string;
22
+
23
+ // diff 标签
24
+ diffNew: string;
25
+ diffRemoved: string;
26
+
27
+ // Tooltip 相关
28
+ tooltipSamples: string;
29
+ tooltipUnitTitles: Record<Units, TooltipUnitMessages>;
30
+
31
+ // 上下文菜单 / 工具栏
32
+ resetView: string;
33
+ collapseNodesAbove: string;
34
+ copyFunctionName: string;
35
+ highlightSimilarNodes: string;
36
+ clearHighlight: string;
37
+ openInSandwichView: string;
38
+ showTextTailFirst: string;
39
+ showTextHeadFirst: string;
40
+
41
+ // 工具栏 fit 模式
42
+ headFirst: string;
43
+ tailFirst: string;
44
+
45
+ // Tooltip 底部说明
46
+ clickToHighlightNode: string;
47
+ rightClickForMoreNodeOptions: string;
48
+
49
+ // 视图切换按钮
50
+ viewTable: string;
51
+ viewTableAndFlamegraph: string;
52
+ viewFlamegraph: string;
53
+ viewSandwich: string;
54
+ viewGraphviz: string;
55
+ more: string;
56
+
57
+ // Diff 图例 & 调色板
58
+ diffLegendRemovedLabel: string;
59
+ diffLegendAddedLabel: string;
60
+ diffLegendSelectPalette: string;
61
+ paletteDefaultName: string;
62
+ paletteColorBlindName: string;
63
+
64
+ // 搜索框 & 多视图搜索联动
65
+ searchPlaceholder: string;
66
+ syncSearchBars: string;
67
+ unsyncSearchBars: string;
68
+ };
69
+
70
+ const defaultTooltipUnitTitles: Record<Units, TooltipUnitMessages> = {
71
+ objects: {
72
+ percent: '% of objects in RAM',
73
+ formattedValue: 'Objects in RAM',
74
+ total: '% of total RAM',
75
+ },
76
+ goroutines: {
77
+ percent: '% of goroutines',
78
+ formattedValue: 'Goroutines',
79
+ total: '% of total goroutines',
80
+ },
81
+ bytes: {
82
+ percent: '% of RAM',
83
+ formattedValue: 'RAM',
84
+ total: '% of total bytes',
85
+ },
86
+ samples: {
87
+ percent: 'Share of CPU',
88
+ formattedValue: 'CPU Time',
89
+ total: '% of total CPU',
90
+ },
91
+ lock_nanoseconds: {
92
+ percent: '% of Time spent',
93
+ formattedValue: 'Time',
94
+ total: '% of total seconds',
95
+ },
96
+ lock_samples: {
97
+ percent: '% of contended locks',
98
+ formattedValue: 'Contended locks',
99
+ total: '% of total locks',
100
+ },
101
+ trace_samples: {
102
+ percent: '% of time',
103
+ formattedValue: 'Samples',
104
+ total: '% of total samples',
105
+ },
106
+ exceptions: {
107
+ percent: '% of thrown exceptions',
108
+ formattedValue: 'Thrown exceptions',
109
+ total: '% of total thrown exceptions',
110
+ },
111
+ unknown: {
112
+ percent: 'Percentage',
113
+ formattedValue: 'Units',
114
+ total: '% of total units',
115
+ },
116
+ };
117
+
118
+ const zhCNTooltipUnitTitles: Record<Units, TooltipUnitMessages> = {
119
+ objects: {
120
+ percent: 'RAM 中对象占比',
121
+ formattedValue: 'RAM 中对象数',
122
+ total: '占总 RAM 的百分比',
123
+ },
124
+ goroutines: {
125
+ percent: '协程占比',
126
+ formattedValue: '协程数量',
127
+ total: '占协程总数的百分比',
128
+ },
129
+ bytes: {
130
+ percent: 'RAM 占比',
131
+ formattedValue: 'RAM',
132
+ total: '占总字节数的百分比',
133
+ },
134
+ samples: {
135
+ percent: 'CPU 占比',
136
+ formattedValue: 'CPU 时间',
137
+ total: '占总 CPU 的百分比',
138
+ },
139
+ lock_nanoseconds: {
140
+ percent: '耗时占比',
141
+ formattedValue: '时间',
142
+ total: '占总秒数的百分比',
143
+ },
144
+ lock_samples: {
145
+ percent: '锁竞争事件占比',
146
+ formattedValue: '锁竞争事件数',
147
+ total: '占锁竞争总数的百分比',
148
+ },
149
+ trace_samples: {
150
+ percent: '时间占比',
151
+ formattedValue: '样本数',
152
+ total: '占样本总数的百分比',
153
+ },
154
+ exceptions: {
155
+ percent: '异常抛出占比',
156
+ formattedValue: '异常数',
157
+ total: '占异常总数的百分比',
158
+ },
159
+ unknown: {
160
+ percent: '百分比',
161
+ formattedValue: '单位',
162
+ total: '占单位总量的百分比',
163
+ },
164
+ };
165
+
166
+ export const defaultMessages: FlamegraphMessages = {
167
+ location: 'Location',
168
+ self: 'Self',
169
+ total: 'Total',
170
+ baseline: 'Baseline',
171
+ comparison: 'Comparison',
172
+ diff: 'Diff',
173
+
174
+ noItemsFound: 'No items found',
175
+
176
+ diffNew: '(new)',
177
+ diffRemoved: '(removed)',
178
+
179
+ tooltipSamples: 'Samples:',
180
+ tooltipUnitTitles: defaultTooltipUnitTitles,
181
+
182
+ resetView: 'Reset View',
183
+ collapseNodesAbove: 'Collapse nodes above',
184
+ copyFunctionName: 'Copy function name',
185
+ highlightSimilarNodes: 'Highlight similar nodes',
186
+ clearHighlight: 'Clear highlight',
187
+ openInSandwichView: 'Open in sandwich view',
188
+ showTextTailFirst: 'Show text tail first',
189
+ showTextHeadFirst: 'Show text head first',
190
+
191
+ headFirst: 'Head first',
192
+ tailFirst: 'Tail first',
193
+
194
+ clickToHighlightNode: 'Click to highlight node in flamegraph',
195
+ rightClickForMoreNodeOptions: 'Right click for more node viewing options',
196
+
197
+ viewTable: 'Table',
198
+ viewTableAndFlamegraph: 'Table and Flamegraph',
199
+ viewFlamegraph: 'Flamegraph',
200
+ viewSandwich: 'Sandwich',
201
+ viewGraphviz: 'GraphViz',
202
+ more: 'More',
203
+
204
+ diffLegendRemovedLabel: '(-) Removed',
205
+ diffLegendAddedLabel: 'Added (+)',
206
+ diffLegendSelectPalette: 'Select a palette',
207
+ paletteDefaultName: 'Default',
208
+ paletteColorBlindName: 'Color Blind',
209
+
210
+ // 搜索框 & 多视图搜索联动
211
+ searchPlaceholder: 'Search...',
212
+ syncSearchBars: 'Sync Search Bars',
213
+ unsyncSearchBars: 'Unsync Search Bars'
214
+ };
215
+
216
+ export const zhCNMessages: FlamegraphMessages = {
217
+ ...defaultMessages,
218
+ location: '位置',
219
+ self: '自身',
220
+ total: '总计',
221
+ baseline: '基线',
222
+ comparison: '对比',
223
+ diff: '差异',
224
+
225
+ noItemsFound: '没有找到任何条目',
226
+
227
+ diffNew: '(新增)',
228
+ diffRemoved: '(移除)',
229
+
230
+ tooltipSamples: '样本数:',
231
+ tooltipUnitTitles: zhCNTooltipUnitTitles,
232
+
233
+ resetView: '重置视图',
234
+ collapseNodesAbove: '收起上方节点',
235
+ copyFunctionName: '复制函数名',
236
+ highlightSimilarNodes: '高亮相似节点',
237
+ clearHighlight: '清除高亮',
238
+ openInSandwichView: '在 sandwich 视图中查看',
239
+ showTextTailFirst: '显示文本尾部优先',
240
+ showTextHeadFirst: '显示文本头部优先',
241
+
242
+ headFirst: '从头部开始显示',
243
+ tailFirst: '从尾部开始显示',
244
+
245
+ clickToHighlightNode: '点击火焰图节点高亮',
246
+ rightClickForMoreNodeOptions: '右键查看更多节点选项',
247
+
248
+ viewTable: '表格',
249
+ viewTableAndFlamegraph: '表格 + 火焰图',
250
+ viewFlamegraph: '火焰图',
251
+ viewSandwich: '三明治视图',
252
+ viewGraphviz: '调用图 (GraphViz)',
253
+ more: '更多',
254
+
255
+ diffLegendRemovedLabel: '(-) 减少',
256
+ diffLegendAddedLabel: '增加 (+)',
257
+ diffLegendSelectPalette: '选择颜色方案',
258
+ paletteDefaultName: '默认',
259
+ paletteColorBlindName: '色盲模式',
260
+
261
+ // 搜索框 & 多视图搜索联动
262
+ searchPlaceholder: '搜索...',
263
+ syncSearchBars: '同步搜索栏',
264
+ unsyncSearchBars: '取消同步搜索栏'
265
+ };
266
+
267
+ const I18nContext = createContext<FlamegraphMessages>(defaultMessages);
268
+
269
+ export type FlamegraphI18nProviderProps = {
270
+ messages?: Partial<FlamegraphMessages>;
271
+ children: React.ReactNode;
272
+ };
273
+
274
+ export const FlamegraphI18nProvider: React.FC<FlamegraphI18nProviderProps> = ({
275
+ messages,
276
+ children,
277
+ }) => {
278
+ const value = React.useMemo(
279
+ () => ({
280
+ ...defaultMessages,
281
+ ...messages,
282
+ tooltipUnitTitles: {
283
+ ...defaultMessages.tooltipUnitTitles,
284
+ ...(messages?.tooltipUnitTitles ?? {}),
285
+ },
286
+ }),
287
+ [messages]
288
+ );
289
+
290
+ return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
291
+ };
292
+
293
+ export const useFlamegraphI18n = () => useContext(I18nContext);
@@ -0,0 +1,19 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+ import Box from './shims/Box';
4
+ import Flamegraph from './FlameGraph/FlameGraphComponent/Flamegraph';
5
+ import { DefaultPalette } from './FlameGraph/FlameGraphComponent/colorPalette';
6
+ import { FlamegraphRenderer } from './FlamegraphRenderer';
7
+ import { convertJaegerTraceToProfile } from './convert/convertJaegerTraceToProfile';
8
+ import { diffTwoProfiles } from './convert/diffTwoProfiles';
9
+ import { subtract } from './convert/subtract';
10
+
11
+ export {
12
+ Flamegraph,
13
+ DefaultPalette,
14
+ FlamegraphRenderer,
15
+ Box,
16
+ convertJaegerTraceToProfile,
17
+ diffTwoProfiles,
18
+ subtract,
19
+ };