@parca/profile 0.19.138 → 0.19.140

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 (138) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
  3. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +11 -13
  4. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  5. package/dist/ProfileExplorer/ProfileExplorerCompare.js +4 -9
  6. package/dist/ProfileFlameChart/SamplesStrips/index.d.ts +2 -2
  7. package/dist/ProfileFlameChart/SamplesStrips/index.d.ts.map +1 -1
  8. package/dist/ProfileFlameChart/index.d.ts.map +1 -1
  9. package/dist/ProfileFlameChart/index.js +13 -19
  10. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.d.ts.map +1 -1
  11. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +8 -8
  12. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
  13. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +4 -3
  14. package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
  15. package/dist/ProfileFlameGraph/index.js +6 -4
  16. package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
  17. package/dist/ProfileMetricsGraph/index.js +4 -6
  18. package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
  19. package/dist/ProfileSelector/MetricsGraphSection.js +5 -10
  20. package/dist/ProfileSelector/index.d.ts.map +1 -1
  21. package/dist/ProfileSelector/index.js +27 -25
  22. package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
  23. package/dist/ProfileSelector/useAutoQuerySelector.js +3 -0
  24. package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
  25. package/dist/ProfileTypeSelector/index.js +4 -0
  26. package/dist/ProfileView/components/ActionButtons/SortByDropdown.d.ts.map +1 -1
  27. package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +5 -5
  28. package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
  29. package/dist/ProfileView/components/ColorStackLegend.js +2 -3
  30. package/dist/ProfileView/components/InvertCallStack/index.d.ts.map +1 -1
  31. package/dist/ProfileView/components/InvertCallStack/index.js +5 -4
  32. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts +1 -2
  33. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts.map +1 -1
  34. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +14 -16
  35. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.js +84 -170
  36. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
  37. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +16 -20
  38. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
  39. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +4 -5
  40. package/dist/ProfileView/components/Toolbars/index.d.ts +2 -2
  41. package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
  42. package/dist/ProfileView/components/Toolbars/index.js +1 -1
  43. package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -1
  44. package/dist/ProfileView/components/ViewSelector/index.js +8 -14
  45. package/dist/ProfileView/context/DashboardContext.d.ts.map +1 -1
  46. package/dist/ProfileView/context/DashboardContext.js +6 -6
  47. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -1
  48. package/dist/ProfileView/hooks/useResetFlameGraphState.js +5 -4
  49. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
  50. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +25 -26
  51. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.d.ts.map +1 -1
  52. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +13 -8
  53. package/dist/ProfileView/hooks/useVisualizationState.d.ts +3 -3
  54. package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
  55. package/dist/ProfileView/hooks/useVisualizationState.js +35 -51
  56. package/dist/ProfileViewWithData.d.ts.map +1 -1
  57. package/dist/ProfileViewWithData.js +19 -28
  58. package/dist/Sandwich/index.d.ts.map +1 -1
  59. package/dist/Sandwich/index.js +4 -3
  60. package/dist/SourceView/index.d.ts.map +1 -1
  61. package/dist/SourceView/index.js +4 -2
  62. package/dist/SourceView/useSelectedLineRange.d.ts.map +1 -1
  63. package/dist/SourceView/useSelectedLineRange.js +21 -16
  64. package/dist/Table/MoreDropdown.d.ts.map +1 -1
  65. package/dist/Table/MoreDropdown.js +8 -11
  66. package/dist/Table/TableContextMenu.d.ts.map +1 -1
  67. package/dist/Table/TableContextMenu.js +10 -13
  68. package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
  69. package/dist/Table/hooks/useTableConfiguration.js +3 -4
  70. package/dist/Table/index.d.ts.map +1 -1
  71. package/dist/Table/index.js +11 -9
  72. package/dist/TopTable/index.d.ts.map +1 -1
  73. package/dist/TopTable/index.js +3 -4
  74. package/dist/hooks/urlParsers.d.ts +18 -0
  75. package/dist/hooks/urlParsers.d.ts.map +1 -0
  76. package/dist/hooks/urlParsers.js +32 -0
  77. package/dist/hooks/useColorBy.d.ts +5 -0
  78. package/dist/hooks/useColorBy.d.ts.map +1 -0
  79. package/dist/hooks/useColorBy.js +26 -0
  80. package/dist/hooks/useCompareModeMeta.d.ts.map +1 -1
  81. package/dist/hooks/useCompareModeMeta.js +55 -86
  82. package/dist/hooks/useDashboardItems.d.ts +5 -0
  83. package/dist/hooks/useDashboardItems.d.ts.map +1 -0
  84. package/dist/hooks/useDashboardItems.js +27 -0
  85. package/dist/hooks/useQueryState.d.ts +3 -3
  86. package/dist/hooks/useQueryState.d.ts.map +1 -1
  87. package/dist/hooks/useQueryState.js +105 -105
  88. package/dist/hooks/useQueryState.test.js +186 -302
  89. package/dist/index.d.ts +3 -2
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +3 -12
  92. package/dist/useSumBy.d.ts +1 -1
  93. package/dist/useSumBy.d.ts.map +1 -1
  94. package/dist/useSumBy.js +2 -2
  95. package/package.json +12 -11
  96. package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +11 -13
  97. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +4 -9
  98. package/src/ProfileFlameChart/SamplesStrips/index.tsx +2 -2
  99. package/src/ProfileFlameChart/index.tsx +21 -28
  100. package/src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx +10 -9
  101. package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +5 -3
  102. package/src/ProfileFlameGraph/index.tsx +6 -9
  103. package/src/ProfileMetricsGraph/index.tsx +6 -8
  104. package/src/ProfileSelector/MetricsGraphSection.tsx +5 -10
  105. package/src/ProfileSelector/index.tsx +32 -31
  106. package/src/ProfileSelector/useAutoQuerySelector.ts +5 -0
  107. package/src/ProfileTypeSelector/index.tsx +4 -0
  108. package/src/ProfileView/components/ActionButtons/SortByDropdown.tsx +10 -6
  109. package/src/ProfileView/components/ColorStackLegend.tsx +2 -4
  110. package/src/ProfileView/components/InvertCallStack/index.tsx +5 -4
  111. package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.tsx +94 -192
  112. package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts +21 -21
  113. package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +24 -25
  114. package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +4 -5
  115. package/src/ProfileView/components/Toolbars/index.tsx +3 -3
  116. package/src/ProfileView/components/ViewSelector/index.tsx +9 -16
  117. package/src/ProfileView/context/DashboardContext.tsx +6 -6
  118. package/src/ProfileView/hooks/useResetFlameGraphState.ts +6 -4
  119. package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +24 -26
  120. package/src/ProfileView/hooks/useResetStateOnSeriesChange.ts +16 -8
  121. package/src/ProfileView/hooks/useVisualizationState.ts +61 -69
  122. package/src/ProfileViewWithData.tsx +29 -35
  123. package/src/Sandwich/index.tsx +4 -3
  124. package/src/SourceView/index.tsx +4 -2
  125. package/src/SourceView/useSelectedLineRange.ts +34 -19
  126. package/src/Table/MoreDropdown.tsx +9 -11
  127. package/src/Table/TableContextMenu.tsx +10 -13
  128. package/src/Table/hooks/useTableConfiguration.tsx +3 -4
  129. package/src/Table/index.tsx +12 -21
  130. package/src/TopTable/index.tsx +3 -4
  131. package/src/hooks/urlParsers.ts +38 -0
  132. package/src/hooks/useColorBy.ts +42 -0
  133. package/src/hooks/useCompareModeMeta.ts +61 -91
  134. package/src/hooks/useDashboardItems.ts +46 -0
  135. package/src/hooks/useQueryState.test.tsx +275 -345
  136. package/src/hooks/useQueryState.ts +136 -118
  137. package/src/index.tsx +16 -15
  138. package/src/useSumBy.ts +3 -3
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 0.19.140 (2026-04-13)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## 0.19.139 (2026-03-20)
11
+
12
+ # 0.27.0 (2026-03-20)
13
+
14
+ **Note:** Version bump only for package @parca/profile
15
+
6
16
  ## [0.19.138](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.137...@parca/profile@0.19.138) (2026-03-17)
