@parca/profile 0.16.498 → 0.16.500
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 +8 -0
- package/dist/MetricsGraph/MetricsTooltip/index.d.ts +2 -1
- package/dist/MetricsGraph/MetricsTooltip/index.d.ts.map +1 -1
- package/dist/MetricsGraph/MetricsTooltip/index.js +2 -2
- package/dist/MetricsGraph/UtilizationMetrics/{AreaChart.d.ts → Throughput.d.ts} +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/Throughput.d.ts.map +1 -0
- package/dist/MetricsGraph/UtilizationMetrics/{AreaChart.js → Throughput.js} +37 -61
- package/dist/ProfileSelector/MetricsGraphSection.js +1 -1
- package/package.json +2 -2
- package/src/MetricsGraph/MetricsTooltip/index.tsx +6 -1
- package/src/MetricsGraph/UtilizationMetrics/{AreaChart.tsx → Throughput.tsx} +27 -40
- package/src/ProfileSelector/MetricsGraphSection.tsx +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/AreaChart.d.ts.map +0 -1
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.500](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.499...@parca/profile@0.16.500) (2025-04-28)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.16.499](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.498...@parca/profile@0.16.499) (2025-04-24)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.498](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.497...@parca/profile@0.16.498) (2025-04-24)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -7,7 +7,8 @@ interface Props {
|
|
|
7
7
|
sampleUnit: string;
|
|
8
8
|
delta: boolean;
|
|
9
9
|
utilizationMetrics?: boolean;
|
|
10
|
+
valuePrefix?: string;
|
|
10
11
|
}
|
|
11
|
-
declare const MetricsTooltip: ({ x, y, highlighted, contextElement, sampleUnit, delta, utilizationMetrics, }: Props) => JSX.Element;
|
|
12
|
+
declare const MetricsTooltip: ({ x, y, highlighted, contextElement, sampleUnit, delta, utilizationMetrics, valuePrefix, }: Props) => JSX.Element;
|
|
12
13
|
export default MetricsTooltip;
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/MetricsTooltip/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAAC,iBAAiB,EAAC,MAAM,KAAK,CAAC;AAEtC,UAAU,KAAK;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,iBAAiB,CAAC;IAC/B,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/MetricsTooltip/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAAC,iBAAiB,EAAC,MAAM,KAAK,CAAC;AAEtC,UAAU,KAAK;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,iBAAiB,CAAC;IAC/B,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8BD,QAAA,MAAM,cAAc,+FASjB,KAAK,KAAG,GAAG,CAAC,OAuMd,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -42,7 +42,7 @@ function generateGetBoundingClientRect(contextElement, x = 0, y = 0) {
|
|
|
42
42
|
bottom: domRect.y + y,
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta, utilizationMetrics = false, }) => {
|
|
45
|
+
const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta, utilizationMetrics = false, valuePrefix, }) => {
|
|
46
46
|
const { timezone } = useParcaContext();
|
|
47
47
|
const [popperElement, setPopperElement] = useState(null);
|
|
48
48
|
const { styles, attributes, ...popperProps } = usePopper(virtualElement, popperElement, {
|
|
@@ -91,7 +91,7 @@ const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta,
|
|
|
91
91
|
}, [x, y, contextElement, update]);
|
|
92
92
|
const nameLabel = highlighted?.labels.find(e => e.name === '__name__');
|
|
93
93
|
const highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
|
|
94
|
-
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-50", children: _jsx("div", { className: "flex max-w-lg", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "rounded-lg border-gray-300 bg-gray-50 p-3 opacity-90 shadow-lg dark:border-gray-500 dark:bg-gray-900", style: { borderWidth: 1 }, children: _jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [delta ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4 pr-3", children: "Per\u00A0Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit === 'nanoseconds' ? 'CPU Cores' : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.value, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [
|
|
94
|
+
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-50", children: _jsx("div", { className: "flex max-w-lg", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "rounded-lg border-gray-300 bg-gray-50 p-3 opacity-90 shadow-lg dark:border-gray-500 dark:bg-gray-900", style: { borderWidth: 1 }, children: _jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [delta ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4 pr-3", children: "Per\u00A0Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit === 'nanoseconds' ? 'CPU Cores' : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.value, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsxs("td", { className: "w-1/4", children: [valuePrefix ?? '', "Value"] }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit, 5) })] })), highlighted.duration > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.duration, 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(highlighted.timestamp, timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: utilizationMetrics ? (_jsxs(_Fragment, { children: [Object.keys(attributesResourceMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Resource Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesResourceMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesResourceMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesResourceMap[name]}` }) }, name))) }), Object.keys(attributesMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesMap[name]}` }) }, name))) })] })) : (_jsx(_Fragment, { children: highlighted.labels
|
|
95
95
|
.filter((label) => label.name !== '__name__')
|
|
96
96
|
.map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}` }) }, label.name))) })) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }) }) }) }) }));
|
|
97
97
|
};
|
|
@@ -21,4 +21,4 @@ type Props = CommonProps & {
|
|
|
21
21
|
};
|
|
22
22
|
declare const AreaChart: ({ transmitData, receiveData, addLabelMatcher, setTimeRange, utilizationMetricsLoading, name, humanReadableName, from, to, }: Props) => JSX.Element;
|
|
23
23
|
export default AreaChart;
|
|
24
|
-
//# sourceMappingURL=
|
|
24
|
+
//# sourceMappingURL=Throughput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Throughput.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/Throughput.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,aAAa,EAAqD,MAAM,mBAAmB,CAAC;AAIpG,OAAO,EAAC,KAAK,kBAAkB,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAiB9E,UAAU,WAAW;IACnB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAQD,KAAK,KAAK,GAAG,WAAW,GAAG;IACzB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,CAAC;AAmeF,QAAA,MAAM,SAAS,gIAUZ,KAAK,KAAG,GAAG,CAAC,OAiCd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -48,23 +48,7 @@ function transformToSeries(data, isReceive = false) {
|
|
|
48
48
|
values: series.values.sort((a, b) => a[0] - b[0]),
|
|
49
49
|
}));
|
|
50
50
|
}
|
|
51
|
-
const
|
|
52
|
-
switch (name) {
|
|
53
|
-
case 'gpu_utilization_percent':
|
|
54
|
-
return 'percent';
|
|
55
|
-
case 'gpu_memory_utilization_percent':
|
|
56
|
-
return 'percent';
|
|
57
|
-
case 'gpu_power_watt':
|
|
58
|
-
return 'watts';
|
|
59
|
-
case 'gpu_pcie_throughput_transmit_bytes':
|
|
60
|
-
return 'bytes_per_second';
|
|
61
|
-
case 'gpu_pcie_throughput_receive_bytes':
|
|
62
|
-
return 'bytes_per_second';
|
|
63
|
-
default:
|
|
64
|
-
return 'percent';
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
const RawAreaChart = ({ transmitData, receiveData, addLabelMatcher, setTimeRange, width, height, margin, name, humanReadableName, from, to, }) => {
|
|
51
|
+
const RawAreaChart = ({ transmitData, receiveData, addLabelMatcher, setTimeRange, width, height, margin, humanReadableName, from, to, }) => {
|
|
68
52
|
const { timezone } = useParcaContext();
|
|
69
53
|
const graph = useRef(null);
|
|
70
54
|
const [dragging, setDragging] = useState(false);
|
|
@@ -136,21 +120,15 @@ const RawAreaChart = ({ transmitData, receiveData, addLabelMatcher, setTimeRange
|
|
|
136
120
|
event: e,
|
|
137
121
|
});
|
|
138
122
|
}, [show]);
|
|
123
|
+
const color = d3.scaleOrdinal(d3.schemeCategory10);
|
|
139
124
|
const getSeriesColor = (series) => {
|
|
140
|
-
return series.
|
|
125
|
+
return color(series.labelset);
|
|
141
126
|
};
|
|
142
|
-
// Create
|
|
143
|
-
const
|
|
144
|
-
.
|
|
145
|
-
.x(d => xScale(d[0]))
|
|
146
|
-
.y0(yScale(0)) // Start from zero line
|
|
147
|
-
.y1(d => yScale(d[1])); // Top of the area (data point)
|
|
148
|
-
// Create area generator for receive (below zero)
|
|
149
|
-
const receiveArea = d3
|
|
150
|
-
.area()
|
|
127
|
+
// Create line generator for both transmit and receive
|
|
128
|
+
const lineGenerator = d3
|
|
129
|
+
.line()
|
|
151
130
|
.x(d => xScale(d[0]))
|
|
152
|
-
.
|
|
153
|
-
.y1(d => yScale(d[1])); // Bottom of the area (negative data point)
|
|
131
|
+
.y(d => yScale(d[1]));
|
|
154
132
|
const highlighted = useMemo(() => {
|
|
155
133
|
if (series.length === 0) {
|
|
156
134
|
return null;
|
|
@@ -228,47 +206,45 @@ const RawAreaChart = ({ transmitData, receiveData, addLabelMatcher, setTimeRange
|
|
|
228
206
|
};
|
|
229
207
|
return (_jsxs(_Fragment, { children: [_jsx(MetricsContextMenu, { onAddLabelMatcher: addLabelMatcher, menuId: MENU_ID, highlighted: highlighted, trackVisibility: trackVisibility, utilizationMetrics: true }), highlighted != null && hovering && !dragging && pos[0] !== 0 && pos[1] !== 0 && (_jsx("div", { onMouseMove: onMouseMove, onMouseEnter: () => setHovering(true), onMouseLeave: () => setHovering(false), children: !isContextMenuOpen && (_jsx(MetricsTooltip, { x: pos[0] + margin, y: pos[1] + margin, highlighted: {
|
|
230
208
|
...highlighted,
|
|
231
|
-
valuePerSecond: Math.abs(highlighted.valuePerSecond),
|
|
232
|
-
}, contextElement: graph.current, sampleUnit:
|
|
209
|
+
valuePerSecond: Math.abs(highlighted.valuePerSecond),
|
|
210
|
+
}, contextElement: graph.current, sampleUnit: 'bytes_per_second', delta: false, utilizationMetrics: true, valuePrefix: highlighted.seriesIndex >= transmitData.length ? 'Receive ' : 'Transmit ' })) })), _jsx("div", { ref: graph, onMouseEnter: () => setHovering(true), onMouseLeave: () => setHovering(false), onContextMenu: displayMenu, 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 * 1.5}, ${margin / 1.5})`, children: [_jsxs("g", { className: "y axis", textAnchor: "end", fontSize: "10", fill: "none", children: [yScale.ticks(6).map((d, i, allTicks) => {
|
|
233
211
|
let decimals = 2;
|
|
234
212
|
const intervalBetweenTicks = allTicks[1] - allTicks[0];
|
|
235
213
|
if (intervalBetweenTicks < 1) {
|
|
236
214
|
const precision = getPrecision(intervalBetweenTicks);
|
|
237
215
|
decimals = precision;
|
|
238
216
|
}
|
|
239
|
-
return (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick", transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsxs("text", { fill: "currentColor", x: -9, dy: '0.32em', children: [d < 0 ? '-' : '', valueFormatter(Math.abs(d),
|
|
217
|
+
return (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick", transform: `translate(0, ${yScale(d)})`, children: [_jsx("line", { className: "stroke-gray-300 dark:stroke-gray-500", x2: -6 }), _jsxs("text", { fill: "currentColor", x: -9, dy: '0.32em', children: [d < 0 ? '-' : '', valueFormatter(Math.abs(d), 'bytes_per_second', decimals)] })] }, `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()}`));
|
|
240
218
|
}), _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 }), _jsx("g", { transform: `translate(${-margin}, ${(height - margin) / 2}) rotate(270)`, children: _jsx("text", { fill: "currentColor", dy: "-0.7em", className: "text-sm capitalize", textAnchor: "middle", children: humanReadableName }) })] }), _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",
|
|
241
219
|
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
242
|
-
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), timezone) })] }, `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: 0, x2: graphWidth, y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }),
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
220
|
+
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), timezone) })] }, `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: 0, x2: graphWidth, y1: 0, y2: 0 }), _jsx("g", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _jsxs("g", { className: "areas", children: [_jsx("line", { x1: xScale(from), x2: xScale(to), y1: yScale(0), y2: yScale(0), stroke: "#64748b", strokeDasharray: "4 2", strokeWidth: 1, opacity: 0.7 }), series.map((s, i) => {
|
|
221
|
+
let isSelected = false;
|
|
222
|
+
if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
|
|
223
|
+
isSelected = parsedSelectedSeries.every(m => {
|
|
224
|
+
for (let i = 0; i < s.metric.length; i++) {
|
|
225
|
+
if (s.metric[i].name === m.key && s.metric[i].value === m.value) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
249
228
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
} }) }, i));
|
|
271
|
-
}) })] })] }) })] }));
|
|
229
|
+
return false;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const seriesColor = getSeriesColor(s);
|
|
233
|
+
const strokeOpacity = isSelected ? 1 : 0.8;
|
|
234
|
+
return (_jsx("g", { className: "line cursor-pointer", children: _jsx("path", { d: lineGenerator(s.values) ?? '', fill: "none", stroke: seriesColor, strokeWidth: isSelected
|
|
235
|
+
? lineStrokeSelected
|
|
236
|
+
: hovering && highlighted != null && i === highlighted.seriesIndex
|
|
237
|
+
? lineStrokeHover
|
|
238
|
+
: lineStroke, strokeOpacity: strokeOpacity, onClick: () => {
|
|
239
|
+
if (highlighted != null) {
|
|
240
|
+
setSelectedSeries(JSON.stringify(highlighted.labels.map(l => ({
|
|
241
|
+
key: l.name,
|
|
242
|
+
value: l.value,
|
|
243
|
+
}))));
|
|
244
|
+
setSelectedTimeframe(undefined);
|
|
245
|
+
}
|
|
246
|
+
} }) }, i));
|
|
247
|
+
})] })] })] }) })] }));
|
|
272
248
|
};
|
|
273
249
|
const AreaChart = ({ transmitData, receiveData, addLabelMatcher, setTimeRange, utilizationMetricsLoading, name, humanReadableName, from, to, }) => {
|
|
274
250
|
const { isDarkMode } = useParcaContext();
|
|
@@ -15,7 +15,7 @@ import cx from 'classnames';
|
|
|
15
15
|
import { Query } from '@parca/parser';
|
|
16
16
|
import { MergedProfileSelection } from '..';
|
|
17
17
|
import UtilizationMetricsGraph from '../MetricsGraph/UtilizationMetrics';
|
|
18
|
-
import AreaChart from '../MetricsGraph/UtilizationMetrics/
|
|
18
|
+
import AreaChart from '../MetricsGraph/UtilizationMetrics/Throughput';
|
|
19
19
|
import ProfileMetricsGraph, { ProfileMetricsEmptyState } from '../ProfileMetricsGraph';
|
|
20
20
|
export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGraphButton, heightStyle, querySelection, profileSelection, comparing, sumBy, defaultSumByLoading, queryClient, queryExpressionString, setTimeRangeSelection, selectQuery, selectProfile, query, setNewQueryExpression, utilizationMetrics, utilizationMetricsLoading, }) {
|
|
21
21
|
const handleTimeRangeChange = (range) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.500",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@headlessui/react": "^1.7.19",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"access": "public",
|
|
78
78
|
"registry": "https://registry.npmjs.org/"
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "4fe4798ae9359ce2ca83f9ff5c83ef9868b9ef45"
|
|
81
81
|
}
|
|
@@ -31,6 +31,7 @@ interface Props {
|
|
|
31
31
|
sampleUnit: string;
|
|
32
32
|
delta: boolean;
|
|
33
33
|
utilizationMetrics?: boolean;
|
|
34
|
+
valuePrefix?: string;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const virtualElement: VirtualElement = {
|
|
@@ -69,6 +70,7 @@ const MetricsTooltip = ({
|
|
|
69
70
|
sampleUnit,
|
|
70
71
|
delta,
|
|
71
72
|
utilizationMetrics = false,
|
|
73
|
+
valuePrefix,
|
|
72
74
|
}: Props): JSX.Element => {
|
|
73
75
|
const {timezone} = useParcaContext();
|
|
74
76
|
|
|
@@ -164,7 +166,10 @@ const MetricsTooltip = ({
|
|
|
164
166
|
</>
|
|
165
167
|
) : (
|
|
166
168
|
<tr>
|
|
167
|
-
<td className="w-1/4">
|
|
169
|
+
<td className="w-1/4">
|
|
170
|
+
{valuePrefix ?? ''}
|
|
171
|
+
Value
|
|
172
|
+
</td>
|
|
168
173
|
<td className="w-3/4">
|
|
169
174
|
{valueFormatter(highlighted.valuePerSecond, sampleUnit, 5)}
|
|
170
175
|
</td>
|
|
@@ -100,23 +100,6 @@ function transformToSeries(data: MetricSeries[], isReceive = false): NetworkSeri
|
|
|
100
100
|
}));
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
const getYAxisUnit = (name: string): string => {
|
|
104
|
-
switch (name) {
|
|
105
|
-
case 'gpu_utilization_percent':
|
|
106
|
-
return 'percent';
|
|
107
|
-
case 'gpu_memory_utilization_percent':
|
|
108
|
-
return 'percent';
|
|
109
|
-
case 'gpu_power_watt':
|
|
110
|
-
return 'watts';
|
|
111
|
-
case 'gpu_pcie_throughput_transmit_bytes':
|
|
112
|
-
return 'bytes_per_second';
|
|
113
|
-
case 'gpu_pcie_throughput_receive_bytes':
|
|
114
|
-
return 'bytes_per_second';
|
|
115
|
-
default:
|
|
116
|
-
return 'percent';
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
103
|
const RawAreaChart = ({
|
|
121
104
|
transmitData,
|
|
122
105
|
receiveData,
|
|
@@ -125,7 +108,6 @@ const RawAreaChart = ({
|
|
|
125
108
|
width,
|
|
126
109
|
height,
|
|
127
110
|
margin,
|
|
128
|
-
name,
|
|
129
111
|
humanReadableName,
|
|
130
112
|
from,
|
|
131
113
|
to,
|
|
@@ -225,23 +207,17 @@ const RawAreaChart = ({
|
|
|
225
207
|
[show]
|
|
226
208
|
);
|
|
227
209
|
|
|
210
|
+
const color = d3.scaleOrdinal(d3.schemeCategory10);
|
|
211
|
+
|
|
228
212
|
const getSeriesColor = (series: NetworkSeries): string => {
|
|
229
|
-
return series.
|
|
213
|
+
return color(series.labelset);
|
|
230
214
|
};
|
|
231
215
|
|
|
232
|
-
// Create
|
|
233
|
-
const
|
|
234
|
-
.
|
|
216
|
+
// Create line generator for both transmit and receive
|
|
217
|
+
const lineGenerator = d3
|
|
218
|
+
.line<number[]>()
|
|
235
219
|
.x(d => xScale(d[0]))
|
|
236
|
-
.
|
|
237
|
-
.y1(d => yScale(d[1])); // Top of the area (data point)
|
|
238
|
-
|
|
239
|
-
// Create area generator for receive (below zero)
|
|
240
|
-
const receiveArea = d3
|
|
241
|
-
.area<number[]>()
|
|
242
|
-
.x(d => xScale(d[0]))
|
|
243
|
-
.y0(yScale(0)) // Start from zero line
|
|
244
|
-
.y1(d => yScale(d[1])); // Bottom of the area (negative data point)
|
|
220
|
+
.y(d => yScale(d[1]));
|
|
245
221
|
|
|
246
222
|
const highlighted = useMemo(() => {
|
|
247
223
|
if (series.length === 0) {
|
|
@@ -360,12 +336,15 @@ const RawAreaChart = ({
|
|
|
360
336
|
y={pos[1] + margin}
|
|
361
337
|
highlighted={{
|
|
362
338
|
...highlighted,
|
|
363
|
-
valuePerSecond: Math.abs(highlighted.valuePerSecond),
|
|
339
|
+
valuePerSecond: Math.abs(highlighted.valuePerSecond),
|
|
364
340
|
}}
|
|
365
341
|
contextElement={graph.current}
|
|
366
|
-
sampleUnit={
|
|
342
|
+
sampleUnit={'bytes_per_second'}
|
|
367
343
|
delta={false}
|
|
368
344
|
utilizationMetrics={true}
|
|
345
|
+
valuePrefix={
|
|
346
|
+
highlighted.seriesIndex >= transmitData.length ? 'Receive ' : 'Transmit '
|
|
347
|
+
}
|
|
369
348
|
/>
|
|
370
349
|
)}
|
|
371
350
|
</div>
|
|
@@ -414,7 +393,7 @@ const RawAreaChart = ({
|
|
|
414
393
|
<line className="stroke-gray-300 dark:stroke-gray-500" x2={-6} />
|
|
415
394
|
<text fill="currentColor" x={-9} dy={'0.32em'}>
|
|
416
395
|
{d < 0 ? '-' : ''}
|
|
417
|
-
{valueFormatter(Math.abs(d),
|
|
396
|
+
{valueFormatter(Math.abs(d), 'bytes_per_second', decimals)}
|
|
418
397
|
</text>
|
|
419
398
|
</g>
|
|
420
399
|
<g key={`grid-${i}`}>
|
|
@@ -499,6 +478,17 @@ const RawAreaChart = ({
|
|
|
499
478
|
</g>
|
|
500
479
|
</g>
|
|
501
480
|
<g className="areas">
|
|
481
|
+
{/* Draw baseline at y=0 */}
|
|
482
|
+
<line
|
|
483
|
+
x1={xScale(from)}
|
|
484
|
+
x2={xScale(to)}
|
|
485
|
+
y1={yScale(0)}
|
|
486
|
+
y2={yScale(0)}
|
|
487
|
+
stroke="#64748b"
|
|
488
|
+
strokeDasharray="4 2"
|
|
489
|
+
strokeWidth={1}
|
|
490
|
+
opacity={0.7}
|
|
491
|
+
/>
|
|
502
492
|
{series.map((s, i) => {
|
|
503
493
|
let isSelected = false;
|
|
504
494
|
if (parsedSelectedSeries != null && parsedSelectedSeries.length > 0) {
|
|
@@ -513,16 +503,13 @@ const RawAreaChart = ({
|
|
|
513
503
|
}
|
|
514
504
|
|
|
515
505
|
const seriesColor = getSeriesColor(s);
|
|
516
|
-
const fillOpacity = isSelected ? 0.4 : 0.2;
|
|
517
506
|
const strokeOpacity = isSelected ? 1 : 0.8;
|
|
518
|
-
const areaGenerator = s.isReceive === true ? receiveArea : transmitArea;
|
|
519
507
|
|
|
520
508
|
return (
|
|
521
|
-
<g key={i} className="
|
|
509
|
+
<g key={i} className="line cursor-pointer">
|
|
522
510
|
<path
|
|
523
|
-
d={
|
|
524
|
-
fill=
|
|
525
|
-
fillOpacity={fillOpacity}
|
|
511
|
+
d={lineGenerator(s.values) ?? ''}
|
|
512
|
+
fill="none"
|
|
526
513
|
stroke={seriesColor}
|
|
527
514
|
strokeWidth={
|
|
528
515
|
isSelected
|
|
@@ -19,7 +19,7 @@ import {Query} from '@parca/parser';
|
|
|
19
19
|
|
|
20
20
|
import {MergedProfileSelection, ProfileSelection} from '..';
|
|
21
21
|
import UtilizationMetricsGraph from '../MetricsGraph/UtilizationMetrics';
|
|
22
|
-
import AreaChart from '../MetricsGraph/UtilizationMetrics/
|
|
22
|
+
import AreaChart from '../MetricsGraph/UtilizationMetrics/Throughput';
|
|
23
23
|
import ProfileMetricsGraph, {ProfileMetricsEmptyState} from '../ProfileMetricsGraph';
|
|
24
24
|
import {QuerySelection, type UtilizationMetrics as UtilizationMetricsType} from './index';
|
|
25
25
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AreaChart.d.ts","sourceRoot":"","sources":["../../../src/MetricsGraph/UtilizationMetrics/AreaChart.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAC,aAAa,EAAqD,MAAM,mBAAmB,CAAC;AAIpG,OAAO,EAAC,KAAK,kBAAkB,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAiB9E,UAAU,WAAW;IACnB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAQD,KAAK,KAAK,GAAG,WAAW,GAAG;IACzB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,CAAC;AAgfF,QAAA,MAAM,SAAS,gIAUZ,KAAK,KAAG,GAAG,CAAC,OAiCd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|