@parca/profile 0.16.236 → 0.16.238

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.238](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.237...@parca/profile@0.16.238) (2023-08-30)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.237](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.236...@parca/profile@0.16.237) (2023-08-30)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## 0.16.236 (2023-08-29)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -51,7 +51,6 @@ const GraphTooltip = ({ children, x, y, contextElement, isFixed = false, virtual
51
51
  options: {
52
52
  tether: false,
53
53
  altAxis: true,
54
- boundary: contextElement ?? undefined,
55
54
  },
56
55
  },
57
56
  {
@@ -60,12 +59,6 @@ const GraphTooltip = ({ children, x, y, contextElement, isFixed = false, virtual
60
59
  offset: [30, 30],
61
60
  },
62
61
  },
63
- {
64
- name: 'flip',
65
- options: {
66
- boundary: contextElement ?? undefined,
67
- },
68
- },
69
62
  ],
70
63
  });
71
64
  const { isShiftDown } = useKeyDown();
@@ -91,6 +84,6 @@ const GraphTooltip = ({ children, x, y, contextElement, isFixed = false, virtual
91
84
  contextElement.removeEventListener('mousemove', onMouseMove);
92
85
  };
93
86
  }, [contextElement, popperProps, isShiftDown, x, y]);
94
- return isFixed ? (_jsx(_Fragment, { children: children })) : (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, children: children }));
87
+ return isFixed ? (_jsx(_Fragment, { children: children })) : (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-10", children: children }));
95
88
  };
96
89
  export default GraphTooltip;
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- import { useRef, useState } from 'react';
14
+ import { Fragment, useRef, useState } from 'react';
15
15
  import * as d3 from 'd3';
16
16
  import { pointer } from 'd3-selection';
17
17
  import throttle from 'lodash.throttle';
@@ -230,11 +230,11 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, onLabe
230
230
  const selected = findSelectedProfile();
