@perses-dev/flame-chart-plugin 0.2.0

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 (198) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +23 -0
  3. package/__mf/css/async/325.f56729ca.css +1 -0
  4. package/__mf/css/async/341.f56729ca.css +1 -0
  5. package/__mf/css/async/908.f56729ca.css +1 -0
  6. package/__mf/font/lato-all-300-normal.322bdf14.woff +0 -0
  7. package/__mf/font/lato-all-400-normal.63513b00.woff +0 -0
  8. package/__mf/font/lato-all-700-normal.bb27db94.woff +0 -0
  9. package/__mf/font/lato-all-900-normal.a27049a3.woff +0 -0
  10. package/__mf/font/lato-latin-300-normal.c5195215.woff2 +0 -0
  11. package/__mf/font/lato-latin-400-normal.b7ffde23.woff2 +0 -0
  12. package/__mf/font/lato-latin-700-normal.d5eb20bc.woff2 +0 -0
  13. package/__mf/font/lato-latin-900-normal.d884a71c.woff2 +0 -0
  14. package/__mf/font/lato-latin-ext-300-normal.abcc64a9.woff2 +0 -0
  15. package/__mf/font/lato-latin-ext-400-normal.6ebed106.woff2 +0 -0
  16. package/__mf/font/lato-latin-ext-700-normal.8697d1d5.woff2 +0 -0
  17. package/__mf/font/lato-latin-ext-900-normal.20a2b415.woff2 +0 -0
  18. package/__mf/js/FlameChart.96aae761.js +5 -0
  19. package/__mf/js/async/109.f7e97e30.js +73 -0
  20. package/__mf/js/async/109.f7e97e30.js.LICENSE.txt +35 -0
  21. package/__mf/js/async/173.40a64c5c.js +2 -0
  22. package/__mf/js/async/173.40a64c5c.js.LICENSE.txt +19 -0
  23. package/__mf/js/async/214.f491540e.js +1 -0
  24. package/__mf/js/async/224.511d05b6.js +1 -0
  25. package/__mf/js/async/238.5fdc556e.js +1 -0
  26. package/__mf/js/async/29.8b55315e.js +1 -0
  27. package/__mf/js/async/292.643bbcde.js +1 -0
  28. package/__mf/js/async/32.a46fc45f.js +110 -0
  29. package/__mf/js/async/32.a46fc45f.js.LICENSE.txt +49 -0
  30. package/__mf/js/async/325.80031d25.js +1 -0
  31. package/__mf/js/async/362.c587718a.js +1 -0
  32. package/__mf/js/async/409.fd2d437e.js +1 -0
  33. package/__mf/js/async/464.bb266d9b.js +7 -0
  34. package/__mf/js/async/464.bb266d9b.js.LICENSE.txt +21 -0
  35. package/__mf/js/async/488.807096d6.js +1 -0
  36. package/__mf/js/async/600.fdf527b8.js +38 -0
  37. package/__mf/js/async/651.9eb6f201.js +1 -0
  38. package/__mf/js/async/69.a1079bc1.js +2 -0
  39. package/__mf/js/async/69.a1079bc1.js.LICENSE.txt +24 -0
  40. package/__mf/js/async/694.15848123.js +1 -0
  41. package/__mf/js/async/738.0b2ab393.js +1 -0
  42. package/__mf/js/async/740.65aa69e2.js +1 -0
  43. package/__mf/js/async/75.3435fe3f.js +1 -0
  44. package/__mf/js/async/770.bc6ab5a3.js +1 -0
  45. package/__mf/js/async/863.8b7bdf43.js +2 -0
  46. package/__mf/js/async/863.8b7bdf43.js.LICENSE.txt +9 -0
  47. package/__mf/js/async/908.0672909d.js +1 -0
  48. package/__mf/js/async/960.d56a397e.js +2 -0
  49. package/__mf/js/async/960.d56a397e.js.LICENSE.txt +8 -0
  50. package/__mf/js/async/964.86d91e52.js +2 -0
  51. package/__mf/js/async/964.86d91e52.js.LICENSE.txt +9 -0
  52. package/__mf/js/async/981.4de2d5c8.js +2 -0
  53. package/__mf/js/async/981.4de2d5c8.js.LICENSE.txt +8 -0
  54. package/__mf/js/async/__federation_expose_FlameChart.aaa6df30.js +17 -0
  55. package/__mf/js/async/lib-router.00804bbc.js +2 -0
  56. package/__mf/js/async/lib-router.00804bbc.js.LICENSE.txt +32 -0
  57. package/__mf/js/main.4931a266.js +5 -0
  58. package/lib/FlameChart.d.ts +8 -0
  59. package/lib/FlameChart.d.ts.map +1 -0
  60. package/lib/FlameChart.js +32 -0
  61. package/lib/FlameChart.js.map +1 -0
  62. package/lib/bootstrap.d.ts +2 -0
  63. package/lib/bootstrap.d.ts.map +1 -0
  64. package/lib/bootstrap.js +19 -0
  65. package/lib/bootstrap.js.map +1 -0
  66. package/lib/cjs/FlameChart.js +38 -0
  67. package/lib/cjs/bootstrap.js +26 -0
  68. package/lib/cjs/components/CustomBreadcrumb.js +96 -0
  69. package/lib/cjs/components/FlameChart.js +341 -0
  70. package/lib/cjs/components/FlameChartOptionsEditorSettings.js +87 -0
  71. package/lib/cjs/components/FlameChartPanel.js +147 -0
  72. package/lib/cjs/components/PaletteSelector.js +49 -0
  73. package/lib/cjs/components/SearchBar.js +59 -0
  74. package/lib/cjs/components/SeriesChart.js +189 -0
  75. package/lib/cjs/components/Settings.js +202 -0
  76. package/lib/cjs/components/SwitchSelector.js +37 -0
  77. package/lib/cjs/components/TableChart.js +143 -0
  78. package/lib/cjs/components/index.js +39 -0
  79. package/lib/cjs/env.d.js +14 -0
  80. package/lib/cjs/flame-chart-model.js +31 -0
  81. package/lib/cjs/getPluginModule.js +39 -0
  82. package/lib/cjs/index-federation.js +55 -0
  83. package/lib/cjs/index.js +37 -0
  84. package/lib/cjs/setup-tests.js +19 -0
  85. package/lib/cjs/utils/data-model.js +18 -0
  86. package/lib/cjs/utils/data-transform.js +152 -0
  87. package/lib/cjs/utils/format.js +87 -0
  88. package/lib/cjs/utils/palette-gen.js +68 -0
  89. package/lib/cjs/utils/palette.js +62 -0
  90. package/lib/cjs/utils/series-tooltip.js +51 -0
  91. package/lib/cjs/utils/tooltip.js +76 -0
  92. package/lib/cjs/utils/ui-text.js +30 -0
  93. package/lib/cjs/utils/utils.js +108 -0
  94. package/lib/components/CustomBreadcrumb.d.ts +9 -0
  95. package/lib/components/CustomBreadcrumb.d.ts.map +1 -0
  96. package/lib/components/CustomBreadcrumb.js +83 -0
  97. package/lib/components/CustomBreadcrumb.js.map +1 -0
  98. package/lib/components/FlameChart.d.ts +13 -0
  99. package/lib/components/FlameChart.d.ts.map +1 -0
  100. package/lib/components/FlameChart.js +328 -0
  101. package/lib/components/FlameChart.js.map +1 -0
  102. package/lib/components/FlameChartOptionsEditorSettings.d.ts +4 -0
  103. package/lib/components/FlameChartOptionsEditorSettings.d.ts.map +1 -0
  104. package/lib/components/FlameChartOptionsEditorSettings.js +79 -0
  105. package/lib/components/FlameChartOptionsEditorSettings.js.map +1 -0
  106. package/lib/components/FlameChartPanel.d.ts +7 -0
  107. package/lib/components/FlameChartPanel.d.ts.map +1 -0
  108. package/lib/components/FlameChartPanel.js +139 -0
  109. package/lib/components/FlameChartPanel.js.map +1 -0
  110. package/lib/components/PaletteSelector.d.ts +8 -0
  111. package/lib/components/PaletteSelector.d.ts.map +1 -0
  112. package/lib/components/PaletteSelector.js +41 -0
  113. package/lib/components/PaletteSelector.js.map +1 -0
  114. package/lib/components/SearchBar.d.ts +7 -0
  115. package/lib/components/SearchBar.d.ts.map +1 -0
  116. package/lib/components/SearchBar.js +46 -0
  117. package/lib/components/SearchBar.js.map +1 -0
  118. package/lib/components/SeriesChart.d.ts +9 -0
  119. package/lib/components/SeriesChart.d.ts.map +1 -0
  120. package/lib/components/SeriesChart.js +181 -0
  121. package/lib/components/SeriesChart.js.map +1 -0
  122. package/lib/components/Settings.d.ts +11 -0
  123. package/lib/components/Settings.d.ts.map +1 -0
  124. package/lib/components/Settings.js +189 -0
  125. package/lib/components/Settings.js.map +1 -0
  126. package/lib/components/SwitchSelector.d.ts +8 -0
  127. package/lib/components/SwitchSelector.d.ts.map +1 -0
  128. package/lib/components/SwitchSelector.js +29 -0
  129. package/lib/components/SwitchSelector.js.map +1 -0
  130. package/lib/components/TableChart.d.ts +12 -0
  131. package/lib/components/TableChart.d.ts.map +1 -0
  132. package/lib/components/TableChart.js +135 -0
  133. package/lib/components/TableChart.js.map +1 -0
  134. package/lib/components/index.d.ts +11 -0
  135. package/lib/components/index.d.ts.map +1 -0
  136. package/lib/components/index.js +24 -0
  137. package/lib/components/index.js.map +1 -0
  138. package/lib/env.d.js +15 -0
  139. package/lib/env.d.js.map +1 -0
  140. package/lib/flame-chart-model.d.ts +18 -0
  141. package/lib/flame-chart-model.d.ts.map +1 -0
  142. package/lib/flame-chart-model.js +23 -0
  143. package/lib/flame-chart-model.js.map +1 -0
  144. package/lib/getPluginModule.d.ts +6 -0
  145. package/lib/getPluginModule.d.ts.map +1 -0
  146. package/lib/getPluginModule.js +28 -0
  147. package/lib/getPluginModule.js.map +1 -0
  148. package/lib/index-federation.d.ts +1 -0
  149. package/lib/index-federation.d.ts.map +1 -0
  150. package/lib/index-federation.js +15 -0
  151. package/lib/index-federation.js.map +1 -0
  152. package/lib/index.d.ts +3 -0
  153. package/lib/index.d.ts.map +1 -0
  154. package/lib/index.js +16 -0
  155. package/lib/index.js.map +1 -0
  156. package/lib/setup-tests.d.ts +2 -0
  157. package/lib/setup-tests.d.ts.map +1 -0
  158. package/lib/setup-tests.js +17 -0
  159. package/lib/setup-tests.js.map +1 -0
  160. package/lib/utils/data-model.d.ts +37 -0
  161. package/lib/utils/data-model.d.ts.map +1 -0
  162. package/lib/utils/data-model.js +19 -0
  163. package/lib/utils/data-model.js.map +1 -0
  164. package/lib/utils/data-transform.d.ts +19 -0
  165. package/lib/utils/data-transform.d.ts.map +1 -0
  166. package/lib/utils/data-transform.js +138 -0
  167. package/lib/utils/data-transform.js.map +1 -0
  168. package/lib/utils/format.d.ts +3 -0
  169. package/lib/utils/format.d.ts.map +1 -0
  170. package/lib/utils/format.js +71 -0
  171. package/lib/utils/format.js.map +1 -0
  172. package/lib/utils/palette-gen.d.ts +14 -0
  173. package/lib/utils/palette-gen.d.ts.map +1 -0
  174. package/lib/utils/palette-gen.js +56 -0
  175. package/lib/utils/palette-gen.js.map +1 -0
  176. package/lib/utils/palette.d.ts +5 -0
  177. package/lib/utils/palette.d.ts.map +1 -0
  178. package/lib/utils/palette.js +51 -0
  179. package/lib/utils/palette.js.map +1 -0
  180. package/lib/utils/series-tooltip.d.ts +3 -0
  181. package/lib/utils/series-tooltip.d.ts.map +1 -0
  182. package/lib/utils/series-tooltip.js +43 -0
  183. package/lib/utils/series-tooltip.js.map +1 -0
  184. package/lib/utils/tooltip.d.ts +6 -0
  185. package/lib/utils/tooltip.d.ts.map +1 -0
  186. package/lib/utils/tooltip.js +29 -0
  187. package/lib/utils/tooltip.js.map +1 -0
  188. package/lib/utils/ui-text.d.ts +9 -0
  189. package/lib/utils/ui-text.d.ts.map +1 -0
  190. package/lib/utils/ui-text.js +22 -0
  191. package/lib/utils/ui-text.js.map +1 -0
  192. package/lib/utils/utils.d.ts +36 -0
  193. package/lib/utils/utils.d.ts.map +1 -0
  194. package/lib/utils/utils.js +92 -0
  195. package/lib/utils/utils.js.map +1 -0
  196. package/mf-manifest.json +274 -0
  197. package/mf-stats.json +322 -0
  198. package/package.json +64 -0
