@parca/profile 0.16.452 → 0.16.453

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 (43) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/MetricsGraphStrips/MetricsGraphStrips.stories.d.ts +8 -3
  3. package/dist/MetricsGraphStrips/MetricsGraphStrips.stories.d.ts.map +1 -1
  4. package/dist/MetricsGraphStrips/MetricsGraphStrips.stories.js +8 -8
  5. package/dist/MetricsGraphStrips/index.d.ts +6 -5
  6. package/dist/MetricsGraphStrips/index.d.ts.map +1 -1
  7. package/dist/MetricsGraphStrips/index.js +21 -4
  8. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +1 -0
  9. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
  10. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +1 -0
  11. package/dist/ProfileIcicleGraph/index.d.ts +1 -2
  12. package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
  13. package/dist/ProfileIcicleGraph/index.js +4 -4
  14. package/dist/ProfileView/components/DashboardItems/index.d.ts +1 -2
  15. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
  16. package/dist/ProfileView/components/DashboardItems/index.js +2 -2
  17. package/dist/ProfileView/context/ProfileViewContext.d.ts +10 -0
  18. package/dist/ProfileView/context/ProfileViewContext.d.ts.map +1 -1
  19. package/dist/ProfileView/context/ProfileViewContext.js +1 -0
  20. package/dist/ProfileView/index.d.ts +1 -1
  21. package/dist/ProfileView/index.d.ts.map +1 -1
  22. package/dist/ProfileView/index.js +2 -3
  23. package/dist/ProfileView/types/visualization.d.ts +2 -0
  24. package/dist/ProfileView/types/visualization.d.ts.map +1 -1
  25. package/dist/ProfileViewWithData.d.ts +4 -2
  26. package/dist/ProfileViewWithData.d.ts.map +1 -1
  27. package/dist/ProfileViewWithData.js +7 -4
  28. package/dist/TimelineGuide/index.d.ts.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/package.json +2 -2
  33. package/src/MetricsGraphStrips/MetricsGraphStrips.stories.tsx +8 -8
  34. package/src/MetricsGraphStrips/index.tsx +36 -12
  35. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +1 -0
  36. package/src/ProfileIcicleGraph/index.tsx +4 -6
  37. package/src/ProfileView/components/DashboardItems/index.tsx +0 -3
  38. package/src/ProfileView/context/ProfileViewContext.tsx +12 -0
  39. package/src/ProfileView/index.tsx +2 -3
  40. package/src/ProfileView/types/visualization.ts +2 -0
  41. package/src/ProfileViewWithData.tsx +11 -5
  42. package/src/TimelineGuide/index.tsx +0 -5
  43. package/src/index.tsx +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
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.453 (2024-12-05)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
6
10
  ## 0.16.452 (2024-12-02)
7
11
 
8
12
  **Note:** Version bump only for package @parca/profile
@@ -5,13 +5,18 @@ declare const meta: Meta;
5
5
  export default meta;
