@parca/profile 0.19.140 → 0.19.143

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 (182) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/GraphTooltipArrow/Content.js +224 -30
  3. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +192 -33
  4. package/dist/GraphTooltipArrow/ExpandOnHoverValue.js +53 -3
  5. package/dist/GraphTooltipArrow/index.d.ts.map +1 -1
  6. package/dist/GraphTooltipArrow/index.js +86 -56
  7. package/dist/GraphTooltipArrow/useGraphTooltip/index.js +37 -37
  8. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +94 -68
  9. package/dist/MatchersInput/SuggestionItem.js +91 -12
  10. package/dist/MatchersInput/SuggestionsList.d.ts +2 -1
  11. package/dist/MatchersInput/SuggestionsList.d.ts.map +1 -1
  12. package/dist/MatchersInput/SuggestionsList.js +371 -157
  13. package/dist/MatchersInput/SuggestionsList.test.d.ts +2 -0
  14. package/dist/MatchersInput/SuggestionsList.test.d.ts.map +1 -0
  15. package/dist/MatchersInput/index.js +308 -115
  16. package/dist/MetricsCircle/index.js +39 -3
  17. package/dist/MetricsGraph/MetricsContextMenu/index.js +119 -19
  18. package/dist/MetricsGraph/MetricsInfoPanel/index.js +81 -20
  19. package/dist/MetricsGraph/MetricsTooltip/index.d.ts.map +1 -1
  20. package/dist/MetricsGraph/MetricsTooltip/index.js +107 -74
  21. package/dist/MetricsGraph/index.js +552 -203
  22. package/dist/MetricsGraph/useMetricsGraphDimensions.js +46 -25
  23. package/dist/MetricsGraph/utils/colorMapping.js +24 -17
  24. package/dist/MetricsSeries/index.js +70 -7
  25. package/dist/PreSelectedMatchers/index.d.ts.map +1 -1
  26. package/dist/PreSelectedMatchers/index.js +249 -102
  27. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  28. package/dist/ProfileExplorer/ProfileExplorerCompare.js +240 -45
  29. package/dist/ProfileExplorer/ProfileExplorerSingle.js +98 -11
  30. package/dist/ProfileExplorer/index.js +183 -32
  31. package/dist/ProfileFlameChart/SamplesStrips/SamplesGraph/index.js +333 -148
  32. package/dist/ProfileFlameChart/SamplesStrips/SamplesStrips.stories.js +69 -35
  33. package/dist/ProfileFlameChart/SamplesStrips/index.js +645 -134
  34. package/dist/ProfileFlameChart/SamplesStrips/labelSetUtils.js +114 -55
  35. package/dist/ProfileFlameChart/index.js +260 -126
  36. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +283 -85
  37. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenuWrapper.js +56 -20
  38. package/dist/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.js +211 -140
  39. package/dist/ProfileFlameGraph/FlameGraphArrow/MemoizedTooltip.js +133 -38
  40. package/dist/ProfileFlameGraph/FlameGraphArrow/MiniMap.js +261 -216
  41. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
  42. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +71 -45
  43. package/dist/ProfileFlameGraph/FlameGraphArrow/TooltipContext.d.ts.map +1 -1
  44. package/dist/ProfileFlameGraph/FlameGraphArrow/TooltipContext.js +58 -28
  45. package/dist/ProfileFlameGraph/FlameGraphArrow/ZoomControls.d.ts.map +1 -1
  46. package/dist/ProfileFlameGraph/FlameGraphArrow/ZoomControls.js +59 -8
  47. package/dist/ProfileFlameGraph/FlameGraphArrow/index.js +396 -179
  48. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.d.ts.map +1 -1
  49. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.js +68 -50
  50. package/dist/ProfileFlameGraph/FlameGraphArrow/useMappingList.js +62 -38
  51. package/dist/ProfileFlameGraph/FlameGraphArrow/useNodeColor.js +14 -6
  52. package/dist/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.js +124 -82
  53. package/dist/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.js +160 -98
  54. package/dist/ProfileFlameGraph/FlameGraphArrow/useZoom.js +232 -112
  55. package/dist/ProfileFlameGraph/FlameGraphArrow/utils.js +137 -114
  56. package/dist/ProfileFlameGraph/benchmarks/benchdata/populateData.js +85 -0
  57. package/dist/ProfileFlameGraph/index.js +322 -147
  58. package/dist/ProfileMetricsGraph/hooks/useQueryRange.js +140 -32
  59. package/dist/ProfileMetricsGraph/index.js +515 -256
  60. package/dist/ProfileSelector/CompareButton.js +132 -12
  61. package/dist/ProfileSelector/MetricsGraphSection.js +228 -63
  62. package/dist/ProfileSelector/index.d.ts +1 -1
  63. package/dist/ProfileSelector/index.d.ts.map +1 -1
  64. package/dist/ProfileSelector/index.js +734 -142
  65. package/dist/ProfileSelector/useAutoQuerySelector.d.ts +1 -3
  66. package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
  67. package/dist/ProfileSelector/useAutoQuerySelector.js +280 -132
  68. package/dist/ProfileSource.js +230 -163
  69. package/dist/ProfileTypeSelector/index.js +214 -125
  70. package/dist/ProfileView/components/ActionButtons/GroupByDropdown.js +50 -4
  71. package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +137 -32
  72. package/dist/ProfileView/components/ColorStackLegend.js +182 -54
  73. package/dist/ProfileView/components/DashboardItems/index.js +87 -28
  74. package/dist/ProfileView/components/DashboardLayout/index.js +108 -16
  75. package/dist/ProfileView/components/DiffLegend.js +172 -29
  76. package/dist/ProfileView/components/GroupByLabelsDropdown/index.js +199 -55
  77. package/dist/ProfileView/components/InvertCallStack/index.js +97 -9
  78. package/dist/ProfileView/components/ProfileFilters/filterPresets.js +260 -315
  79. package/dist/ProfileView/components/ProfileFilters/index.js +518 -215
  80. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +370 -306
  81. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +191 -118
  82. package/dist/ProfileView/components/ProfileHeader/index.js +105 -11
  83. package/dist/ProfileView/components/ShareButton/ResultBox.js +119 -16
  84. package/dist/ProfileView/components/ShareButton/index.js +352 -62
  85. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
  86. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +664 -192
  87. package/dist/ProfileView/components/Toolbars/SwitchMenuItem.js +94 -7
  88. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +196 -155
  89. package/dist/ProfileView/components/Toolbars/index.js +441 -21
  90. package/dist/ProfileView/components/ViewSelector/Dropdown.js +233 -22
  91. package/dist/ProfileView/components/ViewSelector/index.js +186 -82
  92. package/dist/ProfileView/components/VisualizationContainer/index.d.ts.map +1 -1
  93. package/dist/ProfileView/components/VisualizationContainer/index.js +52 -7
  94. package/dist/ProfileView/components/VisualizationPanel.js +185 -8
  95. package/dist/ProfileView/context/DashboardContext.js +74 -26
  96. package/dist/ProfileView/context/ProfileViewContext.js +56 -15
  97. package/dist/ProfileView/hooks/useAutoSelectDimension.js +71 -41
  98. package/dist/ProfileView/hooks/useProfileMetadata.js +50 -18
  99. package/dist/ProfileView/hooks/useResetFlameGraphState.js +31 -10
  100. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +71 -27
  101. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +53 -17
  102. package/dist/ProfileView/hooks/useVisualizationState.js +229 -69
  103. package/dist/ProfileView/index.js +383 -45
  104. package/dist/ProfileView/types/visualization.js +1 -13
  105. package/dist/ProfileView/utils/colorUtils.js +8 -7
  106. package/dist/ProfileViewWithData.js +319 -225
  107. package/dist/QueryControls/index.js +418 -47
  108. package/dist/Sandwich/components/CalleesSection.js +54 -4
  109. package/dist/Sandwich/components/CallersSection.js +97 -27
  110. package/dist/Sandwich/components/TableSection.js +77 -4
  111. package/dist/Sandwich/index.js +125 -12
  112. package/dist/Sandwich/utils/processRowData.js +48 -39
  113. package/dist/SelectWithRefresh/index.js +102 -28
  114. package/dist/SimpleMatchers/Select.js +520 -187
  115. package/dist/SimpleMatchers/index.js +590 -288
  116. package/dist/SourceView/Highlighter.js +230 -70
  117. package/dist/SourceView/LineNo.js +72 -17
  118. package/dist/SourceView/index.js +177 -101
  119. package/dist/SourceView/lang-detector/ext-to-lang.json +798 -798
  120. package/dist/SourceView/lang-detector/index.js +28 -14
  121. package/dist/SourceView/useSelectedLineRange.js +72 -20
  122. package/dist/Table/ColorCell.js +42 -1
  123. package/dist/Table/ColumnsVisibility.js +114 -6
  124. package/dist/Table/MoreDropdown.js +107 -21
  125. package/dist/Table/TableContextMenu.js +144 -134
  126. package/dist/Table/TableContextMenuWrapper.js +59 -14
  127. package/dist/Table/hooks/useColorManagement.js +58 -16
  128. package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
  129. package/dist/Table/hooks/useTableConfiguration.js +323 -167
  130. package/dist/Table/index.js +217 -123
  131. package/dist/Table/utils/functions.js +169 -144
  132. package/dist/Table/utils/topAndBottomExpandedRowModel.js +69 -52
  133. package/dist/TimelineGuide/index.js +209 -16
  134. package/dist/TopTable/benchmarks/benchdata/populateData.js +91 -0
  135. package/dist/TopTable/index.js +325 -121
  136. package/dist/contexts/LabelsQueryProvider.js +94 -32
  137. package/dist/contexts/UnifiedLabelsContext.js +114 -49
  138. package/dist/contexts/utils.js +37 -15
  139. package/dist/hooks/urlParsers.js +27 -15
  140. package/dist/hooks/useColorBy.js +47 -10
  141. package/dist/hooks/useCompareModeMeta.js +112 -62
  142. package/dist/hooks/useDashboardItems.js +52 -11
  143. package/dist/hooks/useLabels.js +295 -52
  144. package/dist/hooks/useQueryState.d.ts +1 -1
  145. package/dist/hooks/useQueryState.d.ts.map +1 -1
  146. package/dist/hooks/useQueryState.js +375 -329
  147. package/dist/index.js +11 -6
  148. package/dist/testdata/fg-diff.json +3750 -0
  149. package/dist/testdata/fg-simple.json +1879 -0
  150. package/dist/testdata/link_data.json +56 -0
  151. package/dist/testdata/tabular.json +30 -0
  152. package/dist/testdata/test_flamegraph.json +26846 -0
  153. package/dist/testdata/test_graph.json +53 -0
  154. package/dist/useDelayedLoader.js +32 -18
  155. package/dist/useGrpcQuery/index.js +71 -11
  156. package/dist/useHasProfileData.js +90 -12
  157. package/dist/useQuery.js +205 -64
  158. package/dist/useSumBy.d.ts.map +1 -1
  159. package/dist/useSumBy.js +294 -138
  160. package/dist/utils.js +62 -30
  161. package/package.json +9 -9
  162. package/src/GraphTooltipArrow/index.tsx +3 -0
  163. package/src/MatchersInput/SuggestionsList.test.tsx +70 -0
  164. package/src/MatchersInput/SuggestionsList.tsx +11 -10
  165. package/src/MatchersInput/index.tsx +1 -1
  166. package/src/MetricsGraph/MetricsTooltip/index.tsx +22 -34
  167. package/src/PreSelectedMatchers/index.tsx +3 -0
  168. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +9 -2
  169. package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +3 -0
  170. package/src/ProfileFlameGraph/FlameGraphArrow/TooltipContext.tsx +3 -0
  171. package/src/ProfileFlameGraph/FlameGraphArrow/ZoomControls.tsx +3 -0
  172. package/src/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.ts +3 -0
  173. package/src/ProfileSelector/index.tsx +31 -9
  174. package/src/ProfileSelector/useAutoQuerySelector.ts +64 -42
  175. package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +3 -0
  176. package/src/ProfileView/components/VisualizationContainer/index.tsx +3 -0
  177. package/src/Table/hooks/useTableConfiguration.tsx +7 -13
  178. package/src/hooks/useQueryState.ts +18 -3
  179. package/src/useDelayedLoader.ts +10 -10
  180. package/src/useSumBy.ts +12 -18
  181. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.js +0 -455
  182. package/dist/hooks/useQueryState.test.js +0 -868