@@ -0,0 +1,138 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { getSpanColor } from './palette-gen';
14
+ import { formatItemValue } from './format';
15
+ /**
16
+ * Filter the global stacktrace by a function ID to focus on that function and display its corresponding flame chart
17
+ */ export function filterJson(json, id) {
18
+ if (id === null) {
19
+ return json;
20
+ }
21
+ const recur = (item, id)=>{
22
+ if (item.id === id) {
23
+ return item;
24
+ }
25
+ for (const child of item.children || []){
26
+ const temp = recur(child, id);
27
+ if (temp) {
28
+ item.children = [
29
+ temp
30
+ ];
31
+ // change the parents' values
32
+ item.start = temp.start;
33
+ item.end = temp.end;
34
+ // item.self = temp.self;
35
+ // item.total = temp.total;
36
+ return item;
37
+ }
38
+ }
39
+ };
40
+ return recur(json, id) || json;
41
+ }
42
+ // build the name of the corresponding flamechart item
43
+ function formatName(item, rootVal, unit) {
44
+ return item.total / rootVal * 100 < 1 ? '' : item.name + ` (${formatItemValue(unit, item.total)})`;
45
+ }
46
+ /**
47
+ * Search the total value of an item corresponding to a given ID
48
+ */ function getCurrentTotalValue(json, id) {
49
+ if (id === undefined) return 0;
50
+ const recur = (item)=>{
51
+ if (item.id === id) {
52
+ return item.total;
53
+ }
54
+ for (const child of item.children || []){
55
+ const total = recur(child);
56
+ if (total !== undefined) {
57
+ return total;
58
+ }
59
+ }
60
+ return 0; // If not found, return 0
61
+ };
62
+ return recur(json);
63
+ }
64
+ /**
65
+ * Build series data for the flame chart option
66
+ */ export function recursionJson(palette, metadata, jsonObj, searchValue, id) {
67
+ const data = [];
68
+ const filteredJson = filterJson(structuredClone(jsonObj), id);
69
+ const rootVal = filteredJson.total; // total samples of root node
70
+ const currentVal = getCurrentTotalValue(filteredJson, id); // total samples of the selected item, used to generate items colors
71
+ const recur = (item)=>{
72
+ const temp = {
73
+ name: item.id,
74
+ value: [
75
+ item.level,
76
+ item.start,
77
+ item.end,
78
+ formatName(item, currentVal ? currentVal : rootVal, metadata?.units),
79
+ item.total / rootVal * 100,
80
+ item.self / rootVal * 100,
81
+ item.name,
82
+ item.self,
83
+ item.total
84
+ ],
85
+ itemStyle: {
86
+ color: !isItemNameMatchesSearchFilters(item.name, searchValue) ? '#dee2e6' : getSpanColor(palette, item.name, item.total / (currentVal ? currentVal : rootVal) * 100)
87
+ }
88
+ };
89
+ data.push(temp);
90
+ for (const child of item.children || []){
91
+ recur(child);
92
+ }
93
+ };
94
+ // check is filteredJson is not empty before call recur
95
+ if (filteredJson.id) recur(filteredJson);
96
+ return data;
97
+ }
98
+ /**
99
+ * Transform query results to a tabular format for the table chart
100
+ */ export function tableRecursionJson(jsonObj, searchValue) {
101
+ const data = [];
102
+ const structuredJson = structuredClone(jsonObj);
103
+ const recur = (item)=>{
104
+ const temp = {
105
+ id: item.id,
106
+ name: item.name,
107
+ self: item.self,
108
+ total: item.total
109
+ };
110
+ if (isItemNameMatchesSearchFilters(temp.name, searchValue)) data.push(temp);
111
+ for (const child of item.children || []){
112
+ recur(child);
113
+ }
114
+ };
115
+ // check is structuredJson is not empty before call recur
116
+ if (structuredJson.id) recur(structuredJson);
117
+ return data;
118
+ }
119
+ // Checks if an item name matches all parts of a search value.
120
+ function isItemNameMatchesSearchFilters(itemName, searchValue) {
121
+ if (searchValue === '') return true;
122
+ const filters = searchValue.trim().toLocaleLowerCase().split(/[^a-zA-Z0-9']+/).filter((s)=>s !== '');
123
+ if (filters.length === 0) {
124
+ return false;
125
+ } else {
126
+ return filters.every((filter)=>itemName.toLowerCase().includes(filter.trim()));
127
+ }
128
+ }
129
+ /**
130
+ * Finds the total sample value of the series data item with the specified name.
131
+ */ export function findTotalSampleByName(seriesData, name) {
132
+ if (name === undefined || name === 0) return undefined;
133
+ const item = seriesData.find((item)=>item.name === name);
134
+ const totalSample = item?.value[8];
135
+ return Number(totalSample);
136
+ }
137
+
138
+ //# sourceMappingURL=data-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/data-transform.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ProfileMetaData, StackTrace } from '@perses-dev/core';\nimport { FlameChartSample as Sample, TableChartSample } from './data-model';\nimport { getSpanColor } from './palette-gen';\nimport { formatItemValue } from './format';\n\n/**\n * Filter the global stacktrace by a function ID to focus on that function and display its corresponding flame chart\n */\nexport function filterJson(json: StackTrace, id?: number): StackTrace {\n if (id === null) {\n return json;\n }\n\n const recur = (item: StackTrace, id?: number): StackTrace | undefined => {\n if (item.id === id) {\n return item;\n }\n\n for (const child of item.children || []) {\n const temp = recur(child, id);\n if (temp) {\n item.children = [temp];\n\n // change the parents' values\n item.start = temp.start;\n item.end = temp.end;\n // item.self = temp.self;\n // item.total = temp.total;\n\n return item;\n }\n }\n };\n\n return recur(json, id) || json;\n}\n\n// build the name of the corresponding flamechart item\nfunction formatName(item: StackTrace, rootVal: number, unit: string | undefined): string {\n return (item.total / rootVal) * 100 < 1 ? '' : item.name + ` (${formatItemValue(unit, item.total)})`;\n}\n\n/**\n * Search the total value of an item corresponding to a given ID\n */\nfunction getCurrentTotalValue(json: StackTrace, id: number | undefined): number {\n if (id === undefined) return 0;\n\n const recur = (item: StackTrace): number => {\n if (item.id === id) {\n return item.total;\n }\n\n for (const child of item.children || []) {\n const total = recur(child);\n if (total !== undefined) {\n return total;\n }\n }\n return 0; // If not found, return 0\n };\n\n return recur(json);\n}\n\n/**\n * Build series data for the flame chart option\n */\nexport function recursionJson(\n palette: string,\n metadata: ProfileMetaData | undefined,\n jsonObj: StackTrace,\n searchValue: string,\n id?: number\n): Sample[] {\n const data: Sample[] = [];\n const filteredJson = filterJson(structuredClone(jsonObj), id);\n\n const rootVal = filteredJson.total; // total samples of root node\n const currentVal = getCurrentTotalValue(filteredJson, id); // total samples of the selected item, used to generate items colors\n\n const recur = (item: StackTrace): void => {\n const temp = {\n name: item.id,\n value: [\n item.level,\n item.start,\n item.end,\n formatName(item, currentVal ? currentVal : rootVal, metadata?.units),\n (item.total / rootVal) * 100,\n (item.self / rootVal) * 100,\n item.name,\n item.self,\n item.total,\n ],\n itemStyle: {\n color: !isItemNameMatchesSearchFilters(item.name, searchValue)\n ? '#dee2e6'\n : getSpanColor(palette, item.name, (item.total / (currentVal ? currentVal : rootVal)) * 100),\n },\n };\n data.push(temp as Sample);\n\n for (const child of item.children || []) {\n recur(child);\n }\n };\n\n // check is filteredJson is not empty before call recur\n if (filteredJson.id) recur(filteredJson);\n return data;\n}\n\n/**\n * Transform query results to a tabular format for the table chart\n */\nexport function tableRecursionJson(jsonObj: StackTrace, searchValue: string): TableChartSample[] {\n const data: TableChartSample[] = [];\n const structuredJson = structuredClone(jsonObj);\n\n const recur = (item: StackTrace): void => {\n const temp = {\n id: item.id,\n name: item.name,\n self: item.self,\n total: item.total,\n };\n\n if (isItemNameMatchesSearchFilters(temp.name, searchValue)) data.push(temp as TableChartSample);\n\n for (const child of item.children || []) {\n recur(child);\n }\n };\n\n // check is structuredJson is not empty before call recur\n if (structuredJson.id) recur(structuredJson);\n return data;\n}\n\n// Checks if an item name matches all parts of a search value.\nfunction isItemNameMatchesSearchFilters(itemName: string, searchValue: string): boolean {\n if (searchValue === '') return true;\n\n const filters = searchValue\n .trim()\n .toLocaleLowerCase()\n .split(/[^a-zA-Z0-9']+/)\n .filter((s) => s !== '');\n\n if (filters.length === 0) {\n return false;\n } else {\n return filters.every((filter) => itemName.toLowerCase().includes(filter.trim()));\n }\n}\n\n/**\n * Finds the total sample value of the series data item with the specified name.\n */\nexport function findTotalSampleByName(seriesData: Sample[], name: number | undefined): number | undefined {\n if (name === undefined || name === 0) return undefined;\n const item = seriesData.find((item) => item.name === name);\n const totalSample = item?.value[8];\n return Number(totalSample);\n}\n"],"names":["getSpanColor","formatItemValue","filterJson","json","id","recur","item","child","children","temp","start","end","formatName","rootVal","unit","total","name","getCurrentTotalValue","undefined","recursionJson","palette","metadata","jsonObj","searchValue","data","filteredJson","structuredClone","currentVal","value","level","units","self","itemStyle","color","isItemNameMatchesSearchFilters","push","tableRecursionJson","structuredJson","itemName","filters","trim","toLocaleLowerCase","split","filter","s","length","every","toLowerCase","includes","findTotalSampleByName","seriesData","find","totalSample","Number"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function formatNanoDuration(value: number): string;
2
+ export declare function formatItemValue(unit: string | undefined, value: number): string;
3
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/utils/format.ts"],"names":[],"mappings":"AAeA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASxD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAuB/E"}
@@ -0,0 +1,71 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { msToPrometheusDuration, formatDuration, formatValue } from '@perses-dev/core';
14
+ export function formatNanoDuration(value) {
15
+ // The value to format is in nanoseconds
16
+ if (value < 1_000) {
17
+ return formatValue(value, {
18
+ unit: 'decimal',
19
+ decimalPlaces: 2,
20
+ shortValues: true
21
+ }) + 'ns';
22
+ } else if (value < 1_000_000) {
23
+ return formatValue(value / 1_000, {
24
+ unit: 'decimal',
25
+ decimalPlaces: 2,
26
+ shortValues: true
27
+ }) + 'μs';
28
+ } else {
29
+ return formatDuration(msToPrometheusDuration(value / 1_000_000));
30
+ }
31
+ }
32
+ export function formatItemValue(unit, value) {
33
+ let valueWithUnit = '';
34
+ switch(unit){
35
+ case 'count':
36
+ valueWithUnit = formatValue(value, {
37
+ unit: 'decimal',
38
+ decimalPlaces: 2,
39
+ shortValues: true
40
+ });
41
+ break;
42
+ case 'samples':
43
+ valueWithUnit = formatValue(value, {
44
+ unit: 'decimal',
45
+ decimalPlaces: 2,
46
+ shortValues: true
47
+ });
48
+ break;
49
+ case 'objects':
50
+ valueWithUnit = formatValue(value, {
51
+ unit: 'decimal',
52
+ decimalPlaces: 2,
53
+ shortValues: true
54
+ });
55
+ break;
56
+ case 'bytes':
57
+ valueWithUnit = formatValue(value, {
58
+ unit: 'bytes'
59
+ });
60
+ break;
61
+ case 'nanoseconds':
62
+ valueWithUnit = formatNanoDuration(value);
63
+ break;
64
+ default:
65
+ valueWithUnit = `${value} ${unit}`;
66
+ break;
67
+ }
68
+ return valueWithUnit;
69
+ }
70
+
71
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/format.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { msToPrometheusDuration, formatDuration, formatValue } from '@perses-dev/core';\n\nexport function formatNanoDuration(value: number): string {\n // The value to format is in nanoseconds\n if (value < 1_000) {\n return formatValue(value, { unit: 'decimal', decimalPlaces: 2, shortValues: true }) + 'ns';\n } else if (value < 1_000_000) {\n return formatValue(value / 1_000, { unit: 'decimal', decimalPlaces: 2, shortValues: true }) + 'μs';\n } else {\n return formatDuration(msToPrometheusDuration(value / 1_000_000));\n }\n}\n\nexport function formatItemValue(unit: string | undefined, value: number): string {\n let valueWithUnit = '';\n switch (unit) {\n case 'count':\n valueWithUnit = formatValue(value, { unit: 'decimal', decimalPlaces: 2, shortValues: true });\n break;\n case 'samples':\n valueWithUnit = formatValue(value, { unit: 'decimal', decimalPlaces: 2, shortValues: true });\n break;\n case 'objects':\n valueWithUnit = formatValue(value, { unit: 'decimal', decimalPlaces: 2, shortValues: true });\n break;\n case 'bytes':\n valueWithUnit = formatValue(value, { unit: 'bytes' });\n break;\n case 'nanoseconds':\n valueWithUnit = formatNanoDuration(value);\n break;\n default:\n valueWithUnit = `${value} ${unit}`;\n break;\n }\n return valueWithUnit;\n}\n"],"names":["msToPrometheusDuration","formatDuration","formatValue","formatNanoDuration","value","unit","decimalPlaces","shortValues","formatItemValue","valueWithUnit"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,sBAAsB,EAAEC,cAAc,EAAEC,WAAW,QAAQ,mBAAmB;AAEvF,OAAO,SAASC,mBAAmBC,KAAa;IAC9C,wCAAwC;IACxC,IAAIA,QAAQ,OAAO;QACjB,OAAOF,YAAYE,OAAO;YAAEC,MAAM;YAAWC,eAAe;YAAGC,aAAa;QAAK,KAAK;IACxF,OAAO,IAAIH,QAAQ,WAAW;QAC5B,OAAOF,YAAYE,QAAQ,OAAO;YAAEC,MAAM;YAAWC,eAAe;YAAGC,aAAa;QAAK,KAAK;IAChG,OAAO;QACL,OAAON,eAAeD,uBAAuBI,QAAQ;IACvD;AACF;AAEA,OAAO,SAASI,gBAAgBH,IAAwB,EAAED,KAAa;IACrE,IAAIK,gBAAgB;IACpB,OAAQJ;QACN,KAAK;YACHI,gBAAgBP,YAAYE,OAAO;gBAAEC,MAAM;gBAAWC,eAAe;gBAAGC,aAAa;YAAK;YAC1F;QACF,KAAK;YACHE,gBAAgBP,YAAYE,OAAO;gBAAEC,MAAM;gBAAWC,eAAe;gBAAGC,aAAa;YAAK;YAC1F;QACF,KAAK;YACHE,gBAAgBP,YAAYE,OAAO;gBAAEC,MAAM;gBAAWC,eAAe;gBAAGC,aAAa;YAAK;YAC1F;QACF,KAAK;YACHE,gBAAgBP,YAAYE,OAAO;gBAAEC,MAAM;YAAQ;YACnD;QACF,KAAK;YACHI,gBAAgBN,mBAAmBC;YACnC;QACF;YACEK,gBAAgB,GAAGL,MAAM,CAAC,EAAEC,MAAM;YAClC;IACJ;IACA,OAAOI;AACT"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Get span color, account for whether palette is 'package-name' or 'value'
3
+ */
4
+ export declare function getSpanColor(palette: string, functionName: string, value: number): string;
5
+ /**
6
+ * Generate a consistent color for displaying flame chart by total value
7
+ */
8
+ export declare function getColorByValue(value: number): string;
9
+ /**
10
+ * Generate a consistent span color for displaying flame chart by package-name
11
+ * (if function name includes 'error', it will have a red hue).
12
+ */
13
+ export declare function getColorByPackageName(functionName: string, value: number): string;
14
+ //# sourceMappingURL=palette-gen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette-gen.d.ts","sourceRoot":"","sources":["../../../src/utils/palette-gen.ts"],"names":[],"mappings":"AAkCA;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjF"}
@@ -0,0 +1,56 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { getConsistentColor } from './palette';
14
+ const LESS_THAN_ONE_COLOR = '#dee2e6'; // use this color when the value is less than 1
15
+ const MORE_THAN_HUNDRED_COLOR = '#ffbdbd'; // use this color when the value is more than 100
16
+ const NOT_FOUND_COLOR = '#393d47';
17
+ // Palette of color to display the flame chart by value
18
+ const valueColorPalette = [
19
+ '#fff85b',
20
+ '#ffde4c',
21
+ '#ffc252',
22
+ '#ff8c00',
23
+ '#f08c00',
24
+ '#e67762',
25
+ '#ff8c00',
26
+ '#ff6f00',
27
+ '#ff7070',
28
+ '#ff3300',
29
+ '#ff004c'
30
+ ];
31
+ /**
32
+ * Get span color, account for whether palette is 'package-name' or 'value'
33
+ */ export function getSpanColor(palette, functionName, value) {
34
+ if (palette === 'package-name') {
35
+ return getColorByPackageName(functionName, value);
36
+ }
37
+ return getColorByValue(value);
38
+ }
39
+ /**
40
+ * Generate a consistent color for displaying flame chart by total value
41
+ */ export function getColorByValue(value) {
42
+ if (value < 1) return LESS_THAN_ONE_COLOR;
43
+ if (value > 100) return MORE_THAN_HUNDRED_COLOR;
44
+ return valueColorPalette[Math.floor(value / (valueColorPalette.length - 1))] || NOT_FOUND_COLOR;
45
+ }
46
+ /**
47
+ * Generate a consistent span color for displaying flame chart by package-name
48
+ * (if function name includes 'error', it will have a red hue).
49
+ */ export function getColorByPackageName(functionName, value) {
50
+ // get package name from the function name.
51
+ // It is the substring between the last '/' and the first '.' or the end of the string
52
+ const packageName = functionName.split('/').pop()?.split('.')[0] || functionName;
53
+ return value < 1 ? LESS_THAN_ONE_COLOR : getConsistentColor(packageName, false);
54
+ }
55
+
56
+ //# sourceMappingURL=palette-gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/palette-gen.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { getConsistentColor } from './palette';\n\nconst LESS_THAN_ONE_COLOR = '#dee2e6'; // use this color when the value is less than 1\nconst MORE_THAN_HUNDRED_COLOR = '#ffbdbd'; // use this color when the value is more than 100\nconst NOT_FOUND_COLOR = '#393d47';\n\n// Palette of color to display the flame chart by value\nconst valueColorPalette: string[] = [\n '#fff85b',\n '#ffde4c',\n '#ffc252',\n '#ff8c00',\n '#f08c00',\n '#e67762',\n '#ff8c00',\n '#ff6f00',\n '#ff7070',\n '#ff3300',\n '#ff004c',\n];\n\n/**\n * Get span color, account for whether palette is 'package-name' or 'value'\n */\nexport function getSpanColor(palette: string, functionName: string, value: number): string {\n if (palette === 'package-name') {\n return getColorByPackageName(functionName, value);\n }\n\n return getColorByValue(value);\n}\n\n/**\n * Generate a consistent color for displaying flame chart by total value\n */\nexport function getColorByValue(value: number): string {\n if (value < 1) return LESS_THAN_ONE_COLOR;\n if (value > 100) return MORE_THAN_HUNDRED_COLOR;\n return valueColorPalette[Math.floor(value / (valueColorPalette.length - 1))] || NOT_FOUND_COLOR;\n}\n\n/**\n * Generate a consistent span color for displaying flame chart by package-name\n * (if function name includes 'error', it will have a red hue).\n */\nexport function getColorByPackageName(functionName: string, value: number): string {\n // get package name from the function name.\n // It is the substring between the last '/' and the first '.' or the end of the string\n const packageName = functionName.split('/').pop()?.split('.')[0] || functionName;\n\n return value < 1 ? LESS_THAN_ONE_COLOR : getConsistentColor(packageName, false);\n}\n"],"names":["getConsistentColor","LESS_THAN_ONE_COLOR","MORE_THAN_HUNDRED_COLOR","NOT_FOUND_COLOR","valueColorPalette","getSpanColor","palette","functionName","value","getColorByPackageName","getColorByValue","Math","floor","length","packageName","split","pop"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,kBAAkB,QAAQ,YAAY;AAE/C,MAAMC,sBAAsB,WAAW,+CAA+C;AACtF,MAAMC,0BAA0B,WAAW,iDAAiD;AAC5F,MAAMC,kBAAkB;AAExB,uDAAuD;AACvD,MAAMC,oBAA8B;IAClC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED;;CAEC,GACD,OAAO,SAASC,aAAaC,OAAe,EAAEC,YAAoB,EAAEC,KAAa;IAC/E,IAAIF,YAAY,gBAAgB;QAC9B,OAAOG,sBAAsBF,cAAcC;IAC7C;IAEA,OAAOE,gBAAgBF;AACzB;AAEA;;CAEC,GACD,OAAO,SAASE,gBAAgBF,KAAa;IAC3C,IAAIA,QAAQ,GAAG,OAAOP;IACtB,IAAIO,QAAQ,KAAK,OAAON;IACxB,OAAOE,iBAAiB,CAACO,KAAKC,KAAK,CAACJ,QAASJ,CAAAA,kBAAkBS,MAAM,GAAG,CAAA,GAAI,IAAIV;AAClF;AAEA;;;CAGC,GACD,OAAO,SAASM,sBAAsBF,YAAoB,EAAEC,KAAa;IACvE,2CAA2C;IAC3C,sFAAsF;IACtF,MAAMM,cAAcP,aAAaQ,KAAK,CAAC,KAAKC,GAAG,IAAID,MAAM,IAAI,CAAC,EAAE,IAAIR;IAEpE,OAAOC,QAAQ,IAAIP,sBAAsBD,mBAAmBc,aAAa;AAC3E"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Return a consistent color for (name, error) tuple
3
+ */
4
+ export declare function getConsistentColor(name: string, error: boolean): string;
5
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../../src/utils/palette.ts"],"names":[],"mappings":"AAiCA;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAQvE"}
@@ -0,0 +1,51 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import ColorHash from 'color-hash';
14
+ // Valid hue values are 0 to 360 and can be adjusted to control the generated colors.
15
+ // More info: https://github.com/zenozeng/color-hash#custom-hue
16
+ // Picked min of 20 and max of 360 to exclude common threshold colors (red).
17
+ // Items with "error" in them will always be generated as red.
18
+ const ERROR_HUE_CUTOFF = 20;
19
+ const colorGenerator = new ColorHash({
20
+ hue: {
21
+ min: ERROR_HUE_CUTOFF,
22
+ max: 360
23
+ }
24
+ });
25
+ const redColorGenerator = new ColorHash({
26
+ hue: {
27
+ min: 0,
28
+ max: ERROR_HUE_CUTOFF
29
+ }
30
+ });
31
+ function computeConsistentColor(name, error) {
32
+ const [hue, saturation, lightness] = error ? redColorGenerator.hsl(name) : colorGenerator.hsl(name);
33
+ const saturationPercent = `${(saturation * 100).toFixed(0)}%`;
34
+ const lightnessPercent = `${(lightness * 100).toFixed(0)}%`;
35
+ return `hsla(${hue.toFixed(2)},${saturationPercent},${lightnessPercent},0.9)`;
36
+ }
37
+ // To check whether a color has already been generated for a given string.
38
+ const colorLookup = {};
39
+ /**
40
+ * Return a consistent color for (name, error) tuple
41
+ */ export function getConsistentColor(name, error) {
42
+ const key = `${name}_____${error}`;
43
+ let value = colorLookup[key];
44
+ if (!value) {
45
+ value = computeConsistentColor(name, error);
46
+ colorLookup[key] = value;
47
+ }
48
+ return value;
49
+ }
50
+
51
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/palette.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport ColorHash from 'color-hash';\n\n// Valid hue values are 0 to 360 and can be adjusted to control the generated colors.\n// More info: https://github.com/zenozeng/color-hash#custom-hue\n// Picked min of 20 and max of 360 to exclude common threshold colors (red).\n// Items with \"error\" in them will always be generated as red.\nconst ERROR_HUE_CUTOFF = 20;\nconst colorGenerator = new ColorHash({ hue: { min: ERROR_HUE_CUTOFF, max: 360 } });\nconst redColorGenerator = new ColorHash({ hue: { min: 0, max: ERROR_HUE_CUTOFF } });\n\nfunction computeConsistentColor(name: string, error: boolean): string {\n const [hue, saturation, lightness] = error ? redColorGenerator.hsl(name) : colorGenerator.hsl(name);\n const saturationPercent = `${(saturation * 100).toFixed(0)}%`;\n const lightnessPercent = `${(lightness * 100).toFixed(0)}%`;\n return `hsla(${hue.toFixed(2)},${saturationPercent},${lightnessPercent},0.9)`;\n}\n\n// To check whether a color has already been generated for a given string.\nconst colorLookup: Record<string, string> = {};\n\n/**\n * Return a consistent color for (name, error) tuple\n */\nexport function getConsistentColor(name: string, error: boolean): string {\n const key = `${name}_____${error}`;\n let value = colorLookup[key];\n if (!value) {\n value = computeConsistentColor(name, error);\n colorLookup[key] = value;\n }\n return value;\n}\n"],"names":["ColorHash","ERROR_HUE_CUTOFF","colorGenerator","hue","min","max","redColorGenerator","computeConsistentColor","name","error","saturation","lightness","hsl","saturationPercent","toFixed","lightnessPercent","colorLookup","getConsistentColor","key","value"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,OAAOA,eAAe,aAAa;AAEnC,qFAAqF;AACrF,+DAA+D;AAC/D,4EAA4E;AAC5E,8DAA8D;AAC9D,MAAMC,mBAAmB;AACzB,MAAMC,iBAAiB,IAAIF,UAAU;IAAEG,KAAK;QAAEC,KAAKH;QAAkBI,KAAK;IAAI;AAAE;AAChF,MAAMC,oBAAoB,IAAIN,UAAU;IAAEG,KAAK;QAAEC,KAAK;QAAGC,KAAKJ;IAAiB;AAAE;AAEjF,SAASM,uBAAuBC,IAAY,EAAEC,KAAc;IAC1D,MAAM,CAACN,KAAKO,YAAYC,UAAU,GAAGF,QAAQH,kBAAkBM,GAAG,CAACJ,QAAQN,eAAeU,GAAG,CAACJ;IAC9F,MAAMK,oBAAoB,GAAG,AAACH,CAAAA,aAAa,GAAE,EAAGI,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAMC,mBAAmB,GAAG,AAACJ,CAAAA,YAAY,GAAE,EAAGG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3D,OAAO,CAAC,KAAK,EAAEX,IAAIW,OAAO,CAAC,GAAG,CAAC,EAAED,kBAAkB,CAAC,EAAEE,iBAAiB,KAAK,CAAC;AAC/E;AAEA,0EAA0E;AAC1E,MAAMC,cAAsC,CAAC;AAE7C;;CAEC,GACD,OAAO,SAASC,mBAAmBT,IAAY,EAAEC,KAAc;IAC7D,MAAMS,MAAM,GAAGV,KAAK,KAAK,EAAEC,OAAO;IAClC,IAAIU,QAAQH,WAAW,CAACE,IAAI;IAC5B,IAAI,CAACC,OAAO;QACVA,QAAQZ,uBAAuBC,MAAMC;QACrCO,WAAW,CAACE,IAAI,GAAGC;IACrB;IACA,OAAOA;AACT"}
@@ -0,0 +1,3 @@
1
+ import { SeriesSample } from './data-model';
2
+ export declare function getSeriesTooltip(data: SeriesSample, unit: string, name: string, color: string, divColor: string): string;
3
+ //# sourceMappingURL=series-tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"series-tooltip.d.ts","sourceRoot":"","sources":["../../../src/utils/series-tooltip.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,CAwBR"}
@@ -0,0 +1,43 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { formatItemValue } from './format';
14
+ export function getSeriesTooltip(data, unit, name, color, divColor) {
15
+ const date = new Date(data.value[0]);
16
+ const formattedDate = date.toLocaleDateString('en-US', {
17
+ month: 'short',
18
+ day: '2-digit',
19
+ year: 'numeric'
20
+ });
21
+ const formattedTime = date.toLocaleString('en-US', {
22
+ hour: '2-digit',
23
+ minute: '2-digit',
24
+ second: '2-digit',
25
+ hour12: false
26
+ });
27
+ return `
28
+ <div>
29
+ <div>
30
+ ${formattedDate} - <b>${formattedTime}</b>
31
+ </div>
32
+ <hr style="border: none; border-top: 1px solid ${divColor}" />
33
+ <div style="display: flex; align-items: center">
34
+ <div style="margin-right: 8px; display: inline-block; width: 11px; height: 11px; border-radius: 2px; background-color: ${color}"></div>
35
+ <div style="width: 100%; display: flex; justify-content: space-between" >
36
+ <span style="margin-right: 8px">${name}</span> <b>${formatItemValue(unit, data.value[1])}</b>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ `;
41
+ }
42
+
43
+ //# sourceMappingURL=series-tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/series-tooltip.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { SeriesSample } from './data-model';\nimport { formatItemValue } from './format';\n\nexport function getSeriesTooltip(\n data: SeriesSample,\n unit: string,\n name: string,\n color: string,\n divColor: string\n): string {\n const date = new Date(data.value[0]);\n const formattedDate = date.toLocaleDateString('en-US', { month: 'short', day: '2-digit', year: 'numeric' });\n const formattedTime = date.toLocaleString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n\n return `\n <div>\n <div>\n ${formattedDate} - <b>${formattedTime}</b>\n </div>\n <hr style=\"border: none; border-top: 1px solid ${divColor}\" />\n <div style=\"display: flex; align-items: center\">\n <div style=\"margin-right: 8px; display: inline-block; width: 11px; height: 11px; border-radius: 2px; background-color: ${color}\"></div>\n <div style=\"width: 100%; display: flex; justify-content: space-between\" >\n <span style=\"margin-right: 8px\">${name}</span> <b>${formatItemValue(unit, data.value[1])}</b>\n </div>\n </div>\n </div>\n `;\n}\n"],"names":["formatItemValue","getSeriesTooltip","data","unit","name","color","divColor","date","Date","value","formattedDate","toLocaleDateString","month","day","year","formattedTime","toLocaleString","hour","minute","second","hour12"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAGjC,SAASA,eAAe,QAAQ,WAAW;AAE3C,OAAO,SAASC,iBACdC,IAAkB,EAClBC,IAAY,EACZC,IAAY,EACZC,KAAa,EACbC,QAAgB;IAEhB,MAAMC,OAAO,IAAIC,KAAKN,KAAKO,KAAK,CAAC,EAAE;IACnC,MAAMC,gBAAgBH,KAAKI,kBAAkB,CAAC,SAAS;QAAEC,OAAO;QAASC,KAAK;QAAWC,MAAM;IAAU;IACzG,MAAMC,gBAAgBR,KAAKS,cAAc,CAAC,SAAS;QACjDC,MAAM;QACNC,QAAQ;QACRC,QAAQ;QACRC,QAAQ;IACV;IAEA,OAAO,CAAC;;;QAGF,EAAEV,cAAc,MAAM,EAAEK,cAAc;;qDAEO,EAAET,SAAS;;+HAE+D,EAAED,MAAM;;4CAE3F,EAAED,KAAK,WAAW,EAAEJ,gBAAgBG,MAAMD,KAAKO,KAAK,CAAC,EAAE,EAAE;;;;EAInG,CAAC;AACH"}
@@ -0,0 +1,6 @@
1
+ import { FlameChartSample } from './data-model';
2
+ /**
3
+ * Generates a tooltip for the flame chart items.
4
+ */
5
+ export declare function generateTooltip(params: FlameChartSample, unit: string | undefined): string;
6
+ //# sourceMappingURL=tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/utils/tooltip.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAW1F"}
@@ -0,0 +1,29 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import * as echarts from 'echarts';
14
+ import { formatItemValue } from './format';
15
+ /**
16
+ * Generates a tooltip for the flame chart items.
17
+ */ export function generateTooltip(params, unit) {
18
+ const totalPercentage = Number(params.value[4]);
19
+ const selfPercentage = Number(params.value[5]);
20
+ const functionName = params.value[6];
21
+ const total = Number(params.value[8]);
22
+ const self = Number(params.value[7]);
23
+ return `${functionName}<br/><br/>
24
+ Total: ${formatItemValue(unit, total)} (${totalPercentage.toFixed(2)}%)<br/>
25
+ Self: ${formatItemValue(unit, self)} (${selfPercentage.toFixed(2)}%)<br/>
26
+ Samples: ${echarts.format.addCommas(total)}`;
27
+ }
28
+
29
+ //# sourceMappingURL=tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/tooltip.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport * as echarts from 'echarts';\nimport { FlameChartSample } from './data-model';\nimport { formatItemValue } from './format';\n\n/**\n * Generates a tooltip for the flame chart items.\n */\nexport function generateTooltip(params: FlameChartSample, unit: string | undefined): string {\n const totalPercentage = Number(params.value[4]);\n const selfPercentage = Number(params.value[5]);\n const functionName = params.value[6];\n const total = Number(params.value[8]);\n const self = Number(params.value[7]);\n\n return `${functionName}<br/><br/>\n Total: ${formatItemValue(unit, total)} (${totalPercentage.toFixed(2)}%)<br/>\n Self: ${formatItemValue(unit, self)} (${selfPercentage.toFixed(2)}%)<br/>\n Samples: ${echarts.format.addCommas(total)}`;\n}\n"],"names":["echarts","formatItemValue","generateTooltip","params","unit","totalPercentage","Number","value","selfPercentage","functionName","total","self","toFixed","format","addCommas"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,YAAYA,aAAa,UAAU;AAEnC,SAASC,eAAe,QAAQ,WAAW;AAE3C;;CAEC,GACD,OAAO,SAASC,gBAAgBC,MAAwB,EAAEC,IAAwB;IAChF,MAAMC,kBAAkBC,OAAOH,OAAOI,KAAK,CAAC,EAAE;IAC9C,MAAMC,iBAAiBF,OAAOH,OAAOI,KAAK,CAAC,EAAE;IAC7C,MAAME,eAAeN,OAAOI,KAAK,CAAC,EAAE;IACpC,MAAMG,QAAQJ,OAAOH,OAAOI,KAAK,CAAC,EAAE;IACpC,MAAMI,OAAOL,OAAOH,OAAOI,KAAK,CAAC,EAAE;IAEnC,OAAO,GAAGE,aAAa;mBACN,EAAER,gBAAgBG,MAAMM,OAAO,EAAE,EAAEL,gBAAgBO,OAAO,CAAC,GAAG;kBAC/D,EAAEX,gBAAgBG,MAAMO,MAAM,EAAE,EAAEH,eAAeI,OAAO,CAAC,GAAG;qBACzD,EAAEZ,QAAQa,MAAM,CAACC,SAAS,CAACJ,QAAQ;AACxD"}
@@ -0,0 +1,9 @@
1
+ export declare const TOOLTIP_TEXT: {
2
+ resetFlameGraph: string;
3
+ changeColorSheme: string;
4
+ exportData: string;
5
+ showTable: string;
6
+ showFlameGraph: string;
7
+ showBoth: string;
8
+ };
9
+ //# sourceMappingURL=ui-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-text.d.ts","sourceRoot":"","sources":["../../../src/utils/ui-text.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC"}
@@ -0,0 +1,22 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ export const TOOLTIP_TEXT = {
14
+ resetFlameGraph: 'Reset graph',
15
+ changeColorSheme: 'Change color sheme',
16
+ exportData: 'Export profile data',
17
+ showTable: 'Only show table',
18
+ showFlameGraph: 'Only show flame graph',
19
+ showBoth: 'Show both the table and flame graph'
20
+ };
21
+
22
+ //# sourceMappingURL=ui-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/ui-text.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport const TOOLTIP_TEXT = {\n resetFlameGraph: 'Reset graph',\n changeColorSheme: 'Change color sheme',\n exportData: 'Export profile data',\n showTable: 'Only show table',\n showFlameGraph: 'Only show flame graph',\n showBoth: 'Show both the table and flame graph',\n};\n"],"names":["TOOLTIP_TEXT","resetFlameGraph","changeColorSheme","exportData","showTable","showFlameGraph","showBoth"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,OAAO,MAAMA,eAAe;IAC1BC,iBAAiB;IACjBC,kBAAkB;IAClBC,YAAY;IACZC,WAAW;IACXC,gBAAgB;IAChBC,UAAU;AACZ,EAAE"}
@@ -0,0 +1,36 @@
1
+ import { FlameChartOptionsEditorProps } from '../flame-chart-model';
2
+ /**
3
+ * Hook to manage `palette` state.
4
+ */
5
+ export declare function usePaletteState(props: FlameChartOptionsEditorProps): {
6
+ handlePaletteChange: (newPalette: 'package-name' | 'value') => void;
7
+ };
8
+ /**
9
+ * Hook to manage `showSettings` state.
10
+ */
11
+ export declare function useShowSettingsState(props: FlameChartOptionsEditorProps): {
12
+ handleShowSettingsChange: (newValue: boolean) => void;
13
+ };
14
+ /**
15
+ * Hook to manage `showSeries` state.
16
+ */
17
+ export declare function useShowSeriesState(props: FlameChartOptionsEditorProps): {
18
+ handleShowSeriesChange: (newValue: boolean) => void;
19
+ };
20
+ /**
21
+ * Hook to manage `showTable` state.
22
+ */
23
+ export declare function useShowTableState(props: FlameChartOptionsEditorProps): {
24
+ handleShowTableChange: (newValue: boolean) => void;
25
+ };
26
+ /**
27
+ * Hook to manage `showFlameGraph` state.
28
+ */
29
+ export declare function useShowFlameGraphState(props: FlameChartOptionsEditorProps): {
30
+ handleShowFlameGraphChange: (newValue: boolean) => void;
31
+ };
32
+ /**
33
+ * Reset all settings to their initial values
34
+ */
35
+ export declare function resetSettings(props: FlameChartOptionsEditorProps): void;
36
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/utils.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,4BAA4B,GAAG;IACpE,mBAAmB,EAAE,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,KAAK,IAAI,CAAC;CACrE,CAYA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,4BAA4B,GAAG;IACzE,wBAAwB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,CAYA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,4BAA4B,GAAG;IACvE,sBAAsB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD,CAYA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,4BAA4B,GAAG;IACtE,qBAAqB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD,CAYA;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,4BAA4B,GAAG;IAC3E,0BAA0B,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACzD,CAYA;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,4BAA4B,GAAG,IAAI,CAYvE"}