6
6
  export declare const ThreeCPUStrips: {
7
7
  args: {
8
- cpus: string[];
8
+ cpus: {
9
+ labels: {
10
+ name: string;
11
+ value: number;
12
+ }[];
13
+ }[];
9
14
  data: DataPoint[][];
10
- selectedTimeline: {
15
+ selectedTimeframe: {
11
16
  index: number;
12
17
  bounds: number[];
13
18
  };
14
- onSelectedTimeline: (index: number, bounds: NumberDuo) => void;
19
+ onSelectedTimeframe: (index: number, bounds: NumberDuo) => void;
15
20
  };
16
21
  render: (args: any) => JSX.Element;
17
22
  };
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsGraphStrips.stories.d.ts","sourceRoot":"","sources":["../../src/MetricsGraphStrips/MetricsGraphStrips.stories.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAC;AAEtC,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAqBtC,QAAA,MAAM,IAAI,EAAE,IAGX,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,eAAO,MAAM,cAAc;;;;;;;;oCAKK,MAAM,UAAU,SAAS,KAAG,IAAI;;mBAI7B,GAAG,KAAG,GAAG,CAAC,OAAO;CAUnD,CAAC"}
1
+ {"version":3,"file":"MetricsGraphStrips.stories.d.ts","sourceRoot":"","sources":["../../src/MetricsGraphStrips/MetricsGraphStrips.stories.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAC;AAEtC,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAqBtC,QAAA,MAAM,IAAI,EAAE,IAGX,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,eAAO,MAAM,cAAc;;;;;;;;;;;;;qCAKM,MAAM,UAAU,SAAS,KAAG,IAAI;;mBAI9B,GAAG,KAAG,GAAG,CAAC,OAAO;CAUnD,CAAC"}
@@ -37,19 +37,19 @@ const meta = {
37
37
  export default meta;
38
38
  export const ThreeCPUStrips = {
39
39
  args: {
40
- cpus: Array.from(mockData, (_, i) => `CPU ${i + 1}`),
40
+ cpus: Array.from(mockData, (_, i) => ({ labels: [{ name: 'cpuid', value: i + 1 }] })),
41
41
  data: mockData,
42
- selectedTimeline: { index: 1, bounds: [mockData[0][25].timestamp, mockData[0][100].timestamp] },
43
- onSelectedTimeline: (index, bounds) => {
44
- console.log('onSelectedTimeline', index, bounds);
42
+ selectedTimeframe: { index: 1, bounds: [mockData[0][25].timestamp, mockData[0][100].timestamp] },
43
+ onSelectedTimeframe: (index, bounds) => {
44
+ console.log('onSelectedTimeframe', index, bounds);
45
45
  },
46
46
  },
47
47
  render: function Component(args) {
48
48
  const [, setArgs] = useArgs();
49
- const onSelectedTimeline = (index, bounds) => {
50
- args.onSelectedTimeline(index, bounds);
51
- setArgs({ ...args, selectedTimeline: { index, bounds } });
49
+ const onSelectedTimeframe = (index, bounds) => {
50
+ args.onSelectedTimeframe(index, bounds);
51
+ setArgs({ ...args, selectedTimeframe: { index, bounds } });
52
52
  };
53
- return _jsx(MetricsGraphStrips, { ...args, onSelectedTimeline: onSelectedTimeline });
53
+ return _jsx(MetricsGraphStrips, { ...args, onSelectedTimeframe: onSelectedTimeframe });
54
54
  },
55
55
  };
@@ -1,15 +1,16 @@
1
+ import { LabelSet } from '@parca/client';
1
2
  import { NumberDuo } from '../utils';
2
3
  import { DataPoint } from './AreaGraph';
3
4
  interface Props {
4
- cpus: string[];
5
+ cpus: LabelSet[];
5
6
  data: DataPoint[][];
6
- selectedTimeline?: {
7
- index: number;
7
+ selectedTimeframe?: {
8
+ labels: LabelSet;
8
9
  bounds: NumberDuo;
9
10
  };
10
- onSelectedTimeline: (index: number, bounds: NumberDuo | undefined) => void;
11
+ onSelectedTimeframe: (labels: LabelSet, bounds: NumberDuo | undefined) => void;
11
12
  width?: number;
12
13
  }
13
- export declare const MetricsGraphStrips: ({ cpus, data, selectedTimeline, onSelectedTimeline, width, }: Props) => JSX.Element;
14
+ export declare const MetricsGraphStrips: ({ cpus, data, selectedTimeframe, onSelectedTimeframe, width, }: Props) => JSX.Element;
14
15
  export {};
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MetricsGraphStrips/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAY,SAAS,EAAC,MAAM,aAAa,CAAC;AAEjD,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,SAAS,CAAC;KACnB,CAAC;IACF,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,eAAO,MAAM,kBAAkB,iEAM5B,KAAK,KAAG,GAAG,CAAC,OA+Dd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MetricsGraphStrips/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAGvC,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAY,SAAS,EAAC,MAAM,aAAa,CAAC;AAEjD,UAAU,KAAK;IACb,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;CAChB;AA2BD,eAAO,MAAM,kBAAkB,mEAM5B,KAAK,KAAG,GAAG,CAAC,OAgEd,CAAC"}
@@ -16,10 +16,26 @@ import { Icon } from '@iconify/react';
16
16
  import * as d3 from 'd3';
17
17
  import { TimelineGuide } from '../TimelineGuide';
18
18
  import { AreaGraph } from './AreaGraph';
19
+ const labelSetToString = (labelSet) => {
20
+ if (labelSet === undefined) {
21
+ return '{}';
22
+ }
23
+ let str = '{';
24
+ let isFirst = true;
25
+ for (const label of labelSet.labels) {
26
+ if (!isFirst) {
27
+ str += ', ';
28
+ isFirst = false;
29
+ }
30
+ str += `${label.name}: ${label.value}`;
31
+ }
32
+ str += '}';
33
+ return str;
34
+ };
19
35
  const getTimelineGuideHeight = (cpus, collapsedIndices) => {
20
36
  return 56 * (cpus.length - collapsedIndices.length) + 20 * collapsedIndices.length + 24;
21
37
  };
22
- export const MetricsGraphStrips = ({ cpus, data, selectedTimeline, onSelectedTimeline, width, }) => {
38
+ export const MetricsGraphStrips = ({ cpus, data, selectedTimeframe, onSelectedTimeframe, width, }) => {
23
39
  const [collapsedIndices, setCollapsedIndices] = useState([]);
24
40
  // @ts-expect-error
25
41
  const color = d3.scaleOrdinal(d3.schemeObservable10);
@@ -35,6 +51,7 @@ export const MetricsGraphStrips = ({ cpus, data, selectedTimeline, onSelectedTim
35
51
  }, [data]);
36
52
  return (_jsxs("div", { className: "flex flex-col gap-1 relative my-0 ml-[70px]", style: { width: width ?? '100%' }, children: [_jsx(TimelineGuide, { bounds: bounds, width: width ?? 1468, height: getTimelineGuideHeight(cpus, collapsedIndices), margin: 1 }), cpus.map((cpu, i) => {
37
53
  const isCollapsed = collapsedIndices.includes(i);
54
+ const labelStr = labelSetToString(cpu);
38
55
  return (_jsxs("div", { className: "relative min-h-5", style: { width: width ?? 1468 }, children: [_jsxs("div", { className: "text-xs absolute top-0 left-0 flex gap-[2px] items-center bg-white/50 px-1 rounded-sm cursor-pointer z-30", onClick: () => {
39
56
  const newCollapsedIndices = [...collapsedIndices];
40
57
  if (collapsedIndices.includes(i)) {
@@ -44,8 +61,8 @@ export const MetricsGraphStrips = ({ cpus, data, selectedTimeline, onSelectedTim
44
61
  newCollapsedIndices.push(i);
45
62
  }
46
63
  setCollapsedIndices(newCollapsedIndices);
47
- }, children: [_jsx(Icon, { icon: isCollapsed ? 'bxs:right-arrow' : 'bxs:down-arrow' }), cpu] }), !isCollapsed ? (_jsx(AreaGraph, { data: data[i], height: 56, width: width ?? 1468, fill: color(i.toString()), selectionBounds: selectedTimeline?.index === i ? selectedTimeline.bounds : undefined, setSelectionBounds: bounds => {
48
- onSelectedTimeline(i, bounds);
49
- } })) : null] }, cpu));
64
+ }, children: [_jsx(Icon, { icon: isCollapsed ? 'bxs:right-arrow' : 'bxs:down-arrow' }), labelStr] }), !isCollapsed ? (_jsx(AreaGraph, { data: data[i], height: 56, width: width ?? 1468, fill: color(labelStr), selectionBounds: cpu === selectedTimeframe?.labels ? selectedTimeframe.bounds : undefined, setSelectionBounds: bounds => {
65
+ onSelectedTimeframe(cpu, bounds);
66
+ } })) : null] }, labelStr));
50
67
  })] }));
51
68
  };
@@ -9,6 +9,7 @@ export declare const FIELD_MAPPING_BUILD_ID = "mapping_build_id";
9
9
  export declare const FIELD_LOCATION_ADDRESS = "location_address";
10
10
  export declare const FIELD_LOCATION_LINE = "location_line";
11
11
  export declare const FIELD_INLINED = "inlined";
12
+ export declare const FIELD_TIMESTAMP = "timestamp";
12
13
  export declare const FIELD_FUNCTION_NAME = "function_name";
13
14
  export declare const FIELD_FUNCTION_SYSTEM_NAME = "function_system_name";
14
15
  export declare const FIELD_FUNCTION_FILE_NAME = "function_file_name";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAKrF,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAQ1C,OAAO,EAA2B,KAAK,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAO5E,OAAO,EAAwB,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAIxE,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAC9D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,UAAU,qBAAqB;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,gBAAgB,iBACb,MAAM,EAAE,cACV,OAAO,uBACE,WAAW,KAC/B,aAQF,CAAC;AAEF,eAAO,MAAM,iBAAiB,kBACb,MAAM,EAAE,cACX,OAAO,uBACE,WAAW,KAC/B,aAQF,CAAC;AAIF,eAAO,MAAM,gBAAgB,mDAiR3B,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAKrF,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAQ1C,OAAO,EAA2B,KAAK,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAO5E,OAAO,EAAwB,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAIxE,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAC9D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,UAAU,qBAAqB;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,gBAAgB,iBACb,MAAM,EAAE,cACV,OAAO,uBACE,WAAW,KAC/B,aAQF,CAAC;AAEF,eAAO,MAAM,iBAAiB,kBACb,MAAM,EAAE,cACX,OAAO,uBACE,WAAW,KAC/B,aAQF,CAAC;AAIF,eAAO,MAAM,gBAAgB,mDAiR3B,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
@@ -32,6 +32,7 @@ export const FIELD_MAPPING_BUILD_ID = 'mapping_build_id';
32
32
  export const FIELD_LOCATION_ADDRESS = 'location_address';
33
33
  export const FIELD_LOCATION_LINE = 'location_line';
34
34
  export const FIELD_INLINED = 'inlined';
35
+ export const FIELD_TIMESTAMP = 'timestamp';
35
36
  export const FIELD_FUNCTION_NAME = 'function_name';
36
37
  export const FIELD_FUNCTION_SYSTEM_NAME = 'function_system_name';
37
38
  export const FIELD_FUNCTION_FILE_NAME = 'function_file_name';
@@ -17,8 +17,7 @@ interface ProfileIcicleGraphProps {
17
17
  isHalfScreen: boolean;
18
18
  metadataMappingFiles?: string[];
19
19
  metadataLoading?: boolean;
20
- showTimelineGuide?: boolean;
21
20
  }
22
- declare const ProfileIcicleGraph: ({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, showTimelineGuide, }: ProfileIcicleGraphProps) => JSX.Element;
21
+ declare const ProfileIcicleGraph: ({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, }: ProfileIcicleGraphProps) => JSX.Element;
23
22
  export default ProfileIcicleGraph;
24
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAI1D,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAY1C,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,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,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,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAMD,QAAA,MAAM,kBAAkB,0JAcrB,uBAAuB,KAAG,GAAG,CAAC,OA2LhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAI1D,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAY1C,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,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,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;CAC3B;AAMD,QAAA,MAAM,kBAAkB,uIAarB,uBAAuB,KAAG,GAAG,CAAC,OA2LhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -25,9 +25,9 @@ const numberFormatter = new Intl.NumberFormat('en-US');
25
25
  const ErrorContent = ({ errorMessage }) => {
26
26
  return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
27
27
  };
28
- const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, showTimelineGuide = false, }) {
28
+ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, }) {
29
29
  const { onError, authenticationErrorMessage, isDarkMode } = useParcaContext();
30
- const { compareMode } = useProfileViewContext();
30
+ const { compareMode, timelineGuide } = useProfileViewContext();
31
31
  const [isLoading, setIsLoading] = useState(true);
32
32
  const mappingsList = useMappingList(metadataMappingFiles);
33
33
  const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState('sort_by');
@@ -83,7 +83,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
83
83
  if (graph !== undefined)
84
84
  return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType }));