231
231
  return (_jsxs(_Fragment, { children: [highlighted != null && hovering && !dragging && pos[0] !== 0 && pos[1] !== 0 && (_jsx("div", { onMouseMove: onMouseMove, onMouseEnter: () => setHovering(true), onMouseLeave: () => setHovering(false), children: _jsx(MetricsTooltip, { x: pos[0] + margin, y: pos[1] + margin, highlighted: highlighted, onLabelClick: onLabelClick, contextElement: graph.current, sampleUnit: sampleUnit, delta: profile !== null ? profile?.query.profType.delta : false }) })), _jsx("div", { ref: graph, onMouseEnter: function () {
232
232
  setHovering(true);
233
- }, onMouseLeave: () => setHovering(false), children: _jsxs("svg", { width: `${width}px`, height: `${height + margin}px`, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseMove: onMouseMove, children: [_jsx("g", { transform: `translate(${margin}, 0)`, children: dragging && (_jsx("g", { className: "zoom-time-rect", children: _jsx("rect", { className: "bar", x: pos[0] - relPos < 0 ? pos[0] : relPos, y: 0, height: height, width: Math.abs(pos[0] - relPos), fill: 'rgba(0, 0, 0, 0.125)' }) })) }), _jsxs("g", { transform: `translate(${margin}, ${margin})`, children: [_jsxs("g", { className: "y axis", textAnchor: "end", fontSize: "10", fill: "none", children: [yScale.ticks(5).map((d, i) => (_jsxs(_Fragment, { children: [_jsxs("g", { className: "tick",
233
+ }, onMouseLeave: () => setHovering(false), children: _jsxs("svg", { width: `${width}px`, height: `${height + margin}px`, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseMove: onMouseMove, children: [_jsx("g", { transform: `translate(${margin}, 0)`, children: dragging && (_jsx("g", { className: "zoom-time-rect", children: _jsx("rect", { className: "bar", x: pos[0] - relPos < 0 ? pos[0] : relPos, y: 0, height: height, width: Math.abs(pos[0] - relPos), fill: 'rgba(0, 0, 0, 0.125)' }) })) }), _jsxs("g", { transform: `translate(${margin}, ${margin})`, children: [_jsxs("g", { className: "y axis", textAnchor: "end", fontSize: "10", fill: "none", children: [yScale.ticks(5).map((d, i) => (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick",
234
234
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
235
- transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsx("text", { fill: "currentColor", x: -9, dy: '0.32em', children: valueFormatter(d, sampleUnit, 1) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: yScale(d), y2: yScale(d) }) }, `grid-${i}`)] }))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: 0, y1: 0, y2: height - margin }), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(to), x2: xScale(to), y1: 0, y2: height - margin })] }), _jsxs("g", { className: "x axis", fill: "none", fontSize: "10", textAnchor: "middle", transform: `translate(0,${height - margin})`, children: [xScale.ticks(5).map((d, i) => (_jsxs(_Fragment, { children: [_jsxs("g", { className: "tick",
235
+ transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsx("text", { fill: "currentColor", x: -9, dy: '0.32em', children: valueFormatter(d, sampleUnit, 1) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: yScale(d), y2: yScale(d) }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: 0, x2: 0, y1: 0, y2: height - margin }), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(to), x2: xScale(to), y1: 0, y2: height - margin })] }), _jsxs("g", { className: "x axis", fill: "none", fontSize: "10", textAnchor: "middle", transform: `translate(0,${height - margin})`, children: [xScale.ticks(5).map((d, i) => (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick",
236
236
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
237
- transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to)) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: 0, y2: 0 })] }), _jsx("g", { className: "lines fill-transparent", children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(i.toString()), strokeWidth: hovering && highlighted != null && i === highlighted.seriesIndex
237
+ transform: `translate(${xScale(d)}, 0)`, children: [_jsx("line", { y2: 6, className: "stroke-gray-300 dark:stroke-gray-500" }), _jsx("text", { fill: "currentColor", dy: ".71em", y: 9, children: formatDate(d, formatForTimespan(from, to)) })] }, `tick-${i}`), _jsx("g", { children: _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(d), x2: xScale(d), y1: 0, y2: -height + margin }) }, `grid-${i}`)] }, `${i.toString()}-${d.toString()}`))), _jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x1: xScale(from), x2: xScale(to), y1: 0, y2: 0 })] }), _jsx("g", { className: "lines fill-transparent", children: series.map((s, i) => (_jsx("g", { className: "line", children: _jsx(MetricsSeries, { data: s, line: l, color: color(i.toString()), strokeWidth: hovering && highlighted != null && i === highlighted.seriesIndex
238
238
  ? lineStrokeHover
239
239
  : lineStroke, xScale: xScale, yScale: yScale }) }, i))) }), hovering && highlighted != null && (_jsx("g", { className: "circle-group", ref: metricPointRef, style: { fill: color(highlighted.seriesIndex.toString()) }, children: _jsx(MetricsCircle, { cx: highlighted.x, cy: highlighted.y }) })), selected != null && (_jsx("g", { className: "circle-group", style: selected?.seriesIndex != null
240
240
  ? { fill: color(selected.seriesIndex.toString()) }
@@ -15,6 +15,7 @@ interface ProfileIcicleGraphProps {
15
15
  navigateTo?: NavigateFunction;
16
16
  loading: boolean;
17
17
  setActionButtons?: (buttons: React.JSX.Element) => void;
18
+ error?: any;
18
19
  }
19
- declare const ProfileIcicleGraph: ({ graph, table, total, filtered, curPath, setNewCurPath, sampleUnit, navigateTo, loading, setActionButtons, }: ProfileIcicleGraphProps) => JSX.Element;
20
+ declare const ProfileIcicleGraph: ({ graph, table, total, filtered, curPath, setNewCurPath, sampleUnit, navigateTo, loading, setActionButtons, error, }: ProfileIcicleGraphProps) => JSX.Element;
20
21
  export default ProfileIcicleGraph;
@@ -50,7 +50,7 @@ const GroupAndSortActionButtons = ({ navigateTo }) => {
50
50
  }, [groupBy, setGroupBy]);
51
51
  return (_jsxs(_Fragment, { children: [_jsx(GroupByDropdown, { groupBy: groupBy, toggleGroupBy: toggleGroupBy }), _jsx(SortBySelect, { compareMode: compareMode, sortBy: storeSortBy, setSortBy: setStoreSortBy })] }));
52
52
  };
53
- const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, table, total, filtered, curPath, setNewCurPath, sampleUnit, navigateTo, loading, setActionButtons, }) {
53
+ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, table, total, filtered, curPath, setNewCurPath, sampleUnit, navigateTo, loading, setActionButtons, error, }) {
54
54
  const compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
55
55
  const { ref, dimensions } = useContainerDimensions();
56
56
  const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState({
@@ -82,6 +82,10 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, table, to
82
82
  }
83
83
  setActionButtons(_jsx("div", { className: "flex w-full justify-end gap-2 pb-2", children: _jsxs("div", { className: "ml-2 flex w-full items-end justify-between gap-2", children: [table !== undefined && _jsx(GroupAndSortActionButtons, { navigateTo: navigateTo }), _jsx("div", { children: _jsx(Button, { color: "neutral", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, variant: "neutral", children: "Reset View" }) })] }) }));
84
84
  }, [navigateTo, table, curPath, setNewCurPath, setActionButtons]);
85
+ if (error != null) {
86
+ console.error('Error: ', error);
87
+ return _jsxs("div", { className: "flex justify-center p-10", children: ["An error occurred: ", error.message] });
88
+ }
85
89
  if (graph === undefined && table === undefined)
86
90
  return _jsx("div", { children: "no data..." });
87
91
  if (total === 0n && !loading)
@@ -35,7 +35,7 @@ interface SourceData {
35
35
  export interface ProfileViewProps {
36
36
  total: bigint;
37
37
  filtered: bigint;
38
- flamegraphData?: FlamegraphData;
38
+ flamegraphData: FlamegraphData;
39
39
  topTableData?: TopTableData;
40
40
  callgraphData?: CallgraphData;
41
41
  sourceData?: SourceData;
@@ -1,5 +1,5 @@
1
1
  import { createElement as _createElement } from "react";
2
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  // Copyright 2022 The Parca Authors
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -119,10 +119,6 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
119
119
  }
120
120
  // eslint-disable-next-line react-hooks/exhaustive-deps
121
121
  }, [graphvizLoaded, callgraphData?.data]);
122
- if (flamegraphData?.error !== null) {
123
- console.error('Error: ', flamegraphData?.error);
124
- return (_jsxs("div", { className: "flex justify-center p-10", children: ["An error occurred: ", flamegraphData?.error.message] }));
125
- }
126
122
  const setNewCurPath = (path) => {
127
123
  if (!arrayEquals(curPath, path)) {
128
124
  setCurPath(path);
@@ -131,10 +127,10 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
131
127
  const getDashboardItemByType = ({ type, isHalfScreen, setActionButtons, }) => {
132
128
  switch (type) {
133
129
  case 'icicle': {
134
- return flamegraphData?.table !== undefined || flamegraphData.data !== undefined ? (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
130
+ return (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
135
131
  id: 'icicleGraph',
136
132
  onRender: perf?.onRender,
137
- }, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, table: flamegraphData.table, graph: flamegraphData.data, total: total, filtered: filtered, sampleUnit: sampleUnit, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) })) : (_jsx(_Fragment, { children: " " }));
133
+ }, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, table: flamegraphData?.table, graph: flamegraphData?.data, total: total, filtered: filtered, sampleUnit: sampleUnit, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons, error: flamegraphData.error }) }));
138
134
  }
139
135
  case 'callgraph': {
140
136
  return callgraphData?.data !== undefined &&
@@ -7,10 +7,10 @@ interface RendererProps {
7
7
  }
8
8
  type Renderer = ({ rows, stylesheet, useInlineStyles }: RendererProps) => JSX.Element;
9
9
  interface HighlighterProps {
10
+ file: string;
10
11
  content: string;
11
- language?: string;
12
12
  renderer?: Renderer;
13
13
  }
14
14
  export declare const profileAwareRenderer: (cumulative: Vector | null, flat: Vector | null, total: bigint, filtered: bigint) => Renderer;
15
- export declare const Highlighter: ({ content, language, renderer }: HighlighterProps) => JSX.Element;
15
+ export declare const Highlighter: ({ file, content, renderer }: HighlighterProps) => JSX.Element;
16
16
  export {};
@@ -11,7 +11,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- import { useId } from 'react';
14
+ import { useId, useMemo } from 'react';
15
15
  import cx from 'classnames';
16
16
  import { scaleLinear } from 'd3-scale';
17
17
  import SyntaxHighlighter, { createElement } from 'react-syntax-highlighter';
@@ -21,6 +21,7 @@ import { useURLState } from '@parca/components';
21
21
  import { selectDarkMode, useAppSelector } from '@parca/store';
22
22
  import { useProfileViewContext } from '../ProfileView/ProfileViewContext';
23
23
  import { LineNo } from './LineNo';
24
+ import { langaugeFromFile } from './lang-detector';
24
25
  // cannot make this a function on the number as we need the classes to be static for tailwind
25
26
  const charsToWidthMap = {
26
27
  1: 'w-3',
@@ -63,7 +64,7 @@ export const profileAwareRenderer = (cumulative, flat, total, filtered) => {
63
64
  const lineNumber = node.children[0].children[0].value;
64
65
  const isCurrentLine = sourceLine === lineNumber.toString();
65
66
  node.children = node.children.slice(1);
66
- return (_jsxs("div", { className: "flex gap-1", children: [_jsx("div", { className: cx('shrink-0 overflow-hidden border-r border-r-gray-200 text-right dark:border-r-gray-700', lineNumberWidth), children: _jsx(LineNo, { value: lineNumber, isCurrent: isCurrentLine, setCurrentLine: () => setSourceLine(lineNumber.toString()) }) }), _jsx(LineProfileMetadata, { value: cumulative?.get(i) ?? 0n, total: total, filtered: filtered }), _jsx(LineProfileMetadata, { value: flat?.get(i) ?? 0n, total: total, filtered: filtered }), _jsx("div", { className: cx('w-11/12 flex-grow-0 border-l border-gray-200 pl-1 dark:border-gray-700', {
67
+ return (_jsxs("div", { className: "flex gap-1", children: [_jsx("div", { className: cx('shrink-0 overflow-hidden border-r border-r-gray-200 text-right dark:border-r-gray-700', lineNumberWidth), children: _jsx(LineNo, { value: lineNumber, isCurrent: isCurrentLine, setCurrentLine: () => setSourceLine(lineNumber.toString()) }) }), _jsx(LineProfileMetadata, { value: cumulative?.get(i) ?? 0n, total: total, filtered: filtered }), _jsx(LineProfileMetadata, { value: flat?.get(i) ?? 0n, total: total, filtered: filtered }), _jsx("div", { className: cx('w-full flex-grow-0 border-l border-gray-200 pl-1 dark:border-gray-700', {
67
68
  'bg-yellow-200 dark:bg-yellow-700': isCurrentLine,
68
69
  }), children: createElement({
69
70
  key: `source-line-${i}`,
@@ -74,7 +75,12 @@ export const profileAwareRenderer = (cumulative, flat, total, filtered) => {
74
75
  }) }));
75
76
  };
76
77
  };
77
- export const Highlighter = ({ content, language, renderer }) => {
78
+ export const Highlighter = ({ file, content, renderer }) => {
78
79
  const isDarkMode = useAppSelector(selectDarkMode);
79
- return (_jsxs("div", { className: "relative", children: [_jsxs("div", { className: "flex gap-2 text-xs", children: [_jsx("div", { className: cx('text-right', charsToWidth(content.split('\n').length.toString().length)), children: "Line" }), _jsxs("div", { className: "flex gap-3", children: [_jsx("div", { children: "Cumulative" }), _jsx("div", { children: "Flat" }), _jsx("div", { children: "Source" })] })] }), _jsx("div", { className: "text-xs", children: _jsx(SyntaxHighlighter, { language: language, style: isDarkMode ? atomOneDark : atomOneLight, showLineNumbers: true, renderer: renderer, customStyle: { padding: 0, height: '80vh' }, children: content }) })] }));
80
+ const language = useMemo(() => langaugeFromFile(file), [file]);
81
+ return (_jsxs("div", { className: "relative", children: [_jsxs("div", { className: "flex gap-2 text-xs", children: [_jsx("div", { className: cx('text-right', charsToWidth(content
82
+ .split(
83
+ // prettier-ignore
84
+ '\n')
85
+ .length.toString().length)), children: "Line" }), _jsxs("div", { className: "flex gap-3", children: [_jsx("div", { children: "Cumulative" }), _jsx("div", { children: "Flat" }), _jsx("div", { children: "Source" })] })] }), _jsx("div", { className: "text-xs", children: _jsx(SyntaxHighlighter, { language: language, style: isDarkMode ? atomOneDark : atomOneLight, showLineNumbers: true, renderer: renderer, customStyle: { padding: 0, height: '80vh' }, children: content }) })] }));
80
86
  };
@@ -32,6 +32,6 @@ export const SourceView = React.memo(function SourceView({ data, loading, total,
32
32
  const table = tableFromIPC(data.record);
33
33
  const cumulative = table.getChild('cumulative');
34
34
  const flat = table.getChild('flat');
35
- return (_jsx(Highlighter, { content: data.source, renderer: profileAwareRenderer(cumulative, flat, total, filtered) }));
35
+ return (_jsx(Highlighter, { file: sourceFileName, content: data.source, renderer: profileAwareRenderer(cumulative, flat, total, filtered) }));
36
36
  });
37
37
  export default SourceView;