7
17
 
8
18
  **Note:** Version bump only for package @parca/profile
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAqBxC,UAAU,KAAK;IACb,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,GAAI,gBAAc,KAAK,KAAG,wBA8F7D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAwBxC,UAAU,KAAK;IACb,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,GAAI,gBAAc,KAAK,KAAG,wBAyF7D,CAAC"}
@@ -10,11 +10,14 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
+ import { useQueryState } from 'nuqs';
13
14
  import { QueryRequest_ReportType } from '@parca/client';
14
- import { useParcaContext, useURLState } from '@parca/components';
15
+ import { useParcaContext } from '@parca/components';
15
16
  import { FIELD_FUNCTION_FILE_NAME, FIELD_FUNCTION_START_LINE, FIELD_FUNCTION_SYSTEM_NAME, FIELD_INLINED, FIELD_LOCATION_ADDRESS, FIELD_LOCATION_LINE, FIELD_MAPPING_BUILD_ID, FIELD_MAPPING_FILE, FIELD_TIMESTAMP, } from '../../ProfileFlameGraph/FlameGraphArrow';
16
17
  import { arrowToString } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
17
18
  import { useProfileViewContext } from '../../ProfileView/context/ProfileViewContext';
19
+ import { stringParam } from '../../hooks/urlParsers';
20
+ import { useDashboardItems } from '../../hooks/useDashboardItems';
18
21
  import { useQuery } from '../../useQuery';
19
22
  export const useGraphTooltipMetaInfo = ({ table, row }) => {
20
23
  const mappingFile = arrowToString(table.getChild(FIELD_MAPPING_FILE)?.get(row));
@@ -55,23 +58,18 @@ export const useGraphTooltipMetaInfo = ({ table, row }) => {
55
58
  arrowToString(table.getChild(field.name)?.get(row)) ?? '',
56
59
  ])
57
60
  .filter(value => value[1] !== '');
58
- const [dashboardItems, setDashboardItems] = useURLState('dashboard_items', {
59
- alwaysReturnArray: true,
60
- });
61
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
62
- const [unusedBuildId, setSourceBuildId] = useURLState('source_buildid');
63
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
- const [unusedFilename, setSourceFilename] = useURLState('source_filename');
65
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
66
- const [unusedLine, setSourceLine] = useURLState('source_line');
61
+ const { dashboardItems, setDashboardItems } = useDashboardItems();
62
+ const [_unusedBuildId, setSourceBuildId] = useQueryState('source_buildid', stringParam);
63
+ const [_unusedFilename, setSourceFilename] = useQueryState('source_filename', stringParam);
64
+ const [_unusedLine, setSourceLine] = useQueryState('source_line', stringParam);
67
65
  const openFile = () => {
68
66
  setDashboardItems([dashboardItems[0], 'source']);
69
67
  if (mappingBuildID != null) {
70
- setSourceBuildId(mappingBuildID);
68
+ void setSourceBuildId(mappingBuildID);
71
69
  }
72
- setSourceFilename(functionFilename);
70
+ void setSourceFilename(functionFilename);
73
71
  if (lineNumber !== undefined) {
74
- setSourceLine(lineNumber.toString());
72
+ void setSourceLine(lineNumber.toString());
75
73
  }
76
74
  };