85
85
  if (arrow !== undefined)
86
- return (_jsxs("div", { className: "relative", children: [showTimelineGuide && (_jsx(TimelineGuide, { bounds: [0, 60000], width: width, height: 1000, margin: 0, ticks: 60000 / 10000 })), _jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList, compareAbsolute: isCompareAbsolute })] }));
86
+ return (_jsxs("div", { className: "relative", children: [timelineGuide?.show === true && (_jsx(TimelineGuide, { bounds: timelineGuide.props.bounds, width: width, height: 1000, margin: 0, ticks: 60000 / 10000 })), _jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList, compareAbsolute: isCompareAbsolute })] }));
87
87
  }, [
88
88
  isLoading,
89
89
  graph,
@@ -100,7 +100,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
100
100
  isDarkMode,
101
101
  mappingsList,
102
102
  isCompareAbsolute,
103
- showTimelineGuide,
103
+ timelineGuide,
104
104
  ]);
105
105
  if (error != null) {
106
106
  onError?.(error);
@@ -20,8 +20,7 @@ interface GetDashboardItemProps {
20
20
  perf?: {
21
21
  onRender?: ProfilerOnRenderCallback;
22
22
  };
23
- showTimelineGuide?: boolean;
24
23
  }
25
- export declare const getDashboardItem: ({ type, isHalfScreen, dimensions, flamegraphData, topTableData, callgraphData, sourceData, profileSource, total, filtered, curPath, setNewCurPath, currentSearchString, setSearchString, callgraphSVG, perf, showTimelineGuide, }: GetDashboardItemProps) => JSX.Element;
24
+ export declare const getDashboardItem: ({ type, isHalfScreen, dimensions, flamegraphData, topTableData, callgraphData, sourceData, profileSource, total, filtered, curPath, setNewCurPath, currentSearchString, setSearchString, callgraphSVG, perf, }: GetDashboardItemProps) => JSX.Element;
26
25
  export {};
27
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAMzD,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAGrD,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,sOAkB1B,qBAAqB,KAAG,GAAG,CAAC,OAgF9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAMzD,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAGrD,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;CACH;AAED,eAAO,MAAM,gBAAgB,mNAiB1B,qBAAqB,KAAG,GAAG,CAAC,OA+E9B,CAAC"}
@@ -17,7 +17,7 @@ import Callgraph from '../../../Callgraph';
17
17
  import ProfileIcicleGraph from '../../../ProfileIcicleGraph';
18
18
  import { SourceView } from '../../../SourceView';
19
19
  import { Table } from '../../../Table';
20
- export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphData, topTableData, callgraphData, sourceData, profileSource, total, filtered, curPath, setNewCurPath, currentSearchString, setSearchString, callgraphSVG, perf, showTimelineGuide, }) => {
20
+ export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphData, topTableData, callgraphData, sourceData, profileSource, total, filtered, curPath, setNewCurPath, currentSearchString, setSearchString, callgraphSVG, perf, }) => {
21
21
  switch (type) {
22
22
  case 'icicle':
23
23
  return (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
@@ -27,7 +27,7 @@ export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphDat
27
27
  ? isHalfScreen
28
28
  ? (dimensions.width - 54) / 2
29
29
  : dimensions.width - 16
30
- : 0, metadataMappingFiles: flamegraphData.metadataMappingFiles, metadataLoading: flamegraphData.metadataLoading, showTimelineGuide: showTimelineGuide }) }));
30
+ : 0, metadataMappingFiles: flamegraphData.metadataMappingFiles, metadataLoading: flamegraphData.metadataLoading }) }));
31
31
  case 'callgraph':
