@parca/profile 0.16.341 → 0.16.342

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,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.342](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.341...@parca/profile@0.16.342) (2024-02-14)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
6
10
  ## [0.16.341](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.340...@parca/profile@0.16.341) (2024-02-13)
7
11
 
8
12
  **Note:** Version bump only for package @parca/profile
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  // Copyright 2022 The Parca Authors
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ const MetricsTooltip = ({ x, y, highlighted, contextElement, sampleUnit, delta,
73
73
  }, [x, y, contextElement, update]);
74
74
  const nameLabel = highlighted?.labels.find(e => e.name === '__name__');
75
75
  const highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
76
- return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-10", children: _jsx("div", { className: "flex max-w-md", 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: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.valuePerSecond, sampleUnit, 5) })] }), delta && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(highlighted.value, sampleUnit, 2) })] })), 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, timeFormat) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: highlighted.labels
76
+ return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, className: "z-10", children: _jsx("div", { className: "flex max-w-md", 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", children: "Per Second" }), _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: [_jsx("td", { className: "w-1/4", children: "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, timeFormat) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: highlighted.labels
77
77
  .filter((label) => label.name !== '__name__')
78
78
  .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.value}` }) }, 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." })] })] }) }) }) }) }) }));
79
79
  };
@@ -241,9 +241,11 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLab
241
241
  };
242
242
  const isDeltaType = profile !== null ? profile?.query.profType.delta : false;
243
243
  let yAxisLabel = sampleUnit;
244
+ let yAxisUnit = sampleUnit;
244
245
  if (isDeltaType) {
245
- if (profile?.query.profType.periodType === 'cpu' && sampleUnit === 'count') {
246
+ if (sampleUnit === 'nanoseconds') {
246
247
  yAxisLabel = 'CPU Cores';
248
+ yAxisUnit = '';
247
249
  }
248
250
  if (sampleUnit === 'bytes') {
249
251
  yAxisLabel = 'Bytes per Second';
@@ -260,7 +262,7 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLab
260
262
  }
261
263
  return (_jsxs(Fragment, { children: [_jsxs("g", { className: "tick",
262
264
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
263
- 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, 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()}`));
265
+ 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, yAxisUnit, 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()}`));
264
266
  }), _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: yAxisLabel }) })] }), _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",
265
267
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
266
268
  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", { transform: `translate(${(width - 2.5 * margin) / 2}, ${margin / 2})`, children: _jsx("text", { fill: "currentColor", dy: ".71em", y: 5, className: "text-sm", children: "Time" }) })] }), _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
@@ -91,7 +91,14 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to,
91
91
  const handleSampleClick = (timestamp, _value, labels) => {
92
92
  onPointClick(timestamp, labels, queryExpression);
93
93
  };
94
- return (_jsx(AnimatePresence, { children: _jsx(motion.div, { className: "h-full w-full", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: _jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: handleSampleClick, addLabelMatcher: addLabelMatcher, sampleUnit: Query.parse(queryExpression).profileType().sampleUnit, height: height, width: width, margin: margin }) }, "metrics-graph-loaded") }));
94
+ let sampleUnit = '';
95
+ if (series.every((val, i, arr) => val?.sampleType?.unit === arr[0]?.sampleType?.unit)) {
96
+ sampleUnit = series[0]?.sampleType?.unit ?? '';
97
+ }
98
+ if (sampleUnit === '') {
99
+ sampleUnit = Query.parse(queryExpression).profileType().sampleUnit;
100
+ }
101
+ return (_jsx(AnimatePresence, { children: _jsx(motion.div, { className: "h-full w-full", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: _jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: handleSampleClick, addLabelMatcher: addLabelMatcher, sampleUnit: sampleUnit, height: height, width: width, margin: margin }) }, "metrics-graph-loaded") }));
95
102
  }
96
103
  return _jsx(ProfileMetricsEmptyState, { message: "No data found. Try a different query." });
97
104
  };
@@ -87,7 +87,18 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
87
87
  sourceResponse,
88
88
  perf,
89
89
  ]);
90
- const sampleUnit = profileSource.ProfileType().sampleUnit;
90
+ // Default to the unit of the selected profile type. This is a heuristic, and
91
+ // only a fallback, the unit should be returned by the backend.
92
+ let sampleUnit = profileSource.ProfileType().sampleUnit;
93
+ if (flamegraphResponse?.report.oneofKind === 'flamegraphArrow') {
94
+ sampleUnit = flamegraphResponse.report.flamegraphArrow.unit;
95
+ }
96
+ if (tableResponse?.report.oneofKind === 'tableArrow') {
97
+ sampleUnit = tableResponse.report.tableArrow.unit;
98
+ }
99
+ if (sourceResponse?.report.oneofKind === 'source') {
100
+ sampleUnit = sourceResponse.report.source.unit;
101
+ }
91
102
  const downloadPProfClick = async () => {
92
103
  if (profileSource == null || queryClient == null) {
93
104
  return;
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.341",
3
+ "version": "0.16.342",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
- "@parca/client": "^0.16.102",
7
- "@parca/components": "^0.16.251",
6
+ "@parca/client": "^0.16.103",
7
+ "@parca/components": "^0.16.252",
8
8
  "@parca/dynamicsize": "^0.16.60",
9
- "@parca/hooks": "^0.0.40",
9
+ "@parca/hooks": "^0.0.41",
10
10
  "@parca/parser": "^0.16.68",
11
- "@parca/store": "^0.16.128",
12
- "@parca/utilities": "^0.0.56",
11
+ "@parca/store": "^0.16.129",
12
+ "@parca/utilities": "^0.0.57",
13
13
  "@tanstack/react-query": "^4.0.5",
14
14
  "@types/react-beautiful-dnd": "^13.1.3",
15
15
  "apache-arrow": "^12.0.0",
@@ -51,5 +51,5 @@
51
51
  "access": "public",
52
52
  "registry": "https://registry.npmjs.org/"
53
53
  },
54
- "gitHead": "1e56ee8a3d821ac02819b9264f55464787d6e667"
54
+ "gitHead": "64e853a94dc382feae3481f3f64efa47e8f5709c"
55
55
  }
@@ -117,17 +117,30 @@ const MetricsTooltip = ({
117
117
  <span className="my-2 block text-gray-700 dark:text-gray-300">
118
118
  <table className="table-auto">
119
119
  <tbody>
120
- <tr>
121
- <td className="w-1/4">Value</td>
122
- <td className="w-3/4">
123
- {valueFormatter(highlighted.valuePerSecond, sampleUnit, 5)}
124
- </td>
125
- </tr>
126
- {delta && (
120
+ {delta ? (
121
+ <>
122
+ <tr>
123
+ <td className="w-1/4">Per Second</td>
124
+ <td className="w-3/4">
125
+ {valueFormatter(
126
+ highlighted.valuePerSecond,
127
+ sampleUnit === 'nanoseconds' ? 'CPU Cores' : sampleUnit,
128
+ 5
129
+ )}
130
+ </td>
131
+ </tr>
132
+ <tr>
133
+ <td className="w-1/4">Total</td>
134
+ <td className="w-3/4">
135
+ {valueFormatter(highlighted.value, sampleUnit, 2)}
136
+ </td>
137
+ </tr>
138
+ </>
139
+ ) : (
127
140
  <tr>
128
- <td className="w-1/4">Total</td>
141
+ <td className="w-1/4">Value</td>
129
142
  <td className="w-3/4">
130
- {valueFormatter(highlighted.value, sampleUnit, 2)}
143
+ {valueFormatter(highlighted.valuePerSecond, sampleUnit, 5)}
131
144
  </td>
132
145
  </tr>
133
146
  )}
@@ -392,9 +392,11 @@ export const RawMetricsGraph = ({
392
392
  const isDeltaType = profile !== null ? profile?.query.profType.delta : false;
393
393
 
394
394
  let yAxisLabel = sampleUnit;
395
+ let yAxisUnit = sampleUnit;
395
396
  if (isDeltaType) {
396
- if (profile?.query.profType.periodType === 'cpu' && sampleUnit === 'count') {
397
+ if (sampleUnit === 'nanoseconds') {
397
398
  yAxisLabel = 'CPU Cores';
399
+ yAxisUnit = '';
398
400
  }
399
401
  if (sampleUnit === 'bytes') {
400
402
  yAxisLabel = 'Bytes per Second';
@@ -477,7 +479,7 @@ export const RawMetricsGraph = ({
477
479
  >
478
480
  <line className="stroke-gray-300 dark:stroke-gray-500" x2={-6} />
479
481
  <text fill="currentColor" x={-9} dy={'0.32em'}>
480
- {valueFormatter(d, sampleUnit, decimals)}
482
+ {valueFormatter(d, yAxisUnit, decimals)}
481
483
  </text>
482
484
  </g>
483
485
  <g key={`grid-${i}`}>
@@ -172,6 +172,14 @@ const ProfileMetricsGraph = ({
172
172
  onPointClick(timestamp, labels, queryExpression);
173
173
  };
174
174
 
175
+ let sampleUnit = '';
176
+ if (series.every((val, i, arr) => val?.sampleType?.unit === arr[0]?.sampleType?.unit)) {
177
+ sampleUnit = series[0]?.sampleType?.unit ?? '';
178
+ }
179
+ if (sampleUnit === '') {
180
+ sampleUnit = Query.parse(queryExpression).profileType().sampleUnit;
181
+ }
182
+
175
183
  return (
176
184
  <AnimatePresence>
177
185
  <motion.div
@@ -189,7 +197,7 @@ const ProfileMetricsGraph = ({
189
197
  setTimeRange={setTimeRange}
190
198
  onSampleClick={handleSampleClick}
191
199
  addLabelMatcher={addLabelMatcher}
192
- sampleUnit={Query.parse(queryExpression).profileType().sampleUnit}
200
+ sampleUnit={sampleUnit}
193
201
  height={height}
194
202
  width={width}
195
203
  margin={margin}
@@ -135,7 +135,18 @@ export const ProfileViewWithData = ({
135
135
  perf,
136
136
  ]);
137
137
 
138
- const sampleUnit = profileSource.ProfileType().sampleUnit;
138
+ // Default to the unit of the selected profile type. This is a heuristic, and
139
+ // only a fallback, the unit should be returned by the backend.
140
+ let sampleUnit = profileSource.ProfileType().sampleUnit;
141
+ if (flamegraphResponse?.report.oneofKind === 'flamegraphArrow') {
142
+ sampleUnit = flamegraphResponse.report.flamegraphArrow.unit;
143
+ }
144
+ if (tableResponse?.report.oneofKind === 'tableArrow') {
145
+ sampleUnit = tableResponse.report.tableArrow.unit;
146
+ }
147
+ if (sourceResponse?.report.oneofKind === 'source') {
148
+ sampleUnit = sourceResponse.report.source.unit;
149
+ }
139
150
 
140
151
  const downloadPProfClick = async (): Promise<void> => {
141
152
  if (profileSource == null || queryClient == null) {