77
75
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOvD,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAChC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,8BAG7B,2BAA2B,KAAG,GAAG,CAAC,OAmHpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOvD,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAChC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,8BAG7B,2BAA2B,KAAG,GAAG,CAAC,OA+GpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -12,7 +12,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { useCallback, useEffect, useMemo, useState } from 'react';
15
- import { useURLStateBatch } from '@parca/components';
16
15
  import { Query } from '@parca/parser';
17
16
  import { TEST_IDS, testId } from '@parca/test-utils';
18
17
  import { ProfileDiffSource, ProfileViewWithData } from '..';
@@ -21,7 +20,6 @@ import { useCompareModeMeta } from '../hooks/useCompareModeMeta';
21
20
  import { useQueryState } from '../hooks/useQueryState';
22
21
  const ProfileExplorerCompare = ({ queryClient, navigateTo, }) => {
23
22
  const [showMetricsGraph, setShowMetricsGraph] = useState(true);
24
- const batchUpdates = useURLStateBatch();
25
23
  const { closeCompareMode, isCompareMode, isCompareAbsolute } = useCompareModeMeta();
26
24
  // Read ProfileSource states from URL for both sides
27
25
  const { profileSource: profileSourceA, querySelection: querySelectionA } = useQueryState({
@@ -42,12 +40,10 @@ const ProfileExplorerCompare = ({ queryClient, navigateTo, }) => {
42
40
  return;
43
41
  }
44
42
  if (querySelectionB.expression === '' && querySelectionA.expression !== '') {
45
- batchUpdates(() => {
46
- setDraftExpressionB(querySelectionA.expression);
47
- setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection);
48
- // Commit to update the URL and trigger metrics graph load
49
- commitDraftB();
50
- });
43
+ setDraftExpressionB(querySelectionA.expression);
44
+ setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection);
45
+ // Commit to update the URL and trigger metrics graph load
46
+ commitDraftB();
51
47
  }
52
48
  }, [
53
49
  isCompareMode,
@@ -59,7 +55,6 @@ const ProfileExplorerCompare = ({ queryClient, navigateTo, }) => {
59
55
  setDraftExpressionB,
60
56
  setDraftTimeRangeB,
61
57
  commitDraftB,
62
- batchUpdates,
63
58
  ]);
64
59
  const closeProfileA = useCallback(() => {
65
60
  closeCompareMode('A');
@@ -6,10 +6,10 @@ interface Props {
6
6
  loading?: boolean;
7
7
  cpus: LabelSet[];
8
8
  data: DataPoint[][];
9
- selectedTimeframe?: {
9
+ selectedTimeframe: {
10
10
  labels: LabelSet;
11
11
  bounds: NumberDuo;
12
- };
12
+ } | null;
13
13
  onSelectedTimeframe: (labels: LabelSet, bounds: NumberDuo | undefined) => void;
14
14
  width?: number;
15
15
  bounds: NumberDuo;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameChart/SamplesStrips/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAIvC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAGvD,YAAY,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAQ9C,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;IACpB,iBAAiB,CAAC,EAAE;QAClB,MAAM,EAAE,QAAQ,CAAC;QACjB,MAAM,EAAE,SAAS,CAAC;KACnB,CAAC;IACF,mBAAmB,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAmID,eAAO,MAAM,YAAY,GAAI,yFAS1B,KAAK,KAAG,GAAG,CAAC,OAyKd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameChart/SamplesStrips/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAIvC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAGvD,YAAY,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAQ9C,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;IACpB,iBAAiB,EAAE;QACjB,MAAM,EAAE,QAAQ,CAAC;QACjB,MAAM,EAAE,SAAS,CAAC;KACnB,GAAG,IAAI,CAAC;IACT,mBAAmB,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAmID,eAAO,MAAM,YAAY,GAAI,yFAS1B,KAAK,KAAG,GAAG,CAAC,OAyKd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameChart/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAoC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAQpF,OAAO,EAAwB,WAAW,EAAQ,MAAM,eAAe,CAAC;AAKxE,OAAO,EAAsB,aAAa,EAAa,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oCAAoC,CAAC;AA4CpE,UAAU,sBAAsB;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AA+BD,eAAO,MAAM,iBAAiB,GAAI,kKAY/B,sBAAsB,KAAG,GAAG,CAAC,OAqM/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameChart/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAoC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEpF,OAAO,EAAwB,WAAW,EAAQ,MAAM,eAAe,CAAC;AAKxE,OAAO,EAAsB,aAAa,EAAa,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oCAAoC,CAAC;AAuCpE,UAAU,sBAAsB;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AA+BD,eAAO,MAAM,iBAAiB,GAAI,kKAY/B,sBAAsB,KAAG,GAAG,CAAC,OAuM/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -12,21 +12,20 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { useEffect, useMemo, useRef } from 'react';
15
+ import { createParser, useQueryState } from 'nuqs';
15
16
  import { QueryRequest_ReportType } from '@parca/client';
16
- import { Button, useParcaContext, useURLState, useURLStateCustom, } from '@parca/components';
17
+ import { Button, useParcaContext } from '@parca/components';
17
18
  import { Matcher, MatcherTypes, Query } from '@parca/parser';
18
19
  import { TimeUnits, formatDate, formatDuration } from '@parca/utilities';
19
20
  import ProfileFlameGraph, { validateFlameChartQuery } from '../ProfileFlameGraph';
20
21
  import { boundsFromProfileSource } from '../ProfileFlameGraph/FlameGraphArrow/utils';
21
22
  import { MergedProfileSource, timeFormat } from '../ProfileSource';
22
23
  import { useProfileFilters } from '../ProfileView/components/ProfileFilters/useProfileFilters';
24
+ import { flamechartDimensionParser } from '../hooks/urlParsers';
23
25
  import { useQuery } from '../useQuery';
24
26
  import { SamplesStrip } from './SamplesStrips';
25
- const TimeframeStateSerializer = {
27
+ const timeframeParser = createParser({
26
28
  parse: (value) => {
27
- if (value == null || value === '' || value === 'undefined' || Array.isArray(value)) {
28
- return undefined;
29
- }
30
29
  try {
31
30
  const [labelPart, boundsPart] = value.split('|');
32
31
  if (labelPart != null && boundsPart != null) {
@@ -46,16 +45,13 @@ const TimeframeStateSerializer = {
46
45
  catch {
47
46
  // Ignore parsing errors
48
47
  }
49
- return undefined;
48
+ return null;
50
49
  },
51
- stringify: (value) => {
52
- if (value == null) {
53
- return '';
54
- }
50
+ serialize: (value) => {
55
51
  const labelsStr = value.labels.labels.map(l => `${l.name}:${l.value}`).join(',');
56
52
  return `${labelsStr}|${value.bounds[0]},${value.bounds[1]}`;
57
53
  },
58
- };
54
+ }).withOptions({ history: 'replace' });
59
55
  // Helper to create a filtered profile source with narrowed time bounds
60
56
  // and dimension label matchers from the selected strip.
61
57
  const createFilteredProfileSource = (profileSource, selectedTimeframe) => {
@@ -75,18 +71,16 @@ export const ProfileFlameChart = ({ samplesData, queryClient, profileSource, wid
75
71
  const { enableFlamechartFiltering } = useParcaContext();
76
72
  const { protoFilters } = useProfileFilters();
77
73
  const zoomControlsRef = useRef(null);
78
- const [selectedTimeframe, setSelectedTimeframe] = useURLStateCustom('flamechart_timeframe', TimeframeStateSerializer);
74
+ const [selectedTimeframe, setSelectedTimeframe] = useQueryState('flamechart_timeframe', timeframeParser);
79
75
  // Read flamechart dimension from URL state to detect changes
80
- const [flamechartDimension] = useURLState('flamechart_dimension', {
81
- alwaysReturnArray: true,
82
- });
76
+ const [flamechartDimension] = useQueryState('flamechart_dimension', flamechartDimensionParser.withDefault([]));
83
77
  // Reset selection when the parent time range (profileSource) changes
84
78
  const timeBoundsKey = boundsFromProfileSource(profileSource).join(',');
85
79
  const prevTimeBoundsKey = useRef(timeBoundsKey);
86
80
  useEffect(() => {
87
81
  if (prevTimeBoundsKey.current !== timeBoundsKey) {
88
82
  prevTimeBoundsKey.current = timeBoundsKey;
89
- setSelectedTimeframe(undefined);
83
+ void setSelectedTimeframe(null);
90
84
  }
91
85
  }, [timeBoundsKey, setSelectedTimeframe]);
92
86
  // Reset selection when the dimension changes
@@ -95,16 +89,16 @@ export const ProfileFlameChart = ({ samplesData, queryClient, profileSource, wid
95
89
  useEffect(() => {
96
90
  if (prevDimensionKey.current !== dimensionKey) {
97
91
  prevDimensionKey.current = dimensionKey;
98
- setSelectedTimeframe(undefined);
92
+ void setSelectedTimeframe(null);
99
93
  }
100
94
  }, [dimensionKey, setSelectedTimeframe]);
101
95
  // Handle timeframe selection from strips
102
96
  const handleSelectedTimeframe = (labels, bounds) => {
103
97
  if (bounds === undefined) {
104
- setSelectedTimeframe(undefined);
98
+ void setSelectedTimeframe(null);
105
99
  }
106
100
  else {
107
- setSelectedTimeframe({ labels, bounds });
101
+ void setSelectedTimeframe({ labels, bounds });
108
102
  }
109
103
  };
110
104
  // Create filtered profile source when selection exists
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAOxC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAQ1C,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,QAAA,MAAM,WAAW,GAAI,kIAalB,gBAAgB,KAAG,GAAG,CAAC,OAyOzB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAQxC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAU1C,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,QAAA,MAAM,WAAW,GAAI,kIAalB,gBAAgB,KAAG,GAAG,CAAC,OAuOzB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -13,14 +13,17 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
13
13
  // limitations under the License.
14
14
  import { Icon } from '@iconify/react';
15
15
  import cx from 'classnames';
16
+ import { useQueryState } from 'nuqs';
16
17
  import { Item, Menu, Separator, Submenu } from 'react-contexify';
17
18
  import { Tooltip } from 'react-tooltip';
18
- import { useParcaContext, useURLState } from '@parca/components';
19
+ import { useParcaContext } from '@parca/components';
19
20
  import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
20
21
  import { TEST_IDS } from '@parca/test-utils';
21
22
  import { getLastItem } from '@parca/utilities';
22
23
  import { useGraphTooltip } from '../../GraphTooltipArrow/useGraphTooltip';
23
24
  import { useGraphTooltipMetaInfo } from '../../GraphTooltipArrow/useGraphTooltipMetaInfo';
25
+ import { stringParam } from '../../hooks/urlParsers';
26
+ import { useDashboardItems } from '../../hooks/useDashboardItems';
24
27
  import { hexifyAddress, truncateString } from '../../utils';
25
28
  const ContextMenu = ({ menuId, table, total, totalUnfiltered, row, compareAbsolute, hideMenu, profileType, unit, hideBinary, resetPath, isSandwich = false, }) => {
26
29
  const { isDarkMode } = useParcaContext();
@@ -36,11 +39,8 @@ const ContextMenu = ({ menuId, table, total, totalUnfiltered, row, compareAbsolu
36
39
  compareAbsolute,
37
40
  });
38
41
  const { functionFilename, functionSystemName, file, openFile, isSourceAvailable, locationAddress, mappingFile, mappingBuildID, inlined, } = useGraphTooltipMetaInfo({ table, row });
39
- const [dashboardItems, setDashboardItems] = useURLState('dashboard_items', {
40
- alwaysReturnArray: true,
41
- });
42
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
43
- const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
42
+ const { dashboardItems, setDashboardItems } = useDashboardItems();
43
+ const [_sandwichFunctionName, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam);
44
44
  if (contextMenuData === null) {
45
45
  return _jsx(_Fragment, {});
46
46
  }
@@ -98,11 +98,11 @@ const ContextMenu = ({ menuId, table, total, totalUnfiltered, row, compareAbsolu
98
98
  return;
99
99
  }
100
100
  if (dashboardItems.includes('sandwich')) {
101
- setSandwichFunctionName(functionName);
101
+ void setSandwichFunctionName(functionName);
102
102
  hideMenu();
103
103
  return;
104
104
  }
105
- setSandwichFunctionName(functionName);
105
+ void setSandwichFunctionName(functionName);
106
106
  setDashboardItems([...dashboardItems, 'sandwich']);
107
107
  hideMenu();
108
108
  }, disabled: functionName === '' || functionName == null, children: _jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx(Icon, { icon: "tdesign:sandwich-filled" }), _jsxs("div", { className: "relative", children: [dashboardItems.includes('sandwich')
@@ -1 +1 @@
1
- {"version":3,"file":"TextWithEllipsis.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx"],"names":[],"mappings":"AAiBA,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AA2CD,iBAAS,gBAAgB,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAC,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAuBjE;AAED,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"TextWithEllipsis.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx"],"names":[],"mappings":"AAmBA,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AA2CD,iBAAS,gBAAgB,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAC,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAuBjE;AAED,eAAe,gBAAgB,CAAC"}
@@ -12,7 +12,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { useEffect, useRef, useState } from 'react';
15
- import { useURLState } from '@parca/components';
15
+ import { useQueryState } from 'nuqs';
16
+ import { stringParam } from '../../hooks/urlParsers';
16
17
  function calculateTruncatedText(text, textElement, maxWidth) {
17
18
  // Create a temporary element for measurement
18
19
  const tempElement = textElement.cloneNode();
@@ -47,8 +48,8 @@ function calculateTruncatedText(text, textElement, maxWidth) {
47
48
  function TextWithEllipsis({ text, x, y, width }) {
48
49
  const textRef = useRef(null);
49
50
  const [displayText, setDisplayText] = useState(text);
50
- const [alignFunctionName] = useURLState('align_function_name');
51
- const showFunctionNameFromLeft = alignFunctionName === 'left' || alignFunctionName === undefined;
51
+ const [alignFunctionName] = useQueryState('align_function_name', stringParam.withDefault('left'));
52
+ const showFunctionNameFromLeft = alignFunctionName === 'left';
52
53
  useEffect(() => {
53
54
  const textElement = textRef.current;
54
55
  if (textElement === null)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAM7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAO9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAMpE,OAAO,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAIzD,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC1D;AAUD,eAAO,MAAM,uBAAuB,GAClC,eAAe,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAKpE,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAqC,sRAqBzD,sBAAsB,KAAG,GAAG,CAAC,OAiT/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAO7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAOpE,OAAO,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAIzD,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC1D;AAUD,eAAO,MAAM,uBAAuB,GAClC,eAAe,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAKpE,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAqC,sRAqBzD,sBAAsB,KAAG,GAAG,CAAC,OAiT/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -14,14 +14,16 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
14
14
  import { useCallback, useEffect, useMemo, useState } from 'react';
15
15
  import cx from 'classnames';
16
16
  import { AnimatePresence, motion } from 'framer-motion';
17
+ import { useQueryState } from 'nuqs';
17
18
  import { useMeasure } from 'react-use';
18
- import { FlameGraphSkeleton, SandwichFlameGraphSkeleton, useParcaContext, useURLState, } from '@parca/components';
19
+ import { FlameGraphSkeleton, SandwichFlameGraphSkeleton, useParcaContext } from '@parca/components';
19
20
  import { TEST_IDS, testId } from '@parca/test-utils';
20
21
  import { capitalizeOnlyFirstLetter, divide } from '@parca/utilities';
21
22
  import DiffLegend from '../ProfileView/components/DiffLegend';
22
23
  import { useProfileViewContext } from '../ProfileView/context/ProfileViewContext';
23
24
  import { useProfileMetadata } from '../ProfileView/hooks/useProfileMetadata';
24
25
  import { useVisualizationState } from '../ProfileView/hooks/useVisualizationState';
26
+ import { boolParam } from '../hooks/urlParsers';
25
27
  import { FlameGraphArrow } from './FlameGraphArrow';
26
28
  const numberFormatter = new Intl.NumberFormat('en-US');
27
29
  const ErrorContent = ({ errorMessage }) => {
@@ -60,8 +62,8 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
60
62
  // By default, we want delta profiles (CPU) to be relatively compared.
61
63
  // For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
62
64
  const compareAbsoluteDefault = profileType?.delta === false ? 'true' : 'false';
63
- const [compareAbsolute = compareAbsoluteDefault] = useURLState('compare_absolute');
64
- const isCompareAbsolute = compareAbsolute === 'true';
65
+ const [compareAbsolute] = useQueryState('compare_absolute', boolParam);
66
+ const isCompareAbsolute = compareAbsolute ?? compareAbsoluteDefault === 'true';
65
67
  const mappingsListCount = useMemo(() => mappingsList.filter(m => m !== '').length, [mappingsList]);
66
68
  const [totalFormatted, totalUnfilteredFormatted, isTrimmed, trimmedFormatted, trimmedPercentage, isFiltered, filteredPercentage,] = useMemo(() => {
67
69
  if (arrow === undefined) {
@@ -85,7 +87,7 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
85
87
  // If there is only one mapping file, we want to color by filename by default.
86
88
  useEffect(() => {
87
89
  if (mappingsListCount === 1 && colorBy !== 'filename') {
88
- setColorBy('filename');
90
+ void setColorBy('filename');
89
91
  }
90
92
  // eslint-disable-next-line react-hooks/exhaustive-deps
91
93
  }, [mappingsListCount]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileMetricsGraph/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EACL,KAAK,EAGL,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EAOd,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AA6G5D,UAAU,6BAA6B;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,eAAO,MAAM,wBAAwB,GAAI,aAAW,6BAA6B,KAAG,GAAG,CAAC,OAMvF,CAAC;AAEF,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,QAAA,MAAM,mBAAmB,GAAI,qHAW1B,wBAAwB,KAAG,GAAG,CAAC,OAiXjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileMetricsGraph/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,EAGL,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EAId,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AA8G5D,UAAU,6BAA6B;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,eAAO,MAAM,wBAAwB,GAAI,aAAW,6BAA6B,KAAG,GAAG,CAAC,OAMvF,CAAC;AAEF,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,QAAA,MAAM,mBAAmB,GAAI,qHAW1B,wBAAwB,KAAG,GAAG,CAAC,OAgXjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -14,13 +14,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
14
14
  import { useEffect, useMemo, useState } from 'react';
15
15
  import { Icon } from '@iconify/react';
16
16
  import { AnimatePresence, motion } from 'framer-motion';
17
- import { MetricsGraphSkeleton, NumberParser, NumberSerializer, TextWithTooltip, useParcaContext, useURLStateCustom, } from '@parca/components';
17
+ import { useQueryState } from 'nuqs';
18
+ import { MetricsGraphSkeleton, TextWithTooltip, useParcaContext, } from '@parca/components';
18
19
  import { Query } from '@parca/parser';
19
20
  import { TEST_IDS, testId } from '@parca/test-utils';
20
21
  import { capitalizeOnlyFirstLetter, formatDate, timePattern, valueFormatter } from '@parca/utilities';
21
22
  import { MergedProfileSelection } from '..';
22
23
  import MetricsGraph from '../MetricsGraph';
23
24
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
25
+ import { intParam } from '../hooks/urlParsers';
24
26
  import { getStepCountFromScreenWidth, useQueryRange } from './hooks/useQueryRange';
25
27
  const createProfileContextMenuItems = (addLabelMatcher, data // The original MetricsSeriesPb[] data
26
28
  ) => {
@@ -113,11 +115,7 @@ export const ProfileMetricsEmptyState = ({ message }) => {
113
115
  return (_jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: _jsx("p", { children: message }) }));
114
116
  };
115
117
  const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, sumBy, }) => {
116
- const [rawStepCount] = useURLStateCustom('step_count', {
117
- defaultValue: String(getStepCountFromScreenWidth(10)),
118
- parse: NumberParser,
119
- stringify: NumberSerializer,
120
- });
118
+ const [rawStepCount] = useQueryState('step_count', intParam.withDefault(getStepCountFromScreenWidth(10)));
121
119
  // Clamp step count so the step duration is at least 1 second as we don't have this enforced server-side anymore.
122
120
  const stepCount = useMemo(() => {
123
121
  const maxForOneSecond = Math.floor((to - from) / 1000);
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAoC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAIpC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAEvC,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,WAAW,EAAE,CACX,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,EACtE,UAAU,CAAC,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,WAAW,EACX,mBAA2B,EAC3B,iBAAyB,GAC1B,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CAmIxC"}
1
+ {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAkB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAIpC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAEvC,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,WAAW,EAAE,CACX,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,EACtE,UAAU,CAAC,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,WAAW,EACX,mBAA2B,EAC3B,iBAAyB,GAC1B,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CA8HxC"}
@@ -12,14 +12,13 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import cx from 'classnames';
15
- import { useParcaContext, useURLStateBatch } from '@parca/components';
15
+ import { useParcaContext } from '@parca/components';
16
16
  import { Query } from '@parca/parser';
17
17
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
18
18
  import ProfileMetricsGraph, { ProfileMetricsEmptyState } from '../ProfileMetricsGraph';
19
19
  import { useResetStateOnSeriesChange } from '../ProfileView/hooks/useResetStateOnSeriesChange';
20
20
  export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGraphButton, querySelection, profileSelection, comparing, sumBy, defaultSumByLoading, queryClient, queryExpressionString, setTimeRangeSelection, selectQuery, setProfileSelection, query, setNewQueryExpression, commitDraft, profileTypesLoading = false, hasNoProfileTypes = false, }) {
21
21
  const resetStateOnSeriesChange = useResetStateOnSeriesChange();
22
- const batchUpdates = useURLStateBatch();
23
22
  const { profileExplorer } = useParcaContext();
24
23
  const { heightStyle } = useMetricsGraphDimensions(comparing, profileExplorer?.metricsGraph.height);
25
24
  const handleTimeRangeChange = (range) => {
@@ -64,10 +63,8 @@ export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGra
64
63
  }
65
64
  if (hasChanged) {
66
65
  // Immediately apply the filter when adding label matchers from the graph
67
- batchUpdates(() => {
68
- setNewQueryExpression(newQuery.toString());
69
- commitDraft(undefined, newQuery.toString());
70
- });
66
+ setNewQueryExpression(newQuery.toString());
67
+ commitDraft(undefined, newQuery.toString());
71
68
  }
72
69
  };
73
70
  const handlePointClick = (timestamp, labels, queryExpression, duration) => {
@@ -80,10 +77,8 @@ export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGra
80
77
  });
81
78
  const mergeFrom = timestamp;
82
79
  const mergeTo = query.profileType().delta ? mergeFrom + BigInt(duration) : mergeFrom;
83
- batchUpdates(() => {
84
- resetStateOnSeriesChange(); // reset some state when a new series is selected
85
- setProfileSelection(mergeFrom, mergeTo, query);
86
- });
80
+ resetStateOnSeriesChange(); // reset some state when a new series is selected
81
+ setProfileSelection(mergeFrom, mergeTo, query);
87
82
  };
88
83
  return (_jsxs("div", { className: cx('relative', { 'py-4': !showMetricsGraph }), children: [setDisplayHideMetricsGraphButton != null ? (_jsxs("button", { onClick: () => setDisplayHideMetricsGraphButton(!showMetricsGraph), className: cx('hidden px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900 z-[5]', showMetricsGraph && 'absolute right-0 bottom-3 !flex', !showMetricsGraph && 'relative !flex ml-auto'), children: [showMetricsGraph ? 'Hide' : 'Show', " Metrics Graph"] })) : null, showMetricsGraph && (_jsx(_Fragment, { children: _jsx("div", { style: { height: heightStyle }, children: (querySelection.expression !== '' || defaultSumByLoading) &&
89
84
  querySelection.from !== undefined &&
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAe/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,kMAYtB,oBAAoB,KAAG,GAAG,CAAC,OAwQ7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAK5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAgB/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,kMAYtB,oBAAoB,KAAG,GAAG,CAAC,OA8Q7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -12,7 +12,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
- import { DateTimeRange, IconButton, useGrpcMetadata, useParcaContext, useURLState, useURLStateBatch, } from '@parca/components';
15
+ import { useQueryState as useNuqsQueryState } from 'nuqs';
16
+ import { DateTimeRange, IconButton, useGrpcMetadata, useParcaContext } from '@parca/components';
16
17
  import { CloseIcon } from '@parca/icons';
17
18
  import { Query } from '@parca/parser';
18
19
  import { TEST_IDS, testId } from '@parca/test-utils';
@@ -21,6 +22,7 @@ import { useProfileFilters, } from '../ProfileView/components/ProfileFilters/use
21
22
  import { QueryControls } from '../QueryControls';
22
23
  import { LabelsQueryProvider, useLabelsQueryProvider } from '../contexts/LabelsQueryProvider';
23
24
  import { UnifiedLabelsProvider } from '../contexts/UnifiedLabelsContext';
25
+ import { stringParam } from '../hooks/urlParsers';
24
26
  import { useLabelNames } from '../hooks/useLabels';
25
27
  import { useQueryState } from '../hooks/useQueryState';
26
28
  import useGrpcQuery from '../useGrpcQuery';
@@ -48,8 +50,10 @@ export const useProfileTypes = (client, start, end) => {
48
50
  };
49
51
  const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, comparing, navigateTo, showMetricsGraph = true, showSumBySelector = true, showProfileTypeSelector = true, setDisplayHideMetricsGraphButton, suffix, onSearchHook, }) => {
50
52
  const { externalProfilerComponent, additionalMetricsGraph } = useParcaContext();
51
- const [queryBrowserMode, setQueryBrowserMode] = useURLState('query_browser_mode');
52
- const batchUpdates = useURLStateBatch();
53
+ const [queryBrowserMode, setRawQueryBrowserMode] = useNuqsQueryState('query_browser_mode', stringParam);
54
+ const setQueryBrowserMode = useCallback((mode) => {
55
+ void setRawQueryBrowserMode(mode);
56
+ }, [setRawQueryBrowserMode]);
53
57
  const profileFilterDefaults = externalProfilerComponent?.profileFilterDefaults;
54
58
  const { forceApplyFilters } = useProfileFilters();
55
59
  const handleProfileTypeChange = useCallback(() => {
@@ -100,28 +104,26 @@ const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, compa
100
104
  const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
101
105
  const selectedProfileName = query.profileName();
102
106
  const setQueryExpression = (updateTs = false) => {
103
- batchUpdates(() => {
104
- if (onSearchHook != null) {
105
- onSearchHook();
106
- }
107
- // When updateTs is true, re-evaluate the time range to current values
108
- if (updateTs) {
109
- // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
110
- const currentFrom = timeRangeSelection.getFromMs(true);
111
- const currentTo = timeRangeSelection.getToMs(true);
112
- const currentRangeKey = timeRangeSelection.getRangeKey();
113
- // Commit with refreshed time range
114
- commitDraft({
115
- from: currentFrom,
116
- to: currentTo,
117
- timeSelection: currentRangeKey,
118
- });
119
- }
120
- else {
121
- // Commit the draft with existing values
122
- commitDraft();
123
- }
124
- });
107
+ if (onSearchHook != null) {
108
+ onSearchHook();
109
+ }
110
+ // When updateTs is true, re-evaluate the time range to current values
111
+ if (updateTs) {
112
+ // Force re-evaluation of time range (important for relative ranges like "last 15 minutes")
113
+ const currentFrom = timeRangeSelection.getFromMs(true);
114
+ const currentTo = timeRangeSelection.getToMs(true);
115
+ const currentRangeKey = timeRangeSelection.getRangeKey();
116
+ // Commit with refreshed time range
117
+ commitDraft({
118
+ from: currentFrom,
119
+ to: currentTo,
120
+ timeSelection: currentRangeKey,
121
+ });
122
+ }
123
+ else {
124
+ // Commit the draft with existing values
125
+ commitDraft();
126
+ }
125
127
  };
126
128
  const setMatchersString = (matchers) => {
127
129
  // Update draft state only
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoQuerySelector.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/useAutoQuerySelector.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAGlD,UAAU,KAAK;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACnD,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB,GAAI,yIASlC,KAAK,KAAG,IA+JV,CAAC"}
1
+ {"version":3,"file":"useAutoQuerySelector.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/useAutoQuerySelector.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAGlD,UAAU,KAAK;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACnD,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB,GAAI,yIASlC,KAAK,KAAG,IAoKV,CAAC"}
@@ -100,6 +100,9 @@ export const useAutoQuerySelector = ({ selectedProfileName, profileTypesData, se
100
100
  return;
101
101
  }
102
102
  let profileType = profileTypesData.types.find(type => type.name === 'parca_agent' && type.sampleType === 'samples' && type.delta);
103
+ if (profileType == null) {
104
+ profileType = profileTypesData.types.find(type => type.name === 'go_opentelemetry_io_ebpf_profiler' && type.delta);
105
+ }
103
106
  if (profileType == null) {
104
107
  profileType = profileTypesData.types.find(type => type.name === 'otel_profiling_agent_on_cpu' && type.delta);
105
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAG7D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,iBAiF/B,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAU3F;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,8BAA8B,EAAE,OAAO,GACtC,aAAa,CAiBf;AAED,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,WAAW,EAAE,KAAG,MAAM,EAItE,CAAC;AAEF,UAAU,KAAK;IACb,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,mBAAmB,GAAI,2GAQ1B,KAAK,KAAG,GAAG,CAAC,OA4Bd,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAG7D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,iBAqF/B,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAU3F;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,8BAA8B,EAAE,OAAO,GACtC,aAAa,CAiBf;AAED,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,WAAW,EAAE,KAAG,MAAM,EAItE,CAAC;AAEF,UAAU,KAAK;IACb,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,mBAAmB,GAAI,2GAQ1B,KAAK,KAAG,GAAG,CAAC,OA4Bd,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -83,6 +83,10 @@ export const wellKnownProfiles = {
83
83
  name: 'On-CPU Samples',
84
84
  help: 'On CPU profile samples observed by the Otel Profiling Agent.',
85
85
  },
86
+ 'go_opentelemetry_io_ebpf_profiler:samples:count:cpu:nanoseconds:delta': {
87
+ name: 'On-CPU',
88
+ help: 'On CPU profile samples as observed by the OpenTelemetry eBPF Profiler.',
89
+ },
86
90
  'parca_agent:samples:count:cpu:nanoseconds:delta': {
87
91
  name: 'On-CPU',
88
92
  help: 'On CPU profile samples as observed by the Parca Agent.',
@@ -1 +1 @@
1
- {"version":3,"file":"SortByDropdown.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ActionButtons/SortByDropdown.tsx"],"names":[],"mappings":"AAsBA,QAAA,MAAM,cAAc,QAAO,KAAK,CAAC,GAAG,CAAC,OA2DpC,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"SortByDropdown.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ActionButtons/SortByDropdown.tsx"],"names":[],"mappings":"AAyBA,QAAA,MAAM,cAAc,QAAO,KAAK,CAAC,GAAG,CAAC,OA4DpC,CAAC;AAEF,eAAe,cAAc,CAAC"}