32
32
  return callgraphData?.data !== undefined &&
33
33
  callgraphSVG !== undefined &&
@@ -1,8 +1,18 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ProfileSource } from '../../ProfileSource';
3
+ import { NumberDuo } from '../../utils';
4
+ export type TimelineGuideData = {
5
+ show: false;
6
+ } | {
7
+ show: true;
8
+ props: {
9
+ bounds: NumberDuo;
10
+ };
11
+ };
3
12
  interface Props {
4
13
  profileSource?: ProfileSource;
5
14
  compareMode: boolean;
15
+ timelineGuide?: TimelineGuideData;
6
16
  }
7
17
  export declare const defaultValue: Props;
8
18
  declare const ProfileViewContext: import("react").Context<Props>;
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileViewContext.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/context/ProfileViewContext.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,SAAS,EAA4B,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,UAAU,KAAK;IACb,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF,QAAA,MAAM,kBAAkB,gCAAqC,CAAC;AAE9D,eAAO,MAAM,0BAA0B,yBAGpC;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,KAAG,GAAG,CAAC,OAMP,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,KAMxC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ProfileViewContext.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/context/ProfileViewContext.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,SAAS,EAA4B,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,MAAM,MAAM,iBAAiB,GACzB;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GACb;IACE,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE;QACL,MAAM,EAAE,SAAS,CAAC;KACnB,CAAC;CACH,CAAC;AAEN,UAAU,KAAK;IACb,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,eAAO,MAAM,YAAY,EAAE,KAI1B,CAAC;AAEF,QAAA,MAAM,kBAAkB,gCAAqC,CAAC;AAE9D,eAAO,MAAM,0BAA0B,yBAGpC;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,KAAG,GAAG,CAAC,OAMP,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,KAMxC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -15,6 +15,7 @@ import { createContext, useContext } from 'react';
15
15
  export const defaultValue = {
16
16
  profileSource: undefined,
17
17
  compareMode: false,
18
+ timelineGuide: { show: false },
18
19
  };
19
20
  const ProfileViewContext = createContext(defaultValue);
20
21
  export const ProfileViewContextProvider = ({ children, value, }) => {
@@ -1,3 +1,3 @@
1
1
  import type { ProfileViewProps } from './types/visualization';
2
- export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, showTimelineGuide, }: ProfileViewProps) => JSX.Element;
2
+ export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, timelineGuide, }: ProfileViewProps) => JSX.Element;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAG/E,eAAO,MAAM,WAAW,wMAcrB,gBAAgB,KAAG,GAAG,CAAC,OAyIzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAG/E,eAAO,MAAM,WAAW,oMAcrB,gBAAgB,KAAG,GAAG,CAAC,OAwIzB,CAAC"}
@@ -26,7 +26,7 @@ import { useGraphviz } from './hooks/useGraphviz';
26
26
  import { useProfileMetadata } from './hooks/useProfileMetadata';
27
27
  import { useVisualizationState } from './hooks/useVisualizationState';
28
28
  import { getColorRange } from './utils/colorUtils';
29
- export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, showTimelineGuide, }) => {
29
+ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, timelineGuide, }) => {
30
30
  const { timezone, perf, profileViewExternalMainActions, preferencesModal, profileViewExternalSubActions, } = useParcaContext();
31
31
  const { ref, dimensions } = useContainerDimensions();
32
32
  const isDarkMode = useAppSelector(selectDarkMode);
@@ -64,7 +64,6 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
64
64
  setSearchString,
65
65
  callgraphSVG,
66
66
  perf,
67
- showTimelineGuide,
68
67
  });
69
68
  };
70
69
  const actionButtons = {
@@ -72,5 +71,5 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
72
71
  table: (_jsx(TableToolbar, { profileType: profileSource?.ProfileType(), total: total, filtered: filtered, clearSelection: clearSelection, currentSearchString: currentSearchString })),
73
72
  };
74
73
  const hasProfileSource = profileSource !== undefined && profileSource.toString(timezone) !== '';
