@parca/profile 0.16.369 → 0.16.372

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,18 @@
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.372](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.371...@parca/profile@0.16.372) (2024-05-16)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.371](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.370...@parca/profile@0.16.371) (2024-05-16)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
14
+ ## [0.16.370](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.369...@parca/profile@0.16.370) (2024-05-14)
15
+
16
+ **Note:** Version bump only for package @parca/profile
17
+
6
18
  ## [0.16.369](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.368...@parca/profile@0.16.369) (2024-05-14)
7
19
 
8
20
  **Note:** Version bump only for package @parca/profile
@@ -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 { Fragment, useCallback, useMemo, useRef, useState } from 'react';
14
+ import { Fragment, useCallback, useId, useMemo, 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';
@@ -45,6 +45,7 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLab
45
45
  const [pos, setPos] = useState([0, 0]);
46
46
  const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
47
47
  const metricPointRef = useRef(null);
48
+ const idForContextMenu = useId();
48
49
  // the time of the selected point is the start of the merge window
49
50
  const time = parseFloat(profile?.HistoryParams().merge_from);
50
51
  if (width === undefined || width == null) {
@@ -228,7 +229,7 @@ export const RawMetricsGraph = ({ data, from, to, profile, onSampleClick, addLab
228
229
  };
229
230
  };
230
231
  const selected = findSelectedProfile();
231
- const MENU_ID = 'metrics-context-menu';
232
+ const MENU_ID = `metrics-context-menu-${idForContextMenu}`;
232
233
  const { show } = useContextMenu({
233
234
  id: MENU_ID,
234
235
  });
@@ -143,7 +143,7 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
143
143
  queryExpressionString === '' ||
144
144
  queryExpressionString === '{}';
145
145
  const compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
146
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex gap-2", children: [_jsxs("div", { className: "flex w-full flex-wrap content-start items-center justify-between gap-2", children: [_jsxs("div", { className: "pb-6", children: [_jsx("label", { className: "text-xs", children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error })] }), _jsxs("div", { className: "w-full flex-1 pb-6", children: [_jsxs("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: [_jsx("label", { className: "text-xs", children: "Query" }), (query.matchers.length > 0 || query.inputMatcherString.length > 0) &&
146
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex gap-2", children: [_jsxs("div", { className: "flex w-full flex-wrap content-start items-center justify-between gap-2", children: [_jsxs("div", { className: "pb-6", children: [_jsx("label", { className: "text-xs", children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error, disabled: viewComponent?.disableProfileTypesDropdown })] }), _jsxs("div", { className: "w-full flex-1 pb-6", children: [_jsxs("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: [_jsx("label", { className: "text-xs", children: "Query" }), (query.matchers.length > 0 || query.inputMatcherString.length > 0) &&
147
147
  viewComponent !== undefined && _jsx("div", { children: viewComponent?.createViewComponent })] }), _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsxs(ButtonGroup, { children: [!searchDisabled && (_jsx(_Fragment, { children: !comparing && (_jsx(CompareButton, { disabled: compareDisabled, onClick: handleCompareClick })) })), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
148
148
  e.preventDefault();
149
149
  setQueryExpression(true);
@@ -117,6 +117,11 @@ export class ProfileDiffSource {
117
117
  return (_jsx(_Fragment, { children: _jsx("p", { children: "Browse the comparison" }) }));
118
118
  }
119
119
  toString() {
120
+ const aDesc = this.a.toString();
121
+ const bDesc = this.b.toString();
122
+ if (aDesc === bDesc) {
123
+ return 'profile comparison';
124
+ }
120
125
  return `${this.a.toString()} compared with ${this.b.toString()}`;
121
126
  }
122
127
  }
@@ -164,6 +169,14 @@ export class MergedProfileSource {
164
169
  .map((m) => `${m.key}=${m.value}`);
165
170
  }
166
171
  toString(timezone) {
167
- return `merged profiles of query "${this.query.toString()}" from ${formatDate(this.mergeFrom, timeFormat(timezone), timezone)} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
172
+ let queryPart = '';
173
+ if (this.query.toString()?.length > 0) {
174
+ queryPart = ` of query "${this.query.toString()}"`;
175
+ }
176
+ let timePart = '';
177
+ if (this.mergeFrom !== 0) {
178
+ timePart = ` from ${formatDate(this.mergeFrom, timeFormat(timezone), timezone)} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
179
+ }
180
+ return `merged profiles${queryPart}${timePart}`;
168
181
  }
169
182
  }
@@ -21,6 +21,7 @@ interface Props {
21
21
  selectedKey: string | undefined;
22
22
  flexibleKnownProfilesDetection?: boolean;
23
23
  onSelection: (value: string | undefined) => void;
24
+ disabled?: boolean;
24
25
  }
25
- declare const ProfileTypeSelector: ({ profileTypesData, loading, error, selectedKey, onSelection, flexibleKnownProfilesDetection, }: Props) => JSX.Element;
26
+ declare const ProfileTypeSelector: ({ profileTypesData, loading, error, selectedKey, onSelection, flexibleKnownProfilesDetection, disabled, }: Props) => JSX.Element;
26
27
  export default ProfileTypeSelector;
@@ -110,7 +110,7 @@ export const normalizeProfileTypesData = (types) => {
110
110
  return a.localeCompare(b);
111
111
  });
112
112
  };
113
- const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selectedKey, onSelection, flexibleKnownProfilesDetection = false, }) => {
113
+ const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selectedKey, onSelection, flexibleKnownProfilesDetection = false, disabled, }) => {
114
114
  const profileNames = useMemo(() => {
115
115
  return (error === undefined || error == null) &&
116
116
  profileTypesData !== undefined &&
@@ -122,6 +122,6 @@ const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selecte
122
122
  key: name,
123
123
  element: profileSelectElement(name, flexibleKnownProfilesDetection),
124
124
  }));
