@parca/profile 0.16.506 → 0.16.508

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
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.16.508](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.507...@parca/profile@0.16.508) (2025-05-07)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.507](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.506...@parca/profile@0.16.507) (2025-05-06)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.506](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.505...@parca/profile@0.16.506) (2025-05-06)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -49,12 +49,12 @@ function transformToSeries(data) {
49
49
  }
50
50
  const getYAxisUnit = (name) => {
51
51
  switch (name) {
52
- case 'gpu_utilization_percent':
53
- return 'percent';
54
- case 'gpu_memory_utilization_percent':
55
- return 'percent';
56
52
  case 'gpu_power_watt':
57
53
  return 'watts';
54
+ case 'gpu_temperature_celsius':
55
+ return 'celsius';
56
+ case 'gpu_clock_hertz':
57
+ return 'hertz';
58
58
  default:
59
59
  return 'percent';
60
60
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Flamegraph, FlamegraphArrow } from '@parca/client';
3
3
  import { ProfileType } from '@parca/parser';
4
- import { ProfileSource } from '../ProfileSource';
4
+ import { MergedProfileSource, ProfileSource } from '../ProfileSource';
5
5
  import { CurrentPathFrame } from './IcicleGraphArrow/utils';
6
6
  export type ResizeHandler = (width: number, height: number) => void;
7
7
  interface ProfileIcicleGraphProps {
@@ -24,6 +24,11 @@ interface ProfileIcicleGraphProps {
24
24
  metadataLoading?: boolean;
25
25
  isIcicleChart?: boolean;
26
26
  }
27
+ export declare const validateIcicleChartQuery: (profileSource: MergedProfileSource) => {
28
+ isValid: boolean;
29
+ isNonDelta: boolean;
30
+ isDurationTooLong: boolean;
31
+ };
27
32
  declare const ProfileIcicleGraph: ({ graph, arrow, total, filtered, curPath, setNewCurPath, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isIcicleChart, profileSource, }: ProfileIcicleGraphProps) => JSX.Element;
28
33
  export default ProfileIcicleGraph;
29
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgD,MAAM,OAAO,CAAC;AAKrE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAO/C,OAAO,EAAC,gBAAgB,EAA0B,MAAM,0BAA0B,CAAC;AAInF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,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,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD,QAAA,MAAM,kBAAkB,uMAiBrB,uBAAuB,KAAG,GAAG,CAAC,OAuMhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgD,MAAM,OAAO,CAAC;AAKrE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAOpE,OAAO,EAAC,gBAAgB,EAA0B,MAAM,0BAA0B,CAAC;AAInF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,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,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD,eAAO,MAAM,wBAAwB,kBACpB,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAIpE,CAAC;AAEF,QAAA,MAAM,kBAAkB,uMAiBrB,uBAAuB,KAAG,GAAG,CAAC,OA4NhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -27,6 +27,11 @@ const numberFormatter = new Intl.NumberFormat('en-US');
27
27
  const ErrorContent = ({ errorMessage }) => {
28
28
  return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
29
29
  };
30
+ export const validateIcicleChartQuery = (profileSource) => {
31
+ const isNonDelta = !profileSource.ProfileType().delta;
32
+ const isDurationTooLong = profileSource.mergeTo - profileSource.mergeFrom > 60000;
33
+ return { isValid: !isNonDelta && !isDurationTooLong, isNonDelta, isDurationTooLong };
34
+ };
30
35
  const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isIcicleChart = false, profileSource, }) {
31
36
  const { onError, authenticationErrorMessage, isDarkMode } = useParcaContext();
32
37
  const { compareMode } = useProfileViewContext();
@@ -76,9 +81,25 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
76
81
  }
77
82
  }, [loadingState]);