75
- return (_jsx(KeyDownProvider, { children: _jsx(ProfileViewContextProvider, { value: { profileSource, compareMode }, children: _jsxs(DashboardProvider, { children: [_jsx(ProfileHeader, { profileSourceString: profileSource?.toString(timezone), hasProfileSource: hasProfileSource, externalMainActions: profileViewExternalMainActions }), _jsx(VisualisationToolbar, { groupBy: groupBy, toggleGroupBy: toggleGroupBy, hasProfileSource: hasProfileSource, pprofdownloading: pprofDownloading, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: onDownloadPProf, curPath: curPath, setNewCurPath: setCurPath, profileType: profileSource?.ProfileType(), total: total, filtered: filtered, currentSearchString: currentSearchString, setSearchString: setSearchString, groupByLabels: flamegraphData.metadataLabels ?? [], preferencesModal: preferencesModal, profileViewExternalSubActions: profileViewExternalSubActions, clearSelection: clearSelection, setGroupByLabels: setGroupByLabels, showVisualizationSelector: showVisualizationSelector }), isColorStackLegendEnabled && (_jsx(ColorStackLegend, { compareMode: compareMode, mappings: colorMappings, loading: flamegraphData.metadataLoading })), _jsx("div", { className: "w-full", ref: ref, children: _jsx(DashboardLayout, { getDashboardItemByType: getDashboardItemByType, actionButtons: actionButtons }) })] }) }) }));
74
+ return (_jsx(KeyDownProvider, { children: _jsx(ProfileViewContextProvider, { value: { profileSource, compareMode, timelineGuide }, children: _jsxs(DashboardProvider, { children: [_jsx(ProfileHeader, { profileSourceString: profileSource?.toString(timezone), hasProfileSource: hasProfileSource, externalMainActions: profileViewExternalMainActions }), _jsx(VisualisationToolbar, { groupBy: groupBy, toggleGroupBy: toggleGroupBy, hasProfileSource: hasProfileSource, pprofdownloading: pprofDownloading, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: onDownloadPProf, curPath: curPath, setNewCurPath: setCurPath, profileType: profileSource?.ProfileType(), total: total, filtered: filtered, currentSearchString: currentSearchString, setSearchString: setSearchString, groupByLabels: flamegraphData.metadataLabels ?? [], preferencesModal: preferencesModal, profileViewExternalSubActions: profileViewExternalSubActions, clearSelection: clearSelection, setGroupByLabels: setGroupByLabels, showVisualizationSelector: showVisualizationSelector }), isColorStackLegendEnabled && (_jsx(ColorStackLegend, { compareMode: compareMode, mappings: colorMappings, loading: flamegraphData.metadataLoading })), _jsx("div", { className: "w-full", ref: ref, children: _jsx(DashboardLayout, { getDashboardItemByType: getDashboardItemByType, actionButtons: actionButtons }) })] }) }) }));
76
75
  };
@@ -1,5 +1,6 @@
1
1
  import { Callgraph as CallgraphType, Flamegraph, FlamegraphArrow, QueryServiceClient, Source, TableArrow } from '@parca/client';
2
2
  import { ProfileSource } from '../../ProfileSource';
3
+ import { TimelineGuideData } from '../context/ProfileViewContext';
3
4
  export interface FlamegraphData {
4
5
  loading: boolean;
5
6
  data?: Flamegraph;
@@ -46,5 +47,6 @@ export interface ProfileViewProps {
46
47
  pprofDownloading?: boolean;
47
48
  showVisualizationSelector?: boolean;
48
49
  showTimelineGuide?: boolean;
50
+ timelineGuide?: TimelineGuideData;
49
51
  }
50
52
  //# sourceMappingURL=visualization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visualization.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/types/visualization.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B"}
1
+ {"version":3,"file":"visualization.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/types/visualization.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC"}
@@ -1,12 +1,14 @@
1
1
  import { QueryServiceClient } from '@parca/client';
2
2
  import { ProfileSource } from './ProfileSource';
3
+ import { TimelineGuideData } from './ProfileView/context/ProfileViewContext';
3
4
  interface ProfileViewWithDataProps {
4
5
  queryClient: QueryServiceClient;
5
6
  profileSource: ProfileSource;
6
7
  compare?: boolean;
7
8
  showVisualizationSelector?: boolean;
8
- showTimelineGuide?: boolean;
9
+ isGroupByTimestamp?: boolean;
10
+ timelineGuide?: TimelineGuideData;
9
11
  }
10
- export declare const ProfileViewWithData: ({ queryClient, profileSource, showVisualizationSelector, showTimelineGuide, }: ProfileViewWithDataProps) => JSX.Element;
12
+ export declare const ProfileViewWithData: ({ queryClient, profileSource, showVisualizationSelector, isGroupByTimestamp, timelineGuide, }: ProfileViewWithDataProps) => JSX.Element;
11
13
  export default ProfileViewWithData;
12
14
  //# sourceMappingURL=ProfileViewWithData.d.ts.map
@@ -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;IACpC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,mBAAmB,kFAK7B,wBAAwB,KAAG,GAAG,CAAC,OAmNjC,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;AAK1E,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,iBAAiB,EAAC,MAAM,0CAA0C,CAAC;AAI3E,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,eAAO,MAAM,mBAAmB,kGAM7B,wBAAwB,KAAG,GAAG,CAAC,OAsNjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -15,11 +15,11 @@ 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 { FIELD_FUNCTION_NAME } from './ProfileIcicleGraph/IcicleGraphArrow';
18
+ import { FIELD_FUNCTION_NAME, FIELD_TIMESTAMP } from './ProfileIcicleGraph/IcicleGraphArrow';
19
19
  import { ProfileView } from './ProfileView';
20
20
  import { useQuery } from './useQuery';
21
21
  import { downloadPprof } from './utils';
22
- export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizationSelector, showTimelineGuide, }) => {
22
+ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizationSelector, isGroupByTimestamp, timelineGuide, }) => {
23
23
  const metadata = useGrpcMetadata();
24
24
  const [dashboardItems] = useURLState('dashboard_items', {
25
25
  alwaysReturnArray: true,
@@ -27,7 +27,10 @@ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizat
27
27
  const [sourceBuildID] = useURLState('source_buildid');
28
28
  const [sourceFilename] = useURLState('source_filename');
29
29
  const [groupBy] = useURLState('group_by', {
30
- defaultValue: [FIELD_FUNCTION_NAME],
30
+ defaultValue: [
31
+ isGroupByTimestamp === true ? FIELD_TIMESTAMP : null,
32
+ FIELD_FUNCTION_NAME,
33
+ ].filter(Boolean),
31
34
  alwaysReturnArray: true,
32
35
  });
33
36
  const [invertStack] = useURLState('invert_call_stack');
@@ -168,6 +171,6 @@ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizat
168
171
  ? sourceResponse?.report?.source
169
172
  : undefined,
170
173
  error: sourceError,
171
- }, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: () => void downloadPProfClick(), pprofDownloading: pprofDownloading, showVisualizationSelector: showVisualizationSelector, showTimelineGuide: showTimelineGuide }));
174
+ }, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: () => void downloadPProfClick(), pprofDownloading: pprofDownloading, showVisualizationSelector: showVisualizationSelector, timelineGuide: timelineGuide }));
172
175
  };