125
- return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown" }));
125
+ return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled }));
126
126
  };
127
127
  export default ProfileTypeSelector;
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.369",
3
+ "version": "0.16.372",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
7
7
  "@iconify/react": "^4.0.0",
8
- "@parca/client": "^0.16.113",
9
- "@parca/components": "^0.16.274",
10
- "@parca/dynamicsize": "^0.16.64",
11
- "@parca/hooks": "^0.0.54",
12
- "@parca/icons": "^0.16.68",
13
- "@parca/parser": "^0.16.73",
14
- "@parca/store": "^0.16.143",
15
- "@parca/utilities": "^0.0.71",
8
+ "@parca/client": "^0.16.114",
9
+ "@parca/components": "^0.16.276",
10
+ "@parca/dynamicsize": "^0.16.65",
11
+ "@parca/hooks": "^0.0.56",
12
+ "@parca/icons": "^0.16.69",
13
+ "@parca/parser": "^0.16.74",
14
+ "@parca/store": "^0.16.145",
15
+ "@parca/utilities": "^0.0.73",
16
16
  "@popperjs/core": "^2.11.8",
17
17
  "@protobuf-ts/runtime-rpc": "^2.5.0",
18
18
  "@tanstack/react-query": "^4.0.5",
@@ -71,5 +71,5 @@
71
71
  "access": "public",
72
72
  "registry": "https://registry.npmjs.org/"
73
73
  },
74
- "gitHead": "704de2373c6b4ac3de52bd666f88e51981700f92"
74
+ "gitHead": "d0d5e43082aac764eecbe6e107b2d2f029132ff2"
75
75
  }
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {Fragment, useCallback, useMemo, useRef, useState} from 'react';
14
+ import React, {Fragment, useCallback, useId, useMemo, useRef, useState} from 'react';
15
15
 
16
16
  import * as d3 from 'd3';
17
17
  import {pointer} from 'd3-selection';
@@ -140,6 +140,7 @@ export const RawMetricsGraph = ({
140
140
  const [pos, setPos] = useState([0, 0]);
141
141
  const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
142
142
  const metricPointRef = useRef(null);
143
+ const idForContextMenu = useId();
143
144
 
144
145
  // the time of the selected point is the start of the merge window
145
146
  const time: number = parseFloat(profile?.HistoryParams().merge_from);
@@ -372,7 +373,7 @@ export const RawMetricsGraph = ({
372
373
 
373
374
  const selected = findSelectedProfile();
374
375
 
375
- const MENU_ID = 'metrics-context-menu';
376
+ const MENU_ID = `metrics-context-menu-${idForContextMenu}`;
376
377
 
377
378
  const {show} = useContextMenu({
378
379
  id: MENU_ID,
@@ -240,6 +240,7 @@ const ProfileSelector = ({
240
240
  selectedKey={selectedProfileName}
241
241
  onSelection={setProfileName}
242
242
  error={error}
243
+ disabled={viewComponent?.disableProfileTypesDropdown}
243
244
  />
244
245
  </div>
245
246
  <div className="w-full flex-1 pb-6">
@@ -182,6 +182,13 @@ export class ProfileDiffSource implements ProfileSource {
182
182
  }
183
183
 
184
184
  toString(): string {
185
+ const aDesc = this.a.toString();
186
+ const bDesc = this.b.toString();
187
+
188
+ if (aDesc === bDesc) {
189
+ return 'profile comparison';
190
+ }
191
+
185
192
  return `${this.a.toString()} compared with ${this.b.toString()}`;
186
193
  }
187
194
  }
@@ -240,10 +247,20 @@ export class MergedProfileSource implements ProfileSource {
240
247
  }
241
248
 
242
249
  toString(timezone?: string): string {
243
- return `merged profiles of query "${this.query.toString()}" from ${formatDate(
244
- this.mergeFrom,
245
- timeFormat(timezone),
246
- timezone
247
- )} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
250
+ let queryPart = '';
251
+ if (this.query.toString()?.length > 0) {
252
+ queryPart = ` of query "${this.query.toString()}"`;
253
+ }
254
+
255
+ let timePart = '';
256
+ if (this.mergeFrom !== 0) {
257
+ timePart = ` from ${formatDate(
258
+ this.mergeFrom,
259
+ timeFormat(timezone),
260
+ timezone
261
+ )} to ${formatDate(this.mergeTo, timeFormat(timezone), timezone)}`;
262
+ }
263
+
264
+ return `merged profiles${queryPart}${timePart}`;
248
265
  }
249
266
  }
@@ -147,6 +147,7 @@ interface Props {
147
147
  selectedKey: string | undefined;
148
148
  flexibleKnownProfilesDetection?: boolean;
149
149
  onSelection: (value: string | undefined) => void;
150
+ disabled?: boolean;
150
151
  }
151
152
 
152
153
  const ProfileTypeSelector = ({
@@ -156,6 +157,7 @@ const ProfileTypeSelector = ({
156
157
  selectedKey,
157
158
  onSelection,
158
159
  flexibleKnownProfilesDetection = false,
160
+ disabled,
159
161
  }: Props): JSX.Element => {
160
162
  const profileNames = useMemo(() => {
161
163
  return (error === undefined || error == null) &&
@@ -178,6 +180,7 @@ const ProfileTypeSelector = ({
178
180
  placeholder="Select profile type..."
179
181
  loading={loading}
180
182
  className="bg-white h-profile-type-dropdown"
183
+ disabled={disabled}
181
184
  />
182
185
  );
183
186
  };