78
83
  const icicleGraph = useMemo(() => {
79
- if (isLoading) {
84
+ const { isValid: isIcicleChartValid, isNonDelta, isDurationTooLong, } = isIcicleChart
85
+ ? validateIcicleChartQuery(profileSource)
86
+ : { isValid: true, isNonDelta: false, isDurationTooLong: false };
87
+ const isInvalidIcicleChartQuery = isIcicleChart && !isIcicleChartValid;
88
+ if (isLoading && !isInvalidIcicleChartQuery) {
80
89
  return (_jsx("div", { className: "h-auto overflow-clip", children: _jsx(IcicleGraphSkeleton, { isHalfScreen: isHalfScreen, isDarkMode: isDarkMode }) }));
81
90
  }
91
+ // Do necessary checks to ensure that icicle chart can be rendered for this query.
92
+ if (isInvalidIcicleChartQuery) {
93
+ if (isNonDelta) {
94
+ return _jsx(ErrorContent, { errorMessage: "Icicle chart is only available for delta profiles." });
95
+ }
96
+ else if (isDurationTooLong) {
97
+ return (_jsx(ErrorContent, { errorMessage: "Icicle chart is not available for queries with a duration longer than a minute, select a point in the metrics graph to continue." }));
98
+ }
99
+ else {
100
+ return _jsx(ErrorContent, { errorMessage: "Icicle chart is not available for this query." });
101
+ }
102
+ }
82
103
  if (graph === undefined && arrow === undefined)
83
104
  return _jsx("div", { className: "mx-auto text-center", children: "No data..." });
84
105
  if (total === 0n && !loading)
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAK1E,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAK9C,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,mBAAmB,+DAI7B,wBAAwB,KAAG,GAAG,CAAC,OAqPjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAM1E,OAAO,EAAsB,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAKnE,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,mBAAmB,+DAI7B,wBAAwB,KAAG,GAAG,CAAC,OAwPjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -15,6 +15,7 @@ import { useEffect, useMemo, useState } from 'react';
15
15
  import { QueryRequest_ReportType } from '@parca/client';
16
16
  import { useGrpcMetadata, useParcaContext, useURLState } from '@parca/components';
17
17
  import { saveAsBlob } from '@parca/utilities';
18
+ import { validateIcicleChartQuery } from './ProfileIcicleGraph';
18
19
  import { FIELD_FUNCTION_NAME } from './ProfileIcicleGraph/IcicleGraphArrow';
19
20
  import { ProfileView } from './ProfileView';
20
21
  import { useQuery } from './useQuery';
@@ -53,7 +54,8 @@ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizat
53
54
  binaryFrameFilter,
54
55
  });
55
56
  const { isLoading: flamechartLoading, response: flamechartResponse, error: flamechartError, } = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMECHART, {
56
- skip: !dashboardItems.includes('iciclechart'),
57
+ skip: !(dashboardItems.includes('iciclechart') &&
58
+ validateIcicleChartQuery(profileSource).isValid),
57
59
  nodeTrimThreshold,
58
60
  groupBy,
59
61
  invertCallStack,
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.506",
3
+ "version": "0.16.508",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
7
7
  "@iconify/react": "^4.0.0",
8
8
  "@parca/client": "0.16.128",
9
- "@parca/components": "0.16.332",
9
+ "@parca/components": "0.16.333",
10
10
  "@parca/dynamicsize": "0.16.65",
11
- "@parca/hooks": "0.0.84",
11
+ "@parca/hooks": "0.0.85",
12
12
  "@parca/icons": "0.16.71",
13
13
  "@parca/parser": "0.16.78",
14
- "@parca/store": "0.16.169",
15
- "@parca/utilities": "0.0.95",
14
+ "@parca/store": "0.16.170",
15
+ "@parca/utilities": "0.0.96",
16
16
  "@popperjs/core": "^2.11.8",
17
17
  "@protobuf-ts/runtime-rpc": "^2.5.0",
18
18
  "@storybook/preview-api": "^8.4.3",
@@ -77,5 +77,5 @@
77
77
  "access": "public",
78
78
  "registry": "https://registry.npmjs.org/"
79
79
  },
80
- "gitHead": "7b92ebba22c9bb62474ce950517b2b8adbfe1e81"
80
+ "gitHead": "43f190912407bbb3959f24ccc931eca866496fbe"
81
81
  }
@@ -90,12 +90,12 @@ function transformToSeries(data: MetricSeries[]): Series[] {
90
90
 
91
91
  const getYAxisUnit = (name: string): string => {
92
92
  switch (name) {
93
- case 'gpu_utilization_percent':
94
- return 'percent';
95
- case 'gpu_memory_utilization_percent':
96
- return 'percent';
97
93
  case 'gpu_power_watt':
98
94
  return 'watts';
95
+ case 'gpu_temperature_celsius':
96
+ return 'celsius';
97
+ case 'gpu_clock_hertz':
98
+ return 'hertz';
99
99
  default:
100
100
  return 'percent';
101
101
  }
@@ -21,7 +21,7 @@ import {IcicleGraphSkeleton, useParcaContext, useURLState} from '@parca/componen
21
21
  import {ProfileType} from '@parca/parser';
22
22
  import {capitalizeOnlyFirstLetter, divide} from '@parca/utilities';
23
23
 
24
- import {ProfileSource} from '../ProfileSource';
24
+ import {MergedProfileSource, ProfileSource} from '../ProfileSource';
25
25
  import DiffLegend from '../ProfileView/components/DiffLegend';
26
26
  import {useProfileViewContext} from '../ProfileView/context/ProfileViewContext';
27
27
  import {TimelineGuide} from '../TimelineGuide';
@@ -59,6 +59,14 @@ const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
59
59
  return <div className="flex justify-center p-10">{errorMessage}</div>;
60
60
  };
61
61
 
62
+ export const validateIcicleChartQuery = (
63
+ profileSource: MergedProfileSource
64
+ ): {isValid: boolean; isNonDelta: boolean; isDurationTooLong: boolean} => {
65
+ const isNonDelta = !profileSource.ProfileType().delta;
66
+ const isDurationTooLong = profileSource.mergeTo - profileSource.mergeFrom > 60000;
67
+ return {isValid: !isNonDelta && !isDurationTooLong, isNonDelta, isDurationTooLong};
68
+ };
69
+
62
70
  const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
63
71
  graph,
64
72
  arrow,
@@ -149,7 +157,15 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
149
157
  }, [loadingState]);
150
158
 
151
159
  const icicleGraph = useMemo(() => {
152
- if (isLoading) {
160
+ const {
161
+ isValid: isIcicleChartValid,
162
+ isNonDelta,
163
+ isDurationTooLong,
164
+ } = isIcicleChart
165
+ ? validateIcicleChartQuery(profileSource as MergedProfileSource)
166
+ : {isValid: true, isNonDelta: false, isDurationTooLong: false};
167
+ const isInvalidIcicleChartQuery = isIcicleChart && !isIcicleChartValid;
168
+ if (isLoading && !isInvalidIcicleChartQuery) {
153
169
  return (
154
170
  <div className="h-auto overflow-clip">
155
171
  <IcicleGraphSkeleton isHalfScreen={isHalfScreen} isDarkMode={isDarkMode} />
@@ -157,6 +173,19 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
157
173
  );
158
174
  }
159
175
 
176
+ // Do necessary checks to ensure that icicle chart can be rendered for this query.
177
+ if (isInvalidIcicleChartQuery) {
178
+ if (isNonDelta) {
179
+ return <ErrorContent errorMessage="Icicle chart is only available for delta profiles." />;
180
+ } else if (isDurationTooLong) {
181
+ return (
182
+ <ErrorContent errorMessage="Icicle chart is not available for queries with a duration longer than a minute, select a point in the metrics graph to continue." />
183
+ );
184
+ } else {
185
+ return <ErrorContent errorMessage="Icicle chart is not available for this query." />;
186
+ }
187
+ }
188
+
160
189
  if (graph === undefined && arrow === undefined)
161
190
  return <div className="mx-auto text-center">No data...</div>;
162
191
 
@@ -17,8 +17,9 @@ import {QueryRequest_ReportType, QueryServiceClient} from '@parca/client';
17
17
  import {useGrpcMetadata, useParcaContext, useURLState} from '@parca/components';
18
18
  import {saveAsBlob} from '@parca/utilities';
19
19
 
20
+ import {validateIcicleChartQuery} from './ProfileIcicleGraph';
20
21
  import {FIELD_FUNCTION_NAME} from './ProfileIcicleGraph/IcicleGraphArrow';
21
- import {ProfileSource} from './ProfileSource';
22
+ import {MergedProfileSource, ProfileSource} from './ProfileSource';
22
23
  import {ProfileView} from './ProfileView';
23
24
  import {useQuery} from './useQuery';
24
25
  import {downloadPprof} from './utils';
@@ -83,7 +84,10 @@ export const ProfileViewWithData = ({
83
84
  response: flamechartResponse,
84
85
  error: flamechartError,
85
86
  } = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMECHART, {
86
- skip: !dashboardItems.includes('iciclechart'),
87
+ skip: !(
88
+ dashboardItems.includes('iciclechart') &&
89
+ validateIcicleChartQuery(profileSource as MergedProfileSource).isValid
90
+ ),
87
91
  nodeTrimThreshold,
88
92
  groupBy,
89
93
  invertCallStack,