173
176
  export default ProfileViewWithData;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/TimelineGuide/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAEnC,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,eAAO,MAAM,aAAa,6CAA4C,KAAK,KAAG,GAAG,CAAC,OA8DjF,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/TimelineGuide/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAEnC,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,eAAO,MAAM,aAAa,6CAA4C,KAAK,KAAG,GAAG,CAAC,OAyDjF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from './ProfileViewWithData';
11
11
  export * from './utils';
12
12
  export * from './ProfileTypeSelector';
13
13
  export * from './SourceView';
14
+ export * from './ProfileMetricsGraph';
14
15
  export { default as Callgraph } from './Callgraph';
15
16
  export declare const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES: {
16
17
  dashboard_items: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,KAAK,IAAI,cAAc,EAAC,MAAM,aAAa,CAAC;AACzD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,eAAe,EAAE,EAAC,sBAAsB,EAAC,MAAM,mBAAmB,CAAC;AAC1E,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAC,OAAO,IAAI,SAAS,EAAC,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,qCAAqC;;CAEjD,CAAC;AAEF,YAAY,EAAC,cAAc,EAAC,CAAC;AAE7B,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,KAAK,IAAI,cAAc,EAAC,MAAM,aAAa,CAAC;AACzD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,eAAe,EAAE,EAAC,sBAAsB,EAAC,MAAM,mBAAmB,CAAC;AAC1E,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAC,OAAO,IAAI,SAAS,EAAC,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,qCAAqC;;CAEjD,CAAC;AAEF,YAAY,EAAC,cAAc,EAAC,CAAC;AAE7B,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAC,CAAC"}
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export * from './ProfileViewWithData';
22
22
  export * from './utils';
23
23
  export * from './ProfileTypeSelector';
24
24
  export * from './SourceView';
25
+ export * from './ProfileMetricsGraph';
25
26
  export { default as Callgraph } from './Callgraph';
26
27
  export const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES = {
27
28
  dashboard_items: 'icicle',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.452",
3
+ "version": "0.16.453",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
@@ -74,5 +74,5 @@
74
74
  "access": "public",
75
75
  "registry": "https://registry.npmjs.org/"
76
76
  },
77
- "gitHead": "b4fffef9d7661cfe6e2cb36a6bc59961e9de6fe9"
77
+ "gitHead": "2e1089b0b34e67c26a29567db2c1e30e9516d10e"
78
78
  }
@@ -46,21 +46,21 @@ export default meta;
46
46
 