@@ -1,4 +1,16 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
8
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
11
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
+ import { c as _c } from "react-compiler-runtime";
2
14
  // Copyright 2022 The Parca Authors
3
15
  // Licensed under the Apache License, Version 2.0 (the "License");
4
16
  // you may not use this file except in compliance with the License.
@@ -11,11 +23,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
23
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
24
  // See the License for the specific language governing permissions and
13
25
  // limitations under the License.
26
+
14
27
  import { useEffect, useMemo, useState } from 'react';
15
28
  import { Icon } from '@iconify/react';
16
29
  import { AnimatePresence, motion } from 'framer-motion';
17
30
  import { useQueryState } from 'nuqs';
18
- import { MetricsGraphSkeleton, TextWithTooltip, useParcaContext, } from '@parca/components';
31
+ import { MetricsGraphSkeleton, TextWithTooltip, useParcaContext } from '@parca/components';
19
32
  import { Query } from '@parca/parser';
20
33
  import { TEST_IDS, testId } from '@parca/test-utils';
21
34
  import { capitalizeOnlyFirstLetter, formatDate, timePattern, valueFormatter } from '@parca/utilities';
@@ -24,270 +37,516 @@ import MetricsGraph from '../MetricsGraph';
24
37
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
25
38
  import { intParam } from '../hooks/urlParsers';
26
39
  import { getStepCountFromScreenWidth, useQueryRange } from './hooks/useQueryRange';
27
- const createProfileContextMenuItems = (addLabelMatcher, data // The original MetricsSeriesPb[] data
28
- ) => {
29
- return [
30
- {
31
- id: 'focus-on-single-series',
32
- label: 'Focus only on this series',
33
- icon: 'ph:star',
34
- onClick: (closestPoint, _series) => {
35
- if (closestPoint != null && data.length > 0 && data[closestPoint.seriesIndex] != null) {
36
- const originalSeriesData = data[closestPoint.seriesIndex];
37
- if (originalSeriesData.labelset?.labels != null) {
38
- const labels = originalSeriesData.labelset.labels.filter((label) => label.name !== '__name__');
39
- const labelsToAdd = labels.map((label) => ({
40
- key: label.name,
41
- value: label.value,
42
- }));
43
- addLabelMatcher(labelsToAdd);
44
- }
45
- }
46
- },
47
- },
48
- {
49
- id: 'add-to-query',
50
- label: 'Add to query',
51
- icon: 'material-symbols:add',
52
- createDynamicItems: (closestPoint, _series) => {
53
- const noLabelsAvailable = [
54
- {
55
- id: 'no-labels-available',
56
- label: 'No labels available',
57
- icon: 'ph:warning',
58
- disabled: () => true,
59
- onClick: () => { }, // No-op for disabled item
60
- },
61
- ];
62
- if (closestPoint == null || data.length === 0 || data[closestPoint.seriesIndex] == null) {
63
- return noLabelsAvailable;
64
- }
65
- const originalSeriesData = data[closestPoint.seriesIndex];
66
- if (originalSeriesData.labelset?.labels == null) {
67
- return noLabelsAvailable;
68
- }
69
- const labels = originalSeriesData.labelset.labels.filter((label) => label.name !== '__name__');
70
- if (labels.length === 0) {
71
- return noLabelsAvailable;
72
- }
73
- return labels.map((label) => ({
74
- id: `add-label-${label.name}`,
75
- label: (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-300", children: `${label.name}="${label.value}"` })),
76
- onClick: () => {
77
- addLabelMatcher({
78
- key: label.name,
79
- value: label.value,
80
- });
81
- },
82
- }));
83
- },
40
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
41
+ var createProfileContextMenuItems = function createProfileContextMenuItems(addLabelMatcher, data) {
42
+ return [{
43
+ id: 'focus-on-single-series',
44
+ label: 'Focus only on this series',
45
+ icon: 'ph:star',
46
+ onClick: function onClick(closestPoint, _series) {
47
+ if (closestPoint != null && data.length > 0 && data[closestPoint.seriesIndex] != null) {
48
+ var _originalSeriesData$l;
49
+ var originalSeriesData = data[closestPoint.seriesIndex];
50
+ if (((_originalSeriesData$l = originalSeriesData.labelset) === null || _originalSeriesData$l === void 0 ? void 0 : _originalSeriesData$l.labels) != null) {
51
+ var labels = originalSeriesData.labelset.labels.filter(function (label) {
52
+ return label.name !== '__name__';
53
+ });
54
+ var labelsToAdd = labels.map(function (label) {
55
+ return {
56
+ key: label.name,
57
+ value: label.value
58
+ };
59
+ });
60
+ addLabelMatcher(labelsToAdd);
61
+ }
62
+ }
63
+ }
64
+ }, {
65
+ id: 'add-to-query',
66
+ label: 'Add to query',
67
+ icon: 'material-symbols:add',
68
+ createDynamicItems: function createDynamicItems(closestPoint, _series) {
69
+ var _originalSeriesData$l2;
70
+ var noLabelsAvailable = [{
71
+ id: 'no-labels-available',
72
+ label: 'No labels available',
73
+ icon: 'ph:warning',
74
+ disabled: function disabled() {
75
+ return true;
84
76
  },
85
- ];
86
- };
87
- const transformMetricsData = (data) => {
88
- const series = data.reduce((agg, s) => {
89
- if (s.labelset !== undefined) {
90
- // Generate ID from sorted labelsets
91
- const labels = s.labelset.labels ?? [];
92
- const sortedLabels = labels
93
- .filter(label => label.name !== '__name__') // Exclude __name__ from ID generation
94
- .sort((a, b) => a.name.localeCompare(b.name));
95
- const id = sortedLabels.map(label => `${label.name}=${label.value}`).join(',');
96
- agg.push({
97
- id: id !== '' ? id : 'default', // fallback to 'default' if no labels
98
- values: s.samples.reduce((agg, d) => {
99
- if (d.timestamp !== undefined && d.valuePerSecond !== undefined) {
100
- const timestampMs = Number(d.timestamp.seconds) * 1000 + d.timestamp.nanos / 1000000;
101
- agg.push([timestampMs, d.valuePerSecond]);
102
- }
103
- return agg;
104
- }, []),
77
+ onClick: function onClick() {} // No-op for disabled item
78
+ }];
79
+ if (closestPoint == null || data.length === 0 || data[closestPoint.seriesIndex] == null) {
80
+ return noLabelsAvailable;
81
+ }
82
+ var originalSeriesData = data[closestPoint.seriesIndex];
83
+ if (((_originalSeriesData$l2 = originalSeriesData.labelset) === null || _originalSeriesData$l2 === void 0 ? void 0 : _originalSeriesData$l2.labels) == null) {
84
+ return noLabelsAvailable;
85
+ }
86
+ var labels = originalSeriesData.labelset.labels.filter(function (label) {
87
+ return label.name !== '__name__';
88
+ });
89
+ if (labels.length === 0) {
90
+ return noLabelsAvailable;
91
+ }
92
+ return labels.map(function (label) {
93
+ return {
94
+ id: "add-label-".concat(label.name),
95
+ label: /*#__PURE__*/_jsx("div", {
96
+ className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-300",
97
+ children: "".concat(label.name, "=\"").concat(label.value, "\"")
98
+ }),
99
+ onClick: function onClick() {
100
+ addLabelMatcher({
101
+ key: label.name,
102
+ value: label.value
105
103
  });
106
- }
107
- return agg;
108
- }, []);
109
- return series;
104
+ }
105
+ };
106
+ });
107
+ }
108
+ }];
109
+ };
110
+ var transformMetricsData = function transformMetricsData(data) {
111
+ var series = data.reduce(function (agg, s) {
112
+ if (s.labelset !== undefined) {
113
+ var _s$labelset$labels;
114
+ // Generate ID from sorted labelsets
115
+ var labels = (_s$labelset$labels = s.labelset.labels) !== null && _s$labelset$labels !== void 0 ? _s$labelset$labels : [];
116
+ var sortedLabels = labels.filter(function (label) {
117
+ return label.name !== '__name__';
118
+ }) // Exclude __name__ from ID generation
119
+ .sort(function (a, b) {
120
+ return a.name.localeCompare(b.name);
121
+ });
122
+ var id = sortedLabels.map(function (label) {
123
+ return "".concat(label.name, "=").concat(label.value);
124
+ }).join(',');
125
+ agg.push({
126
+ id: id !== '' ? id : 'default',
127
+ // fallback to 'default' if no labels
128
+ values: s.samples.reduce(function (agg, d) {
129
+ if (d.timestamp !== undefined && d.valuePerSecond !== undefined) {
130
+ var timestampMs = Number(d.timestamp.seconds) * 1000 + d.timestamp.nanos / 1000000;
131
+ agg.push([timestampMs, d.valuePerSecond]);
132
+ }
133
+ return agg;
134
+ }, [])
135
+ });
136
+ }
137
+ return agg;
138
+ }, []);
139
+ return series;
110
140
  };
111
- const ErrorContent = ({ errorMessage }) => {
112
- return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
141
+ var ErrorContent = function ErrorContent(t0) {
142
+ var $ = _c(2);
143
+ var errorMessage = t0.errorMessage;
144
+ var t1;
145
+ if ($[0] !== errorMessage) {
146
+ t1 = /*#__PURE__*/_jsx("div", {
147
+ className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700",
148
+ role: "alert",
149
+ children: /*#__PURE__*/_jsx("span", {
150
+ className: "block sm:inline",
151
+ children: errorMessage
152
+ })
153
+ });
154
+ $[0] = errorMessage;
155
+ $[1] = t1;
156
+ } else {
157
+ t1 = $[1];
158
+ }
159
+ return t1;
113
160
  };
114
- export const ProfileMetricsEmptyState = ({ message }) => {
115
- return (_jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: _jsx("p", { children: message }) }));
161
+ export var ProfileMetricsEmptyState = function ProfileMetricsEmptyState(t0) {
162
+ var $ = _c(2);
163
+ var message = t0.message;
164
+ var t1;
165
+ if ($[0] !== message) {
166
+ t1 = /*#__PURE__*/_jsx("div", {
167
+ className: "flex h-full w-full flex-col items-center justify-center",
168
+ children: /*#__PURE__*/_jsx("p", {
169
+ children: message
170
+ })
171
+ });
172
+ $[0] = message;
173
+ $[1] = t1;
174
+ } else {
175
+ t1 = $[1];
176
+ }
177
+ return t1;
116
178
  };
117
- const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, sumBy, }) => {
118
- const [rawStepCount] = useQueryState('step_count', intParam.withDefault(getStepCountFromScreenWidth(10)));
119
- // Clamp step count so the step duration is at least 1 second as we don't have this enforced server-side anymore.
120
- const stepCount = useMemo(() => {
121
- const maxForOneSecond = Math.floor((to - from) / 1000);
122
- return Math.min(rawStepCount, maxForOneSecond);
123
- }, [rawStepCount, from, to]);
124
- const { isLoading: metricsGraphLoading, response, error, } = useQueryRange(queryClient, queryExpression, from, to, sumBy, stepCount, queryExpression === '');
125
- const { onError, perf, authenticationErrorMessage, isDarkMode, timezone, profileExplorer } = useParcaContext();
126
- const { width, height, margin, heightStyle } = useMetricsGraphDimensions(comparing, profileExplorer?.metricsGraph.height);
127
- const [showAllSeriesForResponse, setShowAllSeriesForResponse] = useState(null);
128
- useEffect(() => {
129
- if (error !== null) {
130
- onError?.(error);
179
+ var ProfileMetricsGraph = function ProfileMetricsGraph(_ref) {
180
+ var queryClient = _ref.queryClient,
181
+ queryExpression = _ref.queryExpression,
182
+ profile = _ref.profile,
183
+ from = _ref.from,
184
+ to = _ref.to,
185
+ setTimeRange = _ref.setTimeRange,
186
+ addLabelMatcher = _ref.addLabelMatcher,
187
+ onPointClick = _ref.onPointClick,
188
+ _ref$comparing = _ref.comparing,
189
+ comparing = _ref$comparing === void 0 ? false : _ref$comparing,
190
+ sumBy = _ref.sumBy;
191
+ var _useQueryState = useQueryState('step_count', intParam.withDefault(getStepCountFromScreenWidth(10))),
192
+ _useQueryState2 = _slicedToArray(_useQueryState, 1),
193
+ rawStepCount = _useQueryState2[0];
194
+ // Clamp step count so the step duration is at least 1 second as we don't have this enforced server-side anymore.
195
+ var stepCount = useMemo(function () {
196
+ var maxForOneSecond = Math.floor((to - from) / 1000);
197
+ return Math.min(rawStepCount, maxForOneSecond);
198
+ }, [rawStepCount, from, to]);
199
+ var _useQueryRange = useQueryRange(queryClient, queryExpression, from, to, sumBy, stepCount, queryExpression === ''),
200
+ metricsGraphLoading = _useQueryRange.isLoading,
201
+ response = _useQueryRange.response,
202
+ error = _useQueryRange.error;
203
+ var _useParcaContext = useParcaContext(),
204
+ onError = _useParcaContext.onError,
205
+ perf = _useParcaContext.perf,
206
+ authenticationErrorMessage = _useParcaContext.authenticationErrorMessage,
207
+ isDarkMode = _useParcaContext.isDarkMode,
208
+ timezone = _useParcaContext.timezone,
209
+ profileExplorer = _useParcaContext.profileExplorer;
210
+ var _useMetricsGraphDimen = useMetricsGraphDimensions(comparing, profileExplorer === null || profileExplorer === void 0 ? void 0 : profileExplorer.metricsGraph.height),
211
+ width = _useMetricsGraphDimen.width,
212
+ height = _useMetricsGraphDimen.height,
213
+ margin = _useMetricsGraphDimen.margin,
214
+ heightStyle = _useMetricsGraphDimen.heightStyle;
215
+ var _useState = useState(null),
216
+ _useState2 = _slicedToArray(_useState, 2),
217
+ showAllSeriesForResponse = _useState2[0],
218
+ setShowAllSeriesForResponse = _useState2[1];
219
+ useEffect(function () {
220
+ if (error !== null) {
221
+ onError === null || onError === void 0 || onError(error);
222
+ }
223
+ }, [error, onError]);
224
+
225
+ // Reset showAllSeriesForResponse when response changes to free memory
226
+ useEffect(function () {
227
+ setShowAllSeriesForResponse(null);
228
+ }, [response]);
229
+ useEffect(function () {
230
+ if (response === null) {
231
+ return;
232
+ }
233
+ perf === null || perf === void 0 || perf.markInteraction('Metrics graph render', response.series[0].samples.length);
234
+ }, [perf, response]);
235
+ var _useMemo = useMemo(function () {
236
+ if ((response === null || response === void 0 ? void 0 : response.series) != null) {
237
+ // Check if user wants ALL series for THIS specific response
238
+ var userWantsAllForThisResponse = showAllSeriesForResponse === response;
239
+ var maxSeriesLimit = 100;
240
+
241
+ // Limit the number of series to maxSeriesLimit to avoid performance issues (unless user opts to show all)
242
+ if (response.series.length > maxSeriesLimit && !userWantsAllForThisResponse) {
243
+ // Select top `maxSeriesLimit` series based on their max value (to catch series with large spikes)
244
+ var seriesWithMaxValue = response.series.map(function (series) {
245
+ var maxValue = series.samples.reduce(function (max, sample) {
246
+ var _sample$valuePerSecon;
247
+ var value = (_sample$valuePerSecon = sample.valuePerSecond) !== null && _sample$valuePerSecon !== void 0 ? _sample$valuePerSecon : 0;
248
+ return value > max ? value : max;
249
+ }, 0);
250
+ return {
251
+ series: series,
252
+ maxValue: maxValue
253
+ };
254
+ });
255
+
256
+ // Sort by max value descending and take top `maxSeriesLimit` series
257
+ var topSeries = seriesWithMaxValue.sort(function (a, b) {
258
+ return b.maxValue - a.maxValue;
259
+ }).slice(0, maxSeriesLimit).map(function (item) {
260
+ return item.series;
261
+ });
262
+ return [topSeries, {
263
+ isTrimmed: true,
264
+ beforeTrim: response.series.length,
265
+ afterTrim: maxSeriesLimit
266
+ }];
131
267
  }
132
- }, [error, onError]);
133
- // Reset showAllSeriesForResponse when response changes to free memory
134
- useEffect(() => {
135
- setShowAllSeriesForResponse(null);
136
- }, [response]);
137
- useEffect(() => {
138
- if (response === null) {
139
- return;
268
+ return [response.series, {
269
+ isTrimmed: false,
270
+ beforeTrim: 0,
271
+ afterTrim: 0
272
+ }];
273
+ }
274
+ return [null, {
275
+ isTrimmed: false,
276
+ beforeTrim: 0,
277
+ afterTrim: 0
278
+ }];
279
+ }, [response, showAllSeriesForResponse]),
280
+ _useMemo2 = _slicedToArray(_useMemo, 2),
281
+ originalSeries = _useMemo2[0],
282
+ _useMemo2$ = _useMemo2[1],
283
+ isTrimmed = _useMemo2$.isTrimmed,
284
+ beforeTrim = _useMemo2$.beforeTrim,
285
+ afterTrim = _useMemo2$.afterTrim;
286
+ var selectedPoint = useMemo(function () {
287
+ if (profile !== null && profile instanceof MergedProfileSelection) {
288
+ // Iterate over the series and find the series index that matches all
289
+ // labels of the profile selection. We specifically need the index
290
+ // because that's what the SeriesPoint interface expects.
291
+ var seriesIndex = originalSeries === null || originalSeries === void 0 ? void 0 : originalSeries.findIndex(function (s) {
292
+ var _s$labelset;
293
+ return (_s$labelset = s.labelset) === null || _s$labelset === void 0 || (_s$labelset = _s$labelset.labels) === null || _s$labelset === void 0 ? void 0 : _s$labelset.every(function (label) {
294
+ return profile.query.matchers.some(function (matcher) {
295
+ return matcher.key === label.name && matcher.value === label.value;
296
+ });
297
+ });
298
+ });
299
+
300
+ // if we found a series, return the point that matches the from/to timestamp exactly (in millisecond precision)
301
+ if (seriesIndex !== undefined && seriesIndex !== -1 && originalSeries != null && originalSeries[seriesIndex] != null) {
302
+ var series_0 = originalSeries[seriesIndex];
303
+ var pointIndex = series_0.samples.findIndex(function (sample_0) {
304
+ var _sample_0$timestamp, _sample_0$timestamp2;
305
+ return ((_sample_0$timestamp = sample_0.timestamp) === null || _sample_0$timestamp === void 0 ? void 0 : _sample_0$timestamp.seconds) === BigInt(profile.mergeFrom / 1000000000n) && ((_sample_0$timestamp2 = sample_0.timestamp) === null || _sample_0$timestamp2 === void 0 ? void 0 : _sample_0$timestamp2.nanos) === Number(profile.mergeFrom % 1000000000n);
306
+ });
307
+ if (pointIndex !== -1) {
308
+ return {
309
+ seriesIndex: seriesIndex,
310
+ pointIndex: pointIndex
311
+ };
140
312
  }
141
- perf?.markInteraction('Metrics graph render', response.series[0].samples.length);
142
- }, [perf, response]);
143
- const [originalSeries, { isTrimmed, beforeTrim, afterTrim }] = useMemo(() => {
144
- if (response?.series != null) {
145
- // Check if user wants ALL series for THIS specific response
146
- const userWantsAllForThisResponse = showAllSeriesForResponse === response;
147
- const maxSeriesLimit = 100;
148
- // Limit the number of series to maxSeriesLimit to avoid performance issues (unless user opts to show all)
149
- if (response.series.length > maxSeriesLimit && !userWantsAllForThisResponse) {
150
- // Select top `maxSeriesLimit` series based on their max value (to catch series with large spikes)
151
- const seriesWithMaxValue = response.series.map(series => {
152
- const maxValue = series.samples.reduce((max, sample) => {
153
- const value = sample.valuePerSecond ?? 0;
154
- return value > max ? value : max;
155
- }, 0);
156
- return { series, maxValue };
157
- });
158
- // Sort by max value descending and take top `maxSeriesLimit` series
159
- const topSeries = seriesWithMaxValue
160
- .sort((a, b) => b.maxValue - a.maxValue)
161
- .slice(0, maxSeriesLimit)
162
- .map(item => item.series);
163
- return [
164
- topSeries,
165
- { isTrimmed: true, beforeTrim: response.series.length, afterTrim: maxSeriesLimit },
166
- ];
167
- }
168
- return [response.series, { isTrimmed: false, beforeTrim: 0, afterTrim: 0 }];
169
- }
170
- return [null, { isTrimmed: false, beforeTrim: 0, afterTrim: 0 }];
171
- }, [response, showAllSeriesForResponse]);
172
- const selectedPoint = useMemo(() => {
173
- if (profile !== null && profile instanceof MergedProfileSelection) {
174
- // Iterate over the series and find the series index that matches all
175
- // labels of the profile selection. We specifically need the index
176
- // because that's what the SeriesPoint interface expects.
177
- const seriesIndex = originalSeries?.findIndex(s => {
178
- return s.labelset?.labels?.every(label => {
179
- return profile.query.matchers.some(matcher => {
180
- return matcher.key === label.name && matcher.value === label.value;
181
- });
182
- });
183
- });
184
- // if we found a series, return the point that matches the from/to timestamp exactly (in millisecond precision)
185
- if (seriesIndex !== undefined &&
186
- seriesIndex !== -1 &&
187
- originalSeries != null &&
188
- originalSeries[seriesIndex] != null) {
189
- const series = originalSeries[seriesIndex];
190
- const pointIndex = series.samples.findIndex(sample => {
191
- return (sample.timestamp?.seconds === BigInt(profile.mergeFrom / 1000000000n) &&
192
- sample.timestamp?.nanos === Number(profile.mergeFrom % 1000000000n));
193
- });
194
- if (pointIndex !== -1) {
195
- return {
196
- seriesIndex,
197
- pointIndex,
198
- };
199
- }
200
- }
201
- return null;
313
+ }
314
+ return null;
315
+ }
316
+ return null;
317
+ }, [profile, originalSeries]);
318
+ var transformedSeries = useMemo(function () {
319
+ return originalSeries != null ? transformMetricsData(originalSeries) : [];
320
+ }, [originalSeries]);
321
+ var contextMenuItems = useMemo(function () {
322
+ return originalSeries != null ? createProfileContextMenuItems(addLabelMatcher, originalSeries) : [];
323
+ }, [originalSeries, addLabelMatcher]);
324
+ var dataAvailable = originalSeries !== null && originalSeries !== undefined && (originalSeries === null || originalSeries === void 0 ? void 0 : originalSeries.length) > 0;
325
+ var _useMemo3 = useMemo(function () {
326
+ var sampleUnit = '';
327
+ var sampleType = '';
328
+ if (dataAvailable) {
329
+ if (originalSeries !== null && originalSeries !== void 0 && originalSeries.every(function (val, i, arr) {
330
+ var _val$sampleType, _arr$;
331
+ return (val === null || val === void 0 || (_val$sampleType = val.sampleType) === null || _val$sampleType === void 0 ? void 0 : _val$sampleType.unit) === ((_arr$ = arr[0]) === null || _arr$ === void 0 || (_arr$ = _arr$.sampleType) === null || _arr$ === void 0 ? void 0 : _arr$.unit);
332
+ })) {
333
+ var _originalSeries$0$sam, _originalSeries$, _originalSeries$0$sam2, _originalSeries$2;
334
+ sampleUnit = (_originalSeries$0$sam = (_originalSeries$ = originalSeries[0]) === null || _originalSeries$ === void 0 || (_originalSeries$ = _originalSeries$.sampleType) === null || _originalSeries$ === void 0 ? void 0 : _originalSeries$.unit) !== null && _originalSeries$0$sam !== void 0 ? _originalSeries$0$sam : '';
335
+ sampleType = (_originalSeries$0$sam2 = (_originalSeries$2 = originalSeries[0]) === null || _originalSeries$2 === void 0 || (_originalSeries$2 = _originalSeries$2.sampleType) === null || _originalSeries$2 === void 0 ? void 0 : _originalSeries$2.type) !== null && _originalSeries$0$sam2 !== void 0 ? _originalSeries$0$sam2 : '';
202
336
  }
203
- return null;
204
- }, [profile, originalSeries]);
205
- const transformedSeries = useMemo(() => {
206
- return originalSeries != null ? transformMetricsData(originalSeries) : [];
207
- }, [originalSeries]);
208
- const contextMenuItems = useMemo(() => {
209
- return originalSeries != null
210
- ? createProfileContextMenuItems(addLabelMatcher, originalSeries)
211
- : [];
212
- }, [originalSeries, addLabelMatcher]);
213
- const dataAvailable = originalSeries !== null && originalSeries !== undefined && originalSeries?.length > 0;
214
- const { sampleUnit, sampleType, yAxisLabel, yAxisUnit } = useMemo(() => {
215
- let sampleUnit = '';
216
- let sampleType = '';
217
- if (dataAvailable) {
218
- if (originalSeries?.every((val, i, arr) => val?.sampleType?.unit === arr[0]?.sampleType?.unit)) {
219
- sampleUnit = originalSeries[0]?.sampleType?.unit ?? '';
220
- sampleType = originalSeries[0]?.sampleType?.type ?? '';
221
- }
222
- if (sampleUnit === '') {
223
- const profileType = Query.parse(queryExpression).profileType();
224
- sampleUnit = profileType.sampleUnit;
225
- sampleType = profileType.sampleType;
226
- }
337
+ if (sampleUnit === '') {
338
+ var profileType = Query.parse(queryExpression).profileType();
339
+ sampleUnit = profileType.sampleUnit;
340
+ sampleType = profileType.sampleType;
227
341
  }
228
- // Calculate axis labels based on profile data
229
- const isDeltaType = profile !== null ? profile?.query.profType.delta : false;
230
- let yAxisLabel = sampleUnit;
231
- let yAxisUnit = sampleUnit;
232
- if (isDeltaType) {
233
- if (sampleUnit === 'nanoseconds') {
234
- if (sampleType === 'cpu') {
235
- yAxisLabel = 'CPU Cores';
236
- yAxisUnit = '';
237
- }
238
- if (sampleType === 'cuda') {
239
- yAxisLabel = 'GPU Time';
240
- }
241
- }
242
- if (sampleUnit === 'bytes') {
243
- yAxisLabel = 'Bytes per Second';
244
- }
342
+ }
343
+
344
+ // Calculate axis labels based on profile data
345
+ var isDeltaType = profile !== null ? profile === null || profile === void 0 ? void 0 : profile.query.profType.delta : false;
346
+ var yAxisLabel = sampleUnit;
347
+ var yAxisUnit = sampleUnit;
348
+ if (isDeltaType) {
349
+ if (sampleUnit === 'nanoseconds') {
350
+ if (sampleType === 'cpu') {
351
+ yAxisLabel = 'CPU Cores';
352
+ yAxisUnit = '';
353
+ }
354
+ if (sampleType === 'cuda') {
355
+ yAxisLabel = 'GPU Time';
356
+ }
245
357
  }
246
- return { sampleUnit, sampleType, yAxisLabel, yAxisUnit };
247
- }, [dataAvailable, originalSeries, queryExpression, profile]);
248
- const loading = metricsGraphLoading;
249
- // Handle errors after all hooks have been called
250
- if (!metricsGraphLoading && error !== null) {
251
- if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
252
- return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
358
+ if (sampleUnit === 'bytes') {
359
+ yAxisLabel = 'Bytes per Second';
253
360
  }
254
- return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(error.message) });
361
+ }
362
+ return {
363
+ sampleUnit: sampleUnit,
364
+ sampleType: sampleType,
365
+ yAxisLabel: yAxisLabel,
366
+ yAxisUnit: yAxisUnit
367
+ };
368
+ }, [dataAvailable, originalSeries, queryExpression, profile]),
369
+ sampleUnit_0 = _useMemo3.sampleUnit,
370
+ sampleType_0 = _useMemo3.sampleType,
371
+ yAxisLabel_0 = _useMemo3.yAxisLabel,
372
+ yAxisUnit_0 = _useMemo3.yAxisUnit;
373
+ var loading = metricsGraphLoading;
374
+
375
+ // Handle errors after all hooks have been called
376
+ if (!metricsGraphLoading && error !== null) {
377
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
378
+ return /*#__PURE__*/_jsx(ErrorContent, {
379
+ errorMessage: authenticationErrorMessage
380
+ });
255
381
  }
256
- return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "h-full w-full relative", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: [isTrimmed ? (_jsxs("div", { className: "flex justify-center items-center gap-2", ...testId(TEST_IDS.METRICS_GRAPH_TRIMMED_BANNER), children: [_jsxs("span", { className: "text-sm text-amber-800 dark:text-amber-200 bg-amber-100 dark:bg-amber-900 text-center px-2 rounded", children: ["Note: Showing only ", afterTrim, " of ", new Intl.NumberFormat().format(beforeTrim), " series for performance reasons. Please narrow your query to view more."] }), _jsxs("button", { onClick: () => setShowAllSeriesForResponse(response), className: "text-sm px-1 bg-amber-600 hover:bg-amber-700 dark:bg-amber-700 dark:hover:bg-amber-600 text-white rounded font-medium transition-colors", ...testId(TEST_IDS.METRICS_GRAPH_SHOW_ALL_BUTTON), children: ["Show all ", new Intl.NumberFormat().format(beforeTrim)] })] })) : null, loading ? (_jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode })) : dataAvailable ? (_jsx(MetricsGraph, { data: transformedSeries, from: from, to: to, setTimeRange: setTimeRange, selectedPoint: selectedPoint, onSampleClick: (closestPoint) => {
257
- // Use original data for both series and point
258
- if (originalSeries?.[closestPoint.seriesIndex] != null) {
259
- const originalSeriesData = originalSeries[closestPoint.seriesIndex];
260
- const originalPoint = originalSeriesData.samples[closestPoint.pointIndex];
261
- if (originalPoint.timestamp != null && originalPoint.valuePerSecond !== undefined) {
262
- const timestampNanos = originalPoint.timestamp.seconds * 1000000000n +
263
- BigInt(originalPoint.timestamp.nanos);
264
- onPointClick(timestampNanos, // Convert to number to match interface
265
- originalSeriesData.labelset?.labels ?? [], queryExpression, Number(originalPoint.duration ?? 0) // Convert bigint to number
266
- );
267
- }
268
- }
269
- }, renderTooltipContent: (seriesIndex, pointIndex) => {
270
- if (originalSeries?.[seriesIndex]?.samples?.[pointIndex] != null) {
271
- const originalSeriesData = originalSeries[seriesIndex];
272
- const originalPoint = originalSeriesData.samples[pointIndex];
273
- if (originalPoint.timestamp != null && originalPoint.valuePerSecond !== undefined) {
274
- const timestampMs = Number(originalPoint.timestamp.seconds) * 1000 +
275
- originalPoint.timestamp.nanos / 1000000;
276
- const labels = originalSeriesData.labelset?.labels ?? [];
277
- const nameLabel = labels.find(e => e.name === '__name__');
278
- const highlightedNameLabel = nameLabel ?? { name: '', value: '' };
279
- const isDeltaType = profile !== null
280
- ? profile?.query.profType.delta
281
- : false;
282
- return (_jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [isDeltaType ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4 pr-3", children: "Per\u00A0Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit === 'nanoseconds' && sampleType === 'cpu'
283
- ? 'CPU Cores'
284
- : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.value ?? 0, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit, 5) })] })), originalPoint.duration != null &&
285
- Number(originalPoint.duration) > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(Number(originalPoint.duration.toString()), 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(new Date(timestampMs), timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: labels
286
- .filter((label) => label.name !== '__name__')
287
- .map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}` }) }, label.name))) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }));
288
- }
289
- }
290
- return null;
291
- }, yAxisLabel: yAxisLabel, yAxisUnit: yAxisUnit, height: height, width: width, margin: margin, contextMenuItems: contextMenuItems })) : (_jsx(ProfileMetricsEmptyState, { message: "No data found. Try a different query." }))] }, "metrics-graph-loaded") }));
382
+ return /*#__PURE__*/_jsx(ErrorContent, {
383
+ errorMessage: capitalizeOnlyFirstLetter(error.message)
384
+ });
385
+ }
386
+ return /*#__PURE__*/_jsx(AnimatePresence, {
387
+ children: /*#__PURE__*/_jsxs(motion.div, {
388
+ className: "h-full w-full relative",
389
+ initial: {
390
+ display: 'none',
391
+ opacity: 0
392
+ },
393
+ animate: {
394
+ display: 'block',
395
+ opacity: 1
396
+ },
397
+ transition: {
398
+ duration: 0.5
399
+ },
400
+ children: [isTrimmed ? /*#__PURE__*/_jsxs("div", _objectSpread(_objectSpread({
401
+ className: "flex justify-center items-center gap-2"
402
+ }, testId(TEST_IDS.METRICS_GRAPH_TRIMMED_BANNER)), {}, {
403
+ children: [/*#__PURE__*/_jsxs("span", {
404
+ className: "text-sm text-amber-800 dark:text-amber-200 bg-amber-100 dark:bg-amber-900 text-center px-2 rounded",
405
+ children: ["Note: Showing only ", afterTrim, " of ", new Intl.NumberFormat().format(beforeTrim), " series for performance reasons. Please narrow your query to view more."]
406
+ }), /*#__PURE__*/_jsxs("button", _objectSpread(_objectSpread({
407
+ onClick: function onClick() {
408
+ return setShowAllSeriesForResponse(response);
409
+ },
410
+ className: "text-sm px-1 bg-amber-600 hover:bg-amber-700 dark:bg-amber-700 dark:hover:bg-amber-600 text-white rounded font-medium transition-colors"
411
+ }, testId(TEST_IDS.METRICS_GRAPH_SHOW_ALL_BUTTON)), {}, {
412
+ children: ["Show all ", new Intl.NumberFormat().format(beforeTrim)]
413
+ }))]
414
+ })) : null, loading ? /*#__PURE__*/_jsx(MetricsGraphSkeleton, {
415
+ heightStyle: heightStyle,
416
+ isDarkMode: isDarkMode
417
+ }) : dataAvailable ? /*#__PURE__*/_jsx(MetricsGraph, {
418
+ data: transformedSeries,
419
+ from: from,
420
+ to: to,
421
+ setTimeRange: setTimeRange,
422
+ selectedPoint: selectedPoint,
423
+ onSampleClick: function onSampleClick(closestPoint) {
424
+ // Use original data for both series and point
425
+ if ((originalSeries === null || originalSeries === void 0 ? void 0 : originalSeries[closestPoint.seriesIndex]) != null) {
426
+ var originalSeriesData = originalSeries[closestPoint.seriesIndex];
427
+ var originalPoint = originalSeriesData.samples[closestPoint.pointIndex];
428
+ if (originalPoint.timestamp != null && originalPoint.valuePerSecond !== undefined) {
429
+ var _originalSeriesData$l3, _originalSeriesData$l4, _originalPoint$durati;
430
+ var timestampNanos = originalPoint.timestamp.seconds * 1000000000n + BigInt(originalPoint.timestamp.nanos);
431
+ onPointClick(timestampNanos, // Convert to number to match interface
432
+ (_originalSeriesData$l3 = (_originalSeriesData$l4 = originalSeriesData.labelset) === null || _originalSeriesData$l4 === void 0 ? void 0 : _originalSeriesData$l4.labels) !== null && _originalSeriesData$l3 !== void 0 ? _originalSeriesData$l3 : [], queryExpression, Number((_originalPoint$durati = originalPoint.duration) !== null && _originalPoint$durati !== void 0 ? _originalPoint$durati : 0) // Convert bigint to number
433
+ );
434
+ }
435
+ }
436
+ },
437
+ renderTooltipContent: function renderTooltipContent(seriesIndex_0, pointIndex_0) {
438
+ var _originalSeries$serie;
439
+ if ((originalSeries === null || originalSeries === void 0 || (_originalSeries$serie = originalSeries[seriesIndex_0]) === null || _originalSeries$serie === void 0 || (_originalSeries$serie = _originalSeries$serie.samples) === null || _originalSeries$serie === void 0 ? void 0 : _originalSeries$serie[pointIndex_0]) != null) {
440
+ var originalSeriesData_0 = originalSeries[seriesIndex_0];
441
+ var originalPoint_0 = originalSeriesData_0.samples[pointIndex_0];
442
+ if (originalPoint_0.timestamp != null && originalPoint_0.valuePerSecond !== undefined) {
443
+ var _originalSeriesData_, _originalSeriesData_2, _originalPoint_0$valu;
444
+ var timestampMs = Number(originalPoint_0.timestamp.seconds) * 1000 + originalPoint_0.timestamp.nanos / 1000000;
445
+ var labels = (_originalSeriesData_ = (_originalSeriesData_2 = originalSeriesData_0.labelset) === null || _originalSeriesData_2 === void 0 ? void 0 : _originalSeriesData_2.labels) !== null && _originalSeriesData_ !== void 0 ? _originalSeriesData_ : [];
446
+ var nameLabel = labels.find(function (e) {
447
+ return e.name === '__name__';
448
+ });
449
+ var highlightedNameLabel = nameLabel !== null && nameLabel !== void 0 ? nameLabel : {
450
+ name: '',
451
+ value: ''
452
+ };
453
+ var isDeltaType_0 = profile !== null ? profile === null || profile === void 0 ? void 0 : profile.query.profType.delta : false;
454
+ return /*#__PURE__*/_jsx("div", {
455
+ className: "flex flex-row",
456
+ children: /*#__PURE__*/_jsxs("div", {
457
+ className: "ml-2 mr-6",
458
+ children: [/*#__PURE__*/_jsx("span", {
459
+ className: "font-semibold",
460
+ children: highlightedNameLabel.value
461
+ }), /*#__PURE__*/_jsx("span", {
462
+ className: "my-2 block text-gray-700 dark:text-gray-300",
463
+ children: /*#__PURE__*/_jsx("table", {
464
+ className: "table-auto",
465
+ children: /*#__PURE__*/_jsxs("tbody", {
466
+ children: [isDeltaType_0 ? /*#__PURE__*/_jsxs(_Fragment, {
467
+ children: [/*#__PURE__*/_jsxs("tr", {
468
+ children: [/*#__PURE__*/_jsx("td", {
469
+ className: "w-1/4 pr-3",
470
+ children: "Per\xA0Second"
471
+ }), /*#__PURE__*/_jsx("td", {
472
+ className: "w-3/4",
473
+ children: valueFormatter(originalPoint_0.valuePerSecond, sampleUnit_0 === 'nanoseconds' && sampleType_0 === 'cpu' ? 'CPU Cores' : sampleUnit_0, 5)
474
+ })]
475
+ }), /*#__PURE__*/_jsxs("tr", {
476
+ children: [/*#__PURE__*/_jsx("td", {
477
+ className: "w-1/4",
478
+ children: "Total"
479
+ }), /*#__PURE__*/_jsx("td", {
480
+ className: "w-3/4",
481
+ children: valueFormatter((_originalPoint_0$valu = originalPoint_0.value) !== null && _originalPoint_0$valu !== void 0 ? _originalPoint_0$valu : 0, sampleUnit_0, 2)
482
+ })]
483
+ })]
484
+ }) : /*#__PURE__*/_jsxs("tr", {
485
+ children: [/*#__PURE__*/_jsx("td", {
486
+ className: "w-1/4",
487
+ children: "Value"
488
+ }), /*#__PURE__*/_jsx("td", {
489
+ className: "w-3/4",
490
+ children: valueFormatter(originalPoint_0.valuePerSecond, sampleUnit_0, 5)
491
+ })]
492
+ }), originalPoint_0.duration != null && Number(originalPoint_0.duration) > 0 && /*#__PURE__*/_jsxs("tr", {
493
+ children: [/*#__PURE__*/_jsx("td", {
494
+ className: "w-1/4",
495
+ children: "Duration"
496
+ }), /*#__PURE__*/_jsx("td", {
497
+ className: "w-3/4",
498
+ children: valueFormatter(Number(originalPoint_0.duration.toString()), 'nanoseconds', 2)
499
+ })]
500
+ }), /*#__PURE__*/_jsxs("tr", {
501
+ children: [/*#__PURE__*/_jsx("td", {
502
+ className: "w-1/4",
503
+ children: "At"
504
+ }), /*#__PURE__*/_jsx("td", {
505
+ className: "w-3/4",
506
+ children: formatDate(new Date(timestampMs), timePattern(timezone), timezone)
507
+ })]
508
+ })]
509
+ })
510
+ })
511
+ }), /*#__PURE__*/_jsx("span", {
512
+ className: "my-2 block text-gray-500",
513
+ children: labels.filter(function (label_0) {
514
+ return label_0.name !== '__name__';
515
+ }).map(function (label_1) {
516
+ return /*#__PURE__*/_jsx("div", _objectSpread(_objectSpread({
517
+ className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400"
518
+ }, testId(TEST_IDS.TOOLTIP_LABEL)), {}, {
519
+ children: /*#__PURE__*/_jsx(TextWithTooltip, {
520
+ text: "".concat(label_1.name, "=\"").concat(label_1.value, "\""),
521
+ maxTextLength: 37,
522
+ id: "tooltip-".concat(label_1.name)
523
+ })
524
+ }), label_1.name);
525
+ })
526
+ }), /*#__PURE__*/_jsxs("div", {
527
+ className: "flex w-full items-center gap-1 text-xs text-gray-500",
528
+ children: [/*#__PURE__*/_jsx(Icon, {
529
+ icon: "iconoir:mouse-button-right"
530
+ }), /*#__PURE__*/_jsx("div", {
531
+ children: "Right click to add labels to query."
532
+ })]
533
+ })]
534
+ })
535
+ });
536
+ }
537
+ }
538
+ return null;
539
+ },
540
+ yAxisLabel: yAxisLabel_0,
541
+ yAxisUnit: yAxisUnit_0,
542
+ height: height,
543
+ width: width,
544
+ margin: margin,
545
+ contextMenuItems: contextMenuItems
546
+ }) : /*#__PURE__*/_jsx(ProfileMetricsEmptyState, {
547
+ message: "No data found. Try a different query."
548
+ })]
549
+ }, "metrics-graph-loaded")
550
+ });
292
551
  };
293
- export default ProfileMetricsGraph;
552
+ export default ProfileMetricsGraph;