@parca/profile 0.16.114 → 0.16.116

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.116 (2023-02-15)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.115](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.114...@parca/profile@0.16.115) (2023-02-13)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.114](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.113...@parca/profile@0.16.114) (2023-02-13)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -1,12 +1,12 @@
1
1
  /// <reference types="react" />
2
2
  import { DateTimeRange } from '@parca/components';
3
3
  import { MetricsSeries as MetricsSeriesPb, Label } from '@parca/client';
4
- import { SingleProfileSelection } from '..';
4
+ import { MergedProfileSelection } from '..';
5
5
  interface Props {
6
6
  data: MetricsSeriesPb[];
7
7
  from: number;
8
8
  to: number;
9
- profile: SingleProfileSelection | null;
9
+ profile: MergedProfileSelection | null;
10
10
  onSampleClick: (timestamp: number, value: number, labels: Label[]) => void;
11
11
  onLabelClick: (labelName: string, labelValue: string) => void;
12
12
  setTimeRange: (range: DateTimeRange) => void;
@@ -28,7 +28,7 @@ import { pointer } from 'd3-selection';
28
28
  import throttle from 'lodash.throttle';
29
29
  import { DateTimeRange, useKeyDown } from '@parca/components';
30
30
  import { useContainerDimensions } from '@parca/dynamicsize';
31
- import { formatForTimespan } from '@parca/functions/time';
31
+ import { formatForTimespan } from '@parca/functions';
32
32
  import { valueFormatter, formatDate, sanitizeHighlightedValues } from '@parca/functions';
33
33
  import MetricsSeries from '../MetricsSeries';
34
34
  import MetricsCircle from '../MetricsCircle';
@@ -56,7 +56,8 @@ export var RawMetricsGraph = function (_a) {
56
56
  var _e = useState([0, 0]), pos = _e[0], setPos = _e[1];
57
57
  var metricPointRef = useRef(null);
58
58
  var isShiftDown = useKeyDown().isShiftDown;
59
- var time = parseFloat(profile === null || profile === void 0 ? void 0 : profile.HistoryParams().time);
59
+ // the time of the selected point is the start of the merge window
60
+ var time = parseFloat(profile === null || profile === void 0 ? void 0 : profile.HistoryParams().merge_from);
60
61
  if (width === undefined || width == null) {
61
62
  width = 0;
62
63
  }
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
12
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  // Copyright 2022 The Parca Authors
14
14
  // Licensed under the Apache License, Version 2.0 (the "License");
15
15
  // you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
22
22
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
23
  // See the License for the specific language governing permissions and
24
24
  // limitations under the License.
25
+ import { useEffect, useState } from 'react';
25
26
  import { useProfileTypes } from '../ProfileSelector';
26
27
  import { ProfileSelectionFromParams, SuffixParams } from '..';
27
28
  import ProfileExplorerSingle from './ProfileExplorerSingle';
@@ -62,11 +63,45 @@ var swapQueryParameters = function (o) {
62
63
  var ProfileExplorerApp = function (_a) {
63
64
  var _b, _c;
64
65
  var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
65
- var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data, error = _d.error;
66
- var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt;
66
+ var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data, profileTypesError = _d.error;
67
+ var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt, onError = _e.onError;
68
+ useEffect(function () {
69
+ if (profileTypesError !== undefined && profileTypesError !== null) {
70
+ onError === null || onError === void 0 ? void 0 : onError(profileTypesError, 'ProfileExplorer');
71
+ }
72
+ }, [profileTypesError, onError]);
67
73
  /* eslint-disable @typescript-eslint/naming-convention */
68
- var from_a = queryParams.from_a, to_a = queryParams.to_a, merge_a = queryParams.merge_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, time_a = queryParams.time_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, merge_b = queryParams.merge_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, time_b = queryParams.time_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
74
+ var from_a = queryParams.from_a, to_a = queryParams.to_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, merge_from_a = queryParams.merge_from_a, merge_to_a = queryParams.merge_to_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, merge_from_b = queryParams.merge_from_b, merge_to_b = queryParams.merge_to_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
69
75
  /* eslint-enable @typescript-eslint/naming-convention */
76
+ var _f = useState(null), profileA = _f[0], setProfileA = _f[1];
77
+ var _g = useState(null), profileB = _g[0], setProfileB = _g[1];
78
+ useEffect(function () {
79
+ var _a;
80
+ var mergeFrom = merge_from_a !== null && merge_from_a !== void 0 ? merge_from_a : undefined;
81
+ var mergeTo = merge_to_a !== null && merge_to_a !== void 0 ? merge_to_a : undefined;
82
+ var labels = (_a = labels_a) !== null && _a !== void 0 ? _a : [''];
83
+ var profileA = ProfileSelectionFromParams(expression_a, from_a, to_a, mergeFrom, mergeTo, labels, filter_by_function);
84
+ setProfileA(profileA);
85
+ // eslint-disable-next-line react-hooks/exhaustive-deps
86
+ }, [merge_from_a, merge_to_a]);
87
+ useEffect(function () {
88
+ var _a;
89
+ var mergeFrom = merge_from_b !== null && merge_from_b !== void 0 ? merge_from_b : undefined;
90
+ var mergeTo = merge_to_b !== null && merge_to_b !== void 0 ? merge_to_b : undefined;
91
+ var labels = (_a = labels_b) !== null && _a !== void 0 ? _a : [''];
92
+ var profileB = ProfileSelectionFromParams(expression_b, from_b, to_b, mergeFrom, mergeTo, labels, filter_by_function);
93
+ setProfileB(profileB);
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps
95
+ }, [merge_from_b, merge_to_b]);
96
+ if (profileTypesLoading) {
97
+ return _jsx(_Fragment, { children: loader });
98
+ }
99
+ if ((profileTypesData === null || profileTypesData === void 0 ? void 0 : profileTypesData.types.length) === 0) {
100
+ return _jsx(_Fragment, { children: noDataPrompt });
101
+ }
102
+ if (profileTypesError !== undefined && profileTypesError !== null) {
103
+ return (_jsxs("div", __assign({ className: "bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative", role: "alert" }, { children: [_jsx("strong", __assign({ className: "font-bold" }, { children: "Error! " })), _jsx("span", __assign({ className: "block sm:inline" }, { children: profileTypesError.message }))] })));
104
+ }
70
105
  var sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
71
106
  time_selection_a = sanitizedRange.time_selection_a;
72
107
  from_a = sanitizedRange.from_a;
@@ -90,32 +125,20 @@ var ProfileExplorerApp = function (_a) {
90
125
  var selectProfileB = function (p) {
91
126
  return selectProfile(p, '_b');
92
127
  };
93
- if (profileTypesLoading) {
94
- return _jsx(_Fragment, { children: loader });
95
- }
96
- if ((profileTypesData === null || profileTypesData === void 0 ? void 0 : profileTypesData.types.length) === 0) {
97
- return _jsx(_Fragment, { children: noDataPrompt });
98
- }
128
+ var queryA = {
129
+ expression: expression_a,
130
+ from: parseInt(from_a),
131
+ to: parseInt(to_a),
132
+ timeSelection: time_selection_a,
133
+ profile_name: profile_name_a,
134
+ };
99
135
  // Show the SingleProfileExplorer when not comparing
100
136
  if (compare_a !== 'true' && compare_b !== 'true') {
101
- var query_1 = {
102
- expression: expression_a,
103
- from: parseInt(from_a),
104
- to: parseInt(to_a),
105
- merge: merge_a === 'true',
106
- profile_name: profile_name_a,
107
- timeSelection: time_selection_a,
108
- };
109
- var profile_1 = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a, filter_by_function);
110
137
  var selectQuery = function (q) {
111
- return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), {
112
- expression_a: encodeURIComponent(q.expression),
113
- from_a: q.from.toString(),
114
- to_a: q.to.toString(),
115
- merge_a: q.merge,
116
- time_selection_a: q.timeSelection,
117
- dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
118
- }));
138
+ var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
139
+ ? { merge_from_a: q.mergeFrom, merge_to_a: q.mergeTo }
140
+ : {};
141
+ return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), __assign({ expression_a: encodeURIComponent(q.expression), from_a: q.from.toString(), to_a: q.to.toString(), time_selection_a: q.timeSelection, dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
119
142
  };
120
143
  var selectProfile_1 = function (p) {
121
144
  queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
@@ -124,70 +147,43 @@ var ProfileExplorerApp = function (_a) {
124
147
  var compareProfile = function () {
125
148
  var compareQuery = {
126
149
  compare_a: 'true',
127
- expression_a: encodeURIComponent(query_1.expression),
128
- from_a: query_1.from.toString(),
129
- to_a: query_1.to.toString(),
130
- merge_a: query_1.merge,
131
- time_selection_a: query_1.timeSelection,
132
- profile_name_a: query_1.profile_name,
150
+ expression_a: encodeURIComponent(queryA.expression),
151
+ from_a: queryA.from.toString(),
152
+ to_a: queryA.to.toString(),
153
+ time_selection_a: queryA.timeSelection,
154
+ profile_name_a: queryA.profile_name,
133
155
  compare_b: 'true',
134
- expression_b: encodeURIComponent(query_1.expression),
135
- from_b: query_1.from.toString(),
136
- to_b: query_1.to.toString(),
137
- merge_b: query_1.merge,
138
- time_selection_b: query_1.timeSelection,
139
- profile_name_b: query_1.profile_name,
156
+ expression_b: encodeURIComponent(queryA.expression),
157
+ from_b: queryA.from.toString(),
158
+ to_b: queryA.to.toString(),
159
+ time_selection_b: queryA.timeSelection,
160
+ profile_name_b: queryA.profile_name,
140
161
  };
141
- if (profile_1 != null) {
142
- compareQuery = __assign(__assign({}, SuffixParams(profile_1.HistoryParams(), '_a')), compareQuery);
162
+ if (profileA != null) {
163
+ compareQuery = __assign(__assign({}, SuffixParams(profileA.HistoryParams(), '_a')), compareQuery);
143
164
  }
144
165
  void navigateTo('/', __assign(__assign({}, compareQuery), { search_string: '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }));
145
166
  };
146
- return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: query_1, profile: profile_1, selectQuery: selectQuery, selectProfile: selectProfile_1, compareProfile: compareProfile, navigateTo: navigateTo }));
167
+ return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: queryA, profile: profileA, selectQuery: selectQuery, selectProfile: selectProfile_1, compareProfile: compareProfile, navigateTo: navigateTo }));
147
168
  }
148
- var queryA = {
149
- expression: expression_a,
150
- from: parseInt(from_a),
151
- to: parseInt(to_a),
152
- merge: merge_a === 'true',
153
- timeSelection: time_selection_a,
154
- profile_name: profile_name_a,
155
- };
156
169
  var queryB = {
157
170
  expression: expression_b,
158
171
  from: parseInt(from_b),
159
172
  to: parseInt(to_b),
160
- merge: merge_b === 'true',
161
173
  timeSelection: time_selection_b,
162
174
  profile_name: profile_name_b,
163
175
  };
164
- var profileA = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a);
165
- var profileB = ProfileSelectionFromParams(expression_b, from_b, to_b, merge_b, labels_b, profile_name_b, time_b);
166
176
  var selectQueryA = function (q) {
167
- return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), {
168
- compare_a: 'true',
169
- expression_a: encodeURIComponent(q.expression),
170
- expression_b: encodeURIComponent(expression_b),
171
- from_a: q.from.toString(),
172
- to_a: q.to.toString(),
173
- merge_a: q.merge,
174
- time_selection_a: q.timeSelection,
175
- filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
176
- dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
177
- }));
177
+ var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
178
+ ? { merge_from_a: q.mergeFrom, merge_to_a: q.mergeTo }
179
+ : {};
180
+ return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), __assign({ compare_a: 'true', expression_a: encodeURIComponent(q.expression), expression_b: encodeURIComponent(expression_b), from_a: q.from.toString(), to_a: q.to.toString(), time_selection_a: q.timeSelection, filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
178
181
  };
179
182
  var selectQueryB = function (q) {
180
- return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_b')), {
181
- compare_b: 'true',
182
- expression_b: encodeURIComponent(q.expression),
183
- expression_a: encodeURIComponent(expression_a),
184
- from_b: q.from.toString(),
185
- to_b: q.to.toString(),
186
- merge_b: q.merge,
187
- time_selection_b: q.timeSelection,
188
- filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
189
- dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
190
- }));
183
+ var mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
184
+ ? { merge_from_b: q.mergeFrom, merge_to_b: q.mergeTo }
185
+ : {};
186
+ return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_b')), __assign({ compare_b: 'true', expression_b: encodeURIComponent(q.expression), expression_a: encodeURIComponent(expression_a), from_b: q.from.toString(), to_b: q.to.toString(), time_selection_b: q.timeSelection, filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }, mergeParams)));
191
187
  };
192
188
  var closeProfile = function (card) {
193
189
  var newQueryParameters = queryParams;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { ProfileSelection } from '..';
3
- import { QueryServiceClient, QueryRangeResponse } from '@parca/client';
3
+ import { QueryServiceClient, QueryRangeResponse, Label } from '@parca/client';
4
4
  import { RpcError } from '@protobuf-ts/runtime-rpc';
5
5
  import { DateTimeRange } from '@parca/components';
6
6
  interface ProfileMetricsGraphProps {
@@ -9,9 +9,9 @@ interface ProfileMetricsGraphProps {
9
9
  profile: ProfileSelection | null;
10
10
  from: number;
11
11
  to: number;
12
- select: (source: ProfileSelection) => void;
13
12
  setTimeRange: (range: DateTimeRange) => void;
14
13
  addLabelMatcher: (key: string, value: string) => void;
14
+ onPointClick: (timestamp: number, labels: Label[], queryExpression: string) => void;
15
15
  }
16
16
  export interface IQueryRangeState {
17
17
  response: QueryRangeResponse | null;
@@ -19,5 +19,5 @@ export interface IQueryRangeState {
19
19
  error: RpcError | null;
20
20
  }
21
21
  export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number) => IQueryRangeState;
22
- declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, select, setTimeRange, addLabelMatcher, }: ProfileMetricsGraphProps) => JSX.Element;
22
+ declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, }: ProfileMetricsGraphProps) => JSX.Element;
23
23
  export default ProfileMetricsGraph;
@@ -60,11 +60,11 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
60
60
  // limitations under the License.
61
61
  import { useState, useEffect } from 'react';
62
62
  import MetricsGraph from '../MetricsGraph';
63
- import { SingleProfileSelection } from '..';
64
- import { Timestamp } from '@parca/client';
63
+ import { Timestamp, Duration } from '@parca/client';
65
64
  import { useGrpcMetadata, useParcaContext } from '@parca/components';
66
65
  import { Query } from '@parca/parser';
67
66
  import useDelayedLoader from '../useDelayedLoader';
67
+ import { getStepDuration } from '@parca/functions';
68
68
  export var useQueryRange = function (client, queryExpression, start, end) {
69
69
  var _a = useState({
70
70
  response: null,
@@ -74,17 +74,19 @@ export var useQueryRange = function (client, queryExpression, start, end) {
74
74
  var metadata = useGrpcMetadata();
75
75
  useEffect(function () {
76
76
  void (function () { return __awaiter(void 0, void 0, void 0, function () {
77
- var call;
77
+ var stepDuration, call;
78
78
  return __generator(this, function (_a) {
79
79
  setState({
80
80
  response: null,
81
81
  isLoading: true,
82
82
  error: null,
83
83
  });
84
+ stepDuration = getStepDuration(start, end);
84
85
  call = client.queryRange({
85
86
  query: queryExpression,
86
87
  start: Timestamp.fromDate(new Date(start)),
87
88
  end: Timestamp.fromDate(new Date(end)),
89
+ step: Duration.create(stepDuration),
88
90
  limit: 0,
89
91
  }, { meta: metadata });
90
92
  call.response
@@ -97,7 +99,7 @@ export var useQueryRange = function (client, queryExpression, start, end) {
97
99
  return state;
98
100
  };
99
101
  var ProfileMetricsGraph = function (_a) {
100
- var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to, select = _a.select, setTimeRange = _a.setTimeRange, addLabelMatcher = _a.addLabelMatcher;
102
+ var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to, setTimeRange = _a.setTimeRange, addLabelMatcher = _a.addLabelMatcher, onPointClick = _a.onPointClick;
101
103
  var _b = useQueryRange(queryClient, queryExpression, from, to), isLoading = _b.isLoading, response = _b.response, error = _b.error;
102
104
  var isLoaderVisible = useDelayedLoader(isLoading);
103
105
  var _c = useParcaContext(), loader = _c.loader, onError = _c.onError;
@@ -115,7 +117,7 @@ var ProfileMetricsGraph = function (_a) {
115
117
  var series = response === null || response === void 0 ? void 0 : response.series;
116
118
  if (series !== null && series !== undefined && (series === null || series === void 0 ? void 0 : series.length) > 0) {
117
119
  var handleSampleClick = function (timestamp, _value, labels) {
118
- select(new SingleProfileSelection(Query.parse(queryExpression).profileName(), labels, timestamp));
120
+ onPointClick(timestamp, labels, queryExpression);
119
121
  };
120
122
  return (_jsx("div", __assign({ className: "dark:bg-gray-700 rounded border-gray-300 dark:border-gray-500", style: { borderWidth: 1 } }, { children: _jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: handleSampleClick, onLabelClick: addLabelMatcher, width: 0, sampleUnit: Query.parse(queryExpression).profileType().sampleUnit }) })));
121
123
  }
@@ -6,8 +6,9 @@ export interface QuerySelection {
6
6
  expression: string;
7
7
  from: number;
8
8
  to: number;
9
- merge: boolean;
10
9
  timeSelection: string;
10
+ mergeFrom?: number;
11
+ mergeTo?: number;
11
12
  }
12
13
  interface ProfileSelectorProps {
13
14
  queryClient: QueryServiceClient;
@@ -23,10 +23,11 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
23
23
  // See the License for the specific language governing permissions and
24
24
  // limitations under the License.
25
25
  import { Query } from '@parca/parser';
26
+ import { getStepDuration, getStepDurationInMilliseconds } from '@parca/functions';
27
+ import { MergedProfileSelection } from '..';
26
28
  import { useEffect, useState } from 'react';
27
29
  import ProfileMetricsGraph from '../ProfileMetricsGraph';
28
30
  import MatchersInput from '../MatchersInput/index';
29
- import MergeButton from './MergeButton';
30
31
  import CompareButton from './CompareButton';
31
32
  import { Card, DateTimeRangePicker, DateTimeRange, Button, ButtonGroup, useGrpcMetadata, } from '@parca/components';
32
33
  import { CloseIcon } from '@parca/icons';
@@ -70,17 +71,21 @@ var ProfileSelector = function (_a) {
70
71
  };
71
72
  var query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
72
73
  var selectedProfileName = query.profileName();
73
- var setNewQueryExpression = function (expr, merge) {
74
- selectQuery({
75
- expression: expr,
76
- from: timeRangeSelection.getFromMs(),
77
- to: timeRangeSelection.getToMs(),
78
- merge: merge,
79
- timeSelection: timeRangeSelection.getRangeKey(),
80
- });
74
+ var setNewQueryExpression = function (expr) {
75
+ var query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(expr);
76
+ var delta = query.profileType().delta;
77
+ var from = timeRangeSelection.getFromMs();
78
+ var to = timeRangeSelection.getToMs();
79
+ var mergeParams = delta
80
+ ? {
81
+ mergeFrom: from,
82
+ mergeTo: to,
83
+ }
84
+ : {};
85
+ selectQuery(__assign({ expression: expr, from: from, to: to, timeSelection: timeRangeSelection.getRangeKey() }, mergeParams));
81
86
  };
82
87
  var setQueryExpression = function () {
83
- setNewQueryExpression(query.toString(), false);
88
+ setNewQueryExpression(query.toString());
84
89
  };
85
90
  var addLabelMatcher = function (key, value) {
86
91
  // When a user clicks on a label on the metrics graph tooltip,
@@ -88,12 +93,9 @@ var ProfileSelector = function (_a) {
88
93
  var newValue = value.includes('\\') ? value.replaceAll('\\', '\\\\') : value;
89
94
  var _a = Query.parse(queryExpressionString).setMatcher(key, newValue), newQuery = _a[0], changed = _a[1];
90
95
  if (changed) {
91
- setNewQueryExpression(newQuery.toString(), false);
96
+ setNewQueryExpression(newQuery.toString());
92
97
  }
93
98
  };
94
- var setMergedSelection = function () {
95
- setNewQueryExpression(queryExpressionString, true);
96
- };
97
99
  var setMatchersString = function (matchers) {
98
100
  var newExpressionString = "".concat(selectedProfileName, "{").concat(matchers, "}");
99
101
  setQueryExpressionString(newExpressionString);
@@ -112,24 +114,28 @@ var ProfileSelector = function (_a) {
112
114
  var searchDisabled = queryExpressionString === undefined ||
113
115
  queryExpressionString === '' ||
114
116
  queryExpressionString === '{}';
115
- var mergeDisabled = selectedProfileName === '' || querySelection.expression === undefined;
116
117
  var compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
117
- return (_jsxs(Card, { children: [_jsxs(Card.Header, __assign({ className: "flex space-x-2" }, { children: [_jsxs("div", __assign({ className: "flex flex-wrap w-full justify-start space-x-2 space-y-1" }, { children: [_jsx("div", __assign({ className: "ml-2 mt-1" }, { children: _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error }) })), _jsx("div", __assign({ className: "w-full flex-1" }, { children: _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query }) })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsxs(ButtonGroup, { children: [!searchDisabled && (_jsxs(_Fragment, { children: [_jsx(MergeButton, { disabled: mergeDisabled, onClick: setMergedSelection }), !comparing && (_jsx(CompareButton, { disabled: compareDisabled, onClick: handleCompareClick }))] })), _jsx(Button, __assign({ disabled: searchDisabled, onClick: function (e) {
118
+ return (_jsxs(Card, { children: [_jsxs(Card.Header, __assign({ className: "flex space-x-2" }, { children: [_jsxs("div", __assign({ className: "flex flex-wrap w-full justify-start space-x-2 space-y-1" }, { children: [_jsx("div", __assign({ className: "ml-2 mt-1" }, { children: _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error }) })), _jsx("div", __assign({ className: "w-full flex-1" }, { children: _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, __assign({ disabled: searchDisabled, onClick: function (e) {
118
119
  e.preventDefault();
119
120
  setQueryExpression();
120
- } }, { children: "Search" }))] })] })), _jsx("div", { children: comparing && (_jsx("button", __assign({ type: "button", onClick: function () { return closeProfile(); } }, { children: _jsx(CloseIcon, {}) }))) })] })), !querySelection.merge && (_jsx(Card.Body, { children: querySelection.expression !== undefined &&
121
+ } }, { children: "Search" }))] })] })), _jsx("div", { children: comparing && (_jsx("button", __assign({ type: "button", onClick: function () { return closeProfile(); } }, { children: _jsx(CloseIcon, {}) }))) })] })), _jsx(Card.Body, { children: querySelection.expression !== undefined &&
121
122
  querySelection.expression.length > 0 &&
122
123
  querySelection.from !== undefined &&
123
- querySelection.to !== undefined &&
124
- (profileSelection == null || profileSelection.Type() !== 'merge') ? (_jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, select: selectProfile, profile: profileSelection, setTimeRange: function (range) {
124
+ querySelection.to !== undefined ? (_jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, setTimeRange: function (range) {
125
125
  setTimeRangeSelection(range);
126
126
  selectQuery({
127
127
  expression: queryExpressionString,
128
128
  from: range.getFromMs(),
129
129
  to: range.getToMs(),
130
- merge: false,
131
130
  timeSelection: range.getRangeKey(),
132
131
  });
133
- }, addLabelMatcher: addLabelMatcher })) : (_jsx(_Fragment, { children: (profileSelection == null || profileSelection.Type() !== 'merge') && (_jsx("div", __assign({ className: "my-20 text-center" }, { children: _jsx("p", { children: "Run a query, and the result will be displayed here." }) }))) })) }))] }));
132
+ }, addLabelMatcher: addLabelMatcher, onPointClick: function (timestamp, labels, queryExpression) {
133
+ var stepDuration = getStepDuration(querySelection.from, querySelection.to);
134
+ var stepDurationInMilliseconds = getStepDurationInMilliseconds(stepDuration);
135
+ var isDeltaType = Query.parse(queryExpression).profileType().delta;
136
+ var mergeFrom = timestamp;
137
+ var mergeTo = isDeltaType ? mergeFrom + stepDurationInMilliseconds : mergeFrom;
138
+ selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, labels, queryExpression));
139
+ } })) : (_jsx(_Fragment, { children: profileSelection == null && (_jsx("div", __assign({ className: "my-20 text-center" }, { children: _jsx("p", { children: "Run a query, and the result will be displayed here." }) }))) })) })] }));
134
140
  };
135
141
  export default ProfileSelector;
@@ -27,48 +27,21 @@ export declare function SuffixParams(params: {
27
27
  [key: string]: any;
28
28
  };
29
29
  export declare function ParseLabels(labels: string[]): Label[];
30
- export declare function ProfileSelectionFromParams(expression: string | undefined, from: string | undefined, to: string | undefined, merge: string | undefined, labels: string[] | undefined, profileName: string | undefined, time: string | undefined, filterQuery?: string): ProfileSelection | null;
31
- export declare class SingleProfileSelection implements ProfileSelection {
32
- profileName: string;
33
- labels: Label[];
34
- time: number;
35
- filterQuery: string | undefined;
36
- constructor(profileName: string, labels: Label[], time: number, filterQuery?: string);
37
- ProfileName(): string;
38
- HistoryParams(): {
39
- [key: string]: any;
40
- };
41
- Type(): string;
42
- ProfileSource(): ProfileSource;
43
- }
30
+ export declare function ProfileSelectionFromParams(expression: string | undefined, from: string | undefined, to: string | undefined, mergeFrom: string | undefined, mergeTo: string | undefined, labels: string[], filterQuery?: string): ProfileSelection | null;
44
31
  export declare class MergedProfileSelection implements ProfileSelection {
45
- from: number;
46
- to: number;
32
+ mergeFrom: number;
33
+ mergeTo: number;
47
34
  query: string;
48
35
  filterQuery: string | undefined;
49
- constructor(from: number, to: number, query: string, filterQuery?: string);
36
+ labels: Label[];
37
+ constructor(mergeFrom: number, mergeTo: number, labels: Label[], query: string, filterQuery?: string);
50
38
  ProfileName(): string;
51
39
  HistoryParams(): {
52
- [key: string]: string;
40
+ [key: string]: any;
53
41
  };
54
42
  Type(): string;
55
43
  ProfileSource(): ProfileSource;
56
44
  }
57
- export declare class SingleProfileSource implements ProfileSource {
58
- profName: string;
59
- labels: Label[];
60
- time: number;
61
- filterQuery: string | undefined;
62
- constructor(profileName: string, labels: Label[], time: number, filterQuery?: string);
63
- query(): string;
64
- DiffSelection(): ProfileDiffSelection;
65
- QueryRequest(): QueryRequest;
66
- ProfileType(): ProfileType;
67
- profileName(): string;
68
- Describe(): JSX.Element;
69
- stringLabels(): string[];
70
- toString(): string;
71
- }
72
45
  export declare class ProfileDiffSource implements ProfileSource {
73
46
  a: ProfileSource;
74
47
  b: ProfileSource;
@@ -81,14 +54,16 @@ export declare class ProfileDiffSource implements ProfileSource {
81
54
  toString(): string;
82
55
  }
83
56
  export declare class MergedProfileSource implements ProfileSource {
84
- from: number;
85
- to: number;
57
+ mergeFrom: number;
58
+ mergeTo: number;
59
+ labels: Label[];
86
60
  query: string;
87
61
  filterQuery: string | undefined;
88
- constructor(from: number, to: number, query: string, filterQuery?: string);
62
+ constructor(mergeFrom: number, mergeTo: number, labels: Label[], query: string, filterQuery?: string);
89
63
  DiffSelection(): ProfileDiffSelection;
90
64
  QueryRequest(): QueryRequest;
91
65
  ProfileType(): ProfileType;
92
66
  Describe(): JSX.Element;
67
+ stringLabels(): string[];
93
68
  toString(): string;
94
69
  }