47
47
  export const ThreeCPUStrips = {
48
48
  args: {
49
- cpus: Array.from(mockData, (_, i) => `CPU ${i + 1}`),
49
+ cpus: Array.from(mockData, (_, i) => ({labels: [{name: 'cpuid', value: i + 1}]})),
50
50
  data: mockData,
51
- selectedTimeline: {index: 1, bounds: [mockData[0][25].timestamp, mockData[0][100].timestamp]},
52
- onSelectedTimeline: (index: number, bounds: NumberDuo): void => {
53
- console.log('onSelectedTimeline', index, bounds);
51
+ selectedTimeframe: {index: 1, bounds: [mockData[0][25].timestamp, mockData[0][100].timestamp]},
52
+ onSelectedTimeframe: (index: number, bounds: NumberDuo): void => {
53
+ console.log('onSelectedTimeframe', index, bounds);
54
54
  },
55
55
  },
56
56
  render: function Component(args: any): JSX.Element {
57
57
  const [, setArgs] = useArgs();
58
58
 
59
- const onSelectedTimeline = (index: number, bounds: NumberDuo): void => {
60
- args.onSelectedTimeline(index, bounds);
61
- setArgs({...args, selectedTimeline: {index, bounds}});
59
+ const onSelectedTimeframe = (index: number, bounds: NumberDuo): void => {
60
+ args.onSelectedTimeframe(index, bounds);
61
+ setArgs({...args, selectedTimeframe: {index, bounds}});
62
62
  };
63
63
 
64
- return <MetricsGraphStrips {...args} onSelectedTimeline={onSelectedTimeline} />;
64
+ return <MetricsGraphStrips {...args} onSelectedTimeframe={onSelectedTimeframe} />;
65
65
  },
66
66
  };
@@ -16,30 +16,53 @@ import {useMemo, useState} from 'react';
16
16
  import {Icon} from '@iconify/react';
17
17
  import * as d3 from 'd3';
18
18
 
19
+ import {LabelSet} from '@parca/client';
20
+
19
21
  import {TimelineGuide} from '../TimelineGuide';
20
22
  import {NumberDuo} from '../utils';
21
23
  import {AreaGraph, DataPoint} from './AreaGraph';
22
24
 
23
25
  interface Props {
24
- cpus: string[];
26
+ cpus: LabelSet[];
25
27
  data: DataPoint[][];
26
- selectedTimeline?: {
27
- index: number;
28
+ selectedTimeframe?: {
29
+ labels: LabelSet;
28
30
  bounds: NumberDuo;
29
31
  };
30
- onSelectedTimeline: (index: number, bounds: NumberDuo | undefined) => void;
32
+ onSelectedTimeframe: (labels: LabelSet, bounds: NumberDuo | undefined) => void;
31
33
  width?: number;
32
34
  }
33
35
 
34
- const getTimelineGuideHeight = (cpus: string[], collapsedIndices: number[]): number => {
36
+ const labelSetToString = (labelSet?: LabelSet): string => {
37
+ if (labelSet === undefined) {
38
+ return '{}';
39
+ }
40
+
41
+ let str = '{';
42
+
43
+ let isFirst = true;
44
+ for (const label of labelSet.labels) {
45
+ if (!isFirst) {
46
+ str += ', ';
47
+ isFirst = false;
48
+ }
49
+ str += `${label.name}: ${label.value}`;
50
+ }
51
+
52
+ str += '}';
53
+
54
+ return str;
55
+ };
56
+
57
+ const getTimelineGuideHeight = (cpus: LabelSet[], collapsedIndices: number[]): number => {
35
58
  return 56 * (cpus.length - collapsedIndices.length) + 20 * collapsedIndices.length + 24;
36
59
  };
37
60
 
38
61
  export const MetricsGraphStrips = ({
39
62
  cpus,
40
63
  data,
41
- selectedTimeline,
42
- onSelectedTimeline,
64
+ selectedTimeframe,
65
+ onSelectedTimeframe,
43
66
  width,
44
67
  }: Props): JSX.Element => {
45
68
  const [collapsedIndices, setCollapsedIndices] = useState<number[]>([]);
@@ -68,8 +91,9 @@ export const MetricsGraphStrips = ({
68
91
  />
69
92
  {cpus.map((cpu, i) => {
70
93
  const isCollapsed = collapsedIndices.includes(i);
94
+ const labelStr = labelSetToString(cpu);
71
95
  return (
72
- <div className="relative min-h-5" style={{width: width ?? 1468}} key={cpu}>
96
+ <div className="relative min-h-5" style={{width: width ?? 1468}} key={labelStr}>
73
97
  <div
74
98
  className="text-xs absolute top-0 left-0 flex gap-[2px] items-center bg-white/50 px-1 rounded-sm cursor-pointer z-30"
75
99
  onClick={() => {
@@ -83,19 +107,19 @@ export const MetricsGraphStrips = ({
83
107
  }}
84
108
  >
85
109
  <Icon icon={isCollapsed ? 'bxs:right-arrow' : 'bxs:down-arrow'} />
86
- {cpu}
110
+ {labelStr}
87
111
  </div>
88
112
  {!isCollapsed ? (
89
113
  <AreaGraph
90
114
  data={data[i]}
91
115
  height={56}
92
116
  width={width ?? 1468}
93
- fill={color(i.toString()) as string}
117
+ fill={color(labelStr) as string}
94
118
  selectionBounds={
95
- selectedTimeline?.index === i ? selectedTimeline.bounds : undefined
119
+ cpu === selectedTimeframe?.labels ? selectedTimeframe.bounds : undefined
96
120
  }
97
121
  setSelectionBounds={bounds => {
98
- onSelectedTimeline(i, bounds);
122
+ onSelectedTimeframe(cpu, bounds);
99
123
  }}
100
124
  />
101
125
  ) : null}
@@ -44,6 +44,7 @@ export const FIELD_MAPPING_BUILD_ID = 'mapping_build_id';
44
44
  export const FIELD_LOCATION_ADDRESS = 'location_address';
45
45
  export const FIELD_LOCATION_LINE = 'location_line';
46
46
  export const FIELD_INLINED = 'inlined';
47
+ export const FIELD_TIMESTAMP = 'timestamp';
47
48
  export const FIELD_FUNCTION_NAME = 'function_name';
48
49
  export const FIELD_FUNCTION_SYSTEM_NAME = 'function_system_name';
49
50
  export const FIELD_FUNCTION_FILE_NAME = 'function_file_name';
@@ -46,7 +46,6 @@ interface ProfileIcicleGraphProps {
46
46
  isHalfScreen: boolean;
47
47
  metadataMappingFiles?: string[];
48
48
  metadataLoading?: boolean;
49
- showTimelineGuide?: boolean;
50
49
  }
51
50
 
52
51
  const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
@@ -66,10 +65,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
66
65
  width,
67
66
  isHalfScreen,
68
67
  metadataMappingFiles,
69
- showTimelineGuide = false,
70
68
  }: ProfileIcicleGraphProps): JSX.Element {
71
69
  const {onError, authenticationErrorMessage, isDarkMode} = useParcaContext();
72
- const {compareMode} = useProfileViewContext();
70
+ const {compareMode, timelineGuide} = useProfileViewContext();
73
71
  const [isLoading, setIsLoading] = useState<boolean>(true);
74
72
 
75
73
  const mappingsList = useMappingList(metadataMappingFiles);
@@ -169,9 +167,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
169
167
  if (arrow !== undefined)
170
168
  return (
171
169
  <div className="relative">
172
- {showTimelineGuide && (
170
+ {timelineGuide?.show === true && (
173
171
  <TimelineGuide
174
- bounds={[0, 60000]}
172
+ bounds={timelineGuide.props.bounds}
175
173
  width={width}
176
174
  height={1000}
177
175
  margin={0}
@@ -210,7 +208,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
210
208
  isDarkMode,
211
209
  mappingsList,
212
210
  isCompareAbsolute,
213
- showTimelineGuide,
211
+ timelineGuide,
214
212
  ]);
215
213
 
216
214
  if (error != null) {
@@ -47,7 +47,6 @@ interface GetDashboardItemProps {
47
47
  perf?: {
48
48
  onRender?: ProfilerOnRenderCallback;
49
49
  };
50
- showTimelineGuide?: boolean;
51
50
  }
52
51
 
53
52
  export const getDashboardItem = ({
@@ -67,7 +66,6 @@ export const getDashboardItem = ({
67
66
  setSearchString,
68
67
  callgraphSVG,
69
68
  perf,
70
- showTimelineGuide,
71
69
  }: GetDashboardItemProps): JSX.Element => {
72
70
  switch (type) {
73
71
  case 'icicle':
@@ -100,7 +98,6 @@ export const getDashboardItem = ({
100
98
  }
101
99
  metadataMappingFiles={flamegraphData.metadataMappingFiles}
102
100
  metadataLoading={flamegraphData.metadataLoading}
103
- showTimelineGuide={showTimelineGuide}
104
101
  />
105
102
  </ConditionalWrapper>
106
103
  );
@@ -14,15 +14,27 @@
14
14
  import {ReactNode, createContext, useContext} from 'react';
15
15
 
16
16
  import {ProfileSource} from '../../ProfileSource';
17
+ import {NumberDuo} from '../../utils';
18
+
19
+ export type TimelineGuideData =
20
+ | {show: false}
21
+ | {
22
+ show: true;
23
+ props: {
24
+ bounds: NumberDuo;
25
+ };
26
+ };
17
27
 
18
28
  interface Props {
19
29
  profileSource?: ProfileSource;
20
30
  compareMode: boolean;
31
+ timelineGuide?: TimelineGuideData;
21
32
  }
22
33
 
23
34
  export const defaultValue: Props = {
24
35
  profileSource: undefined,
25
36
  compareMode: false,
37
+ timelineGuide: {show: false},
26
38
  };
27
39
 
28
40
  const ProfileViewContext = createContext<Props>(defaultValue);
@@ -42,7 +42,7 @@ export const ProfileView = ({
42
42
  pprofDownloading,
43
43
  compare,
44
44
  showVisualizationSelector,
45
- showTimelineGuide,
45
+ timelineGuide,
46
46
  }: ProfileViewProps): JSX.Element => {
47
47
  const {
48
48
  timezone,
@@ -110,7 +110,6 @@ export const ProfileView = ({
110
110
  setSearchString,
111
111
  callgraphSVG,
112
112
  perf,
113
- showTimelineGuide,
114
113
  });
115
114
  };
116
115
 
@@ -131,7 +130,7 @@ export const ProfileView = ({
131
130
 
132
131
  return (
133
132
  <KeyDownProvider>
134
- <ProfileViewContextProvider value={{profileSource, compareMode}}>
133
+ <ProfileViewContextProvider value={{profileSource, compareMode, timelineGuide}}>
135
134
  <DashboardProvider>
136
135
  <ProfileHeader
137
136
  profileSourceString={profileSource?.toString(timezone)}
@@ -21,6 +21,7 @@ import {
21
21
  } from '@parca/client';
22
22
 
23
23
  import {ProfileSource} from '../../ProfileSource';
24
+ import {TimelineGuideData} from '../context/ProfileViewContext';
24
25
 
25
26
  export interface FlamegraphData {
26
27
  loading: boolean;
@@ -73,4 +74,5 @@ export interface ProfileViewProps {
73
74
  pprofDownloading?: boolean;
74
75
  showVisualizationSelector?: boolean;
75
76
  showTimelineGuide?: boolean;
77
+ timelineGuide?: TimelineGuideData;
76
78
  }
@@ -17,9 +17,10 @@ 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 {FIELD_FUNCTION_NAME} from './ProfileIcicleGraph/IcicleGraphArrow';
20
+ import {FIELD_FUNCTION_NAME, FIELD_TIMESTAMP} from './ProfileIcicleGraph/IcicleGraphArrow';
21
21
  import {ProfileSource} from './ProfileSource';
22
22
  import {ProfileView} from './ProfileView';
23
+ import {TimelineGuideData} from './ProfileView/context/ProfileViewContext';
23
24
  import {useQuery} from './useQuery';
24
25
  import {downloadPprof} from './utils';
25
26
 
@@ -28,14 +29,16 @@ interface ProfileViewWithDataProps {
28
29
  profileSource: ProfileSource;
29
30
  compare?: boolean;
30
31
  showVisualizationSelector?: boolean;
31
- showTimelineGuide?: boolean;
32
+ isGroupByTimestamp?: boolean;
33
+ timelineGuide?: TimelineGuideData;
32
34
  }
33
35
 
34
36
  export const ProfileViewWithData = ({
35
37
  queryClient,
36
38
  profileSource,
37
39
  showVisualizationSelector,
38
- showTimelineGuide,
40
+ isGroupByTimestamp,
41
+ timelineGuide,
39
42
  }: ProfileViewWithDataProps): JSX.Element => {
40
43
  const metadata = useGrpcMetadata();
41
44
  const [dashboardItems] = useURLState<string[]>('dashboard_items', {
@@ -44,7 +47,10 @@ export const ProfileViewWithData = ({
44
47
  const [sourceBuildID] = useURLState<string>('source_buildid');
45
48
  const [sourceFilename] = useURLState<string>('source_filename');
46
49
  const [groupBy] = useURLState<string[]>('group_by', {
47
- defaultValue: [FIELD_FUNCTION_NAME],
50
+ defaultValue: [
51
+ isGroupByTimestamp === true ? FIELD_TIMESTAMP : (null as unknown as string),
52
+ FIELD_FUNCTION_NAME,
53
+ ].filter(Boolean),
48
54
  alwaysReturnArray: true,
49
55
  });
50
56
 
@@ -244,7 +250,7 @@ export const ProfileViewWithData = ({
244
250
  onDownloadPProf={() => void downloadPProfClick()}
245
251
  pprofDownloading={pprofDownloading}
246
252
  showVisualizationSelector={showVisualizationSelector}
247
- showTimelineGuide={showTimelineGuide}
253
+ timelineGuide={timelineGuide}
248
254
  />
249
255
  );
250
256
  };
@@ -88,11 +88,6 @@ export const TimelineGuide = ({bounds, width, height, margin, ticks}: Props): JS
88
88
  y1={-height + 20}
89
89
  y2={-height + 20}
90
90
  />
91
- {/* <g transform={`translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`}>
92
- <text fill="currentColor" dy=".71em" y={5} className="text-sm">
93
- Time
94
- </text>
95
- </g> */}
96
91
  </g>
97
92
  </svg>
98
93
  </div>
package/src/index.tsx CHANGED
@@ -25,6 +25,7 @@ export * from './ProfileViewWithData';
25
25
  export * from './utils';
26
26
  export * from './ProfileTypeSelector';
27
27
  export * from './SourceView';
28
+ export * from './ProfileMetricsGraph';
28
29
  export {default as Callgraph} from './Callgraph';
29
30
 
30
31
  export const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES = {