@parca/profile 0.16.74 → 0.16.76
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/Callgraph/index.d.ts +1 -0
- package/dist/GraphTooltip/index.d.ts +1 -0
- package/dist/IcicleGraph.d.ts +1 -0
- package/dist/MatchersInput/SuggestionItem.d.ts +1 -0
- package/dist/MatchersInput/SuggestionsList.d.ts +24 -0
- package/dist/MatchersInput/SuggestionsList.js +162 -0
- package/dist/MatchersInput/index.d.ts +1 -0
- package/dist/MatchersInput/index.js +75 -185
- package/dist/MetricsCircle/index.d.ts +1 -0
- package/dist/MetricsGraph/index.d.ts +1 -0
- package/dist/MetricsGraph/index.js +3 -2
- package/dist/MetricsSeries/index.d.ts +1 -0
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +1 -0
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +1 -0
- package/dist/ProfileExplorer/index.d.ts +1 -0
- package/dist/ProfileIcicleGraph.d.ts +1 -0
- package/dist/ProfileMetricsGraph/index.d.ts +1 -0
- package/dist/ProfileSelector/CompareButton.d.ts +1 -0
- package/dist/ProfileSelector/MergeButton.d.ts +1 -0
- package/dist/ProfileSelector/index.d.ts +1 -0
- package/dist/ProfileSelector/index.js +4 -1
- package/dist/ProfileSource.d.ts +1 -0
- package/dist/ProfileTypeSelector/index.d.ts +1 -0
- package/dist/ProfileView/FilterByFunctionButton.d.ts +1 -0
- package/dist/ProfileView/index.d.ts +1 -0
- package/dist/ProfileViewWithData.d.ts +1 -0
- package/dist/TopTable.d.ts +1 -0
- package/dist/components/DiffLegend.d.ts +1 -0
- package/dist/components/ProfileShareButton/ResultBox.d.ts +1 -0
- package/dist/components/ProfileShareButton/index.d.ts +1 -0
- package/dist/styles.css +1 -1
- package/package.json +7 -6
- package/src/MatchersInput/SuggestionsList.tsx +291 -0
- package/src/MatchersInput/index.tsx +85 -287
- package/src/MetricsGraph/index.tsx +6 -2
- package/src/ProfileSelector/index.tsx +4 -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.76](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.75...@parca/profile@0.16.76) (2022-11-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## 0.16.75 (2022-11-29)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.74](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.73...@parca/profile@0.16.74) (2022-11-24)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
package/dist/IcicleGraph.d.ts
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare class Suggestion {
|
|
3
|
+
type: string;
|
|
4
|
+
typeahead: string;
|
|
5
|
+
value: string;
|
|
6
|
+
constructor(type: string, typeahead: string, value: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class Suggestions {
|
|
9
|
+
literals: Suggestion[];
|
|
10
|
+
labelNames: Suggestion[];
|
|
11
|
+
labelValues: Suggestion[];
|
|
12
|
+
constructor();
|
|
13
|
+
}
|
|
14
|
+
interface Props {
|
|
15
|
+
suggestions: Suggestions;
|
|
16
|
+
applySuggestion: (suggestion: Suggestion) => void;
|
|
17
|
+
inputRef: HTMLTextAreaElement | null;
|
|
18
|
+
runQuery: () => void;
|
|
19
|
+
focusedInput: boolean;
|
|
20
|
+
isLabelNamesLoading: boolean;
|
|
21
|
+
isLabelValuesLoading: boolean;
|
|
22
|
+
}
|
|
23
|
+
declare const SuggestionsList: ({ suggestions, applySuggestion, inputRef, runQuery, focusedInput, isLabelNamesLoading, isLabelValuesLoading, }: Props) => JSX.Element;
|
|
24
|
+
export default SuggestionsList;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
// Copyright 2022 The Parca Authors
|
|
14
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
15
|
+
// you may not use this file except in compliance with the License.
|
|
16
|
+
// You may obtain a copy of the License at
|
|
17
|
+
//
|
|
18
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
19
|
+
//
|
|
20
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
21
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
22
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
23
|
+
// See the License for the specific language governing permissions and
|
|
24
|
+
// limitations under the License.
|
|
25
|
+
import { Fragment, useCallback, useEffect, useState } from 'react';
|
|
26
|
+
import { Transition } from '@headlessui/react';
|
|
27
|
+
import SuggestionItem from './SuggestionItem';
|
|
28
|
+
import { usePopper } from 'react-popper';
|
|
29
|
+
import { useParcaContext } from '@parca/components';
|
|
30
|
+
var Suggestion = /** @class */ (function () {
|
|
31
|
+
function Suggestion(type, typeahead, value) {
|
|
32
|
+
this.type = type;
|
|
33
|
+
this.typeahead = typeahead;
|
|
34
|
+
this.value = value;
|
|
35
|
+
}
|
|
36
|
+
return Suggestion;
|
|
37
|
+
}());
|
|
38
|
+
export { Suggestion };
|
|
39
|
+
var Suggestions = /** @class */ (function () {
|
|
40
|
+
function Suggestions() {
|
|
41
|
+
this.literals = [];
|
|
42
|
+
this.labelNames = [];
|
|
43
|
+
this.labelValues = [];
|
|
44
|
+
}
|
|
45
|
+
return Suggestions;
|
|
46
|
+
}());
|
|
47
|
+
export { Suggestions };
|
|
48
|
+
var LoadingSpinner = function () {
|
|
49
|
+
var Spinner = useParcaContext().loader;
|
|
50
|
+
return _jsx("div", __assign({ className: "pt-2 pb-4" }, { children: Spinner }));
|
|
51
|
+
};
|
|
52
|
+
var SuggestionsList = function (_a) {
|
|
53
|
+
var suggestions = _a.suggestions, applySuggestion = _a.applySuggestion, inputRef = _a.inputRef, runQuery = _a.runQuery, focusedInput = _a.focusedInput, isLabelNamesLoading = _a.isLabelNamesLoading, isLabelValuesLoading = _a.isLabelValuesLoading;
|
|
54
|
+
var _b = useState(null), popperElement = _b[0], setPopperElement = _b[1];
|
|
55
|
+
var _c = usePopper(inputRef, popperElement, {
|
|
56
|
+
placement: 'bottom-start',
|
|
57
|
+
}), styles = _c.styles, attributes = _c.attributes;
|
|
58
|
+
var _d = useState(-1), highlightedSuggestionIndex = _d[0], setHighlightedSuggestionIndex = _d[1];
|
|
59
|
+
var _e = useState(true), showSuggest = _e[0], setShowSuggest = _e[1];
|
|
60
|
+
var suggestionsLength = suggestions.literals.length + suggestions.labelNames.length + suggestions.labelValues.length;
|
|
61
|
+
var getSuggestion = useCallback(function (index) {
|
|
62
|
+
if (index < suggestions.labelNames.length) {
|
|
63
|
+
return suggestions.labelNames[index];
|
|
64
|
+
}
|
|
65
|
+
if (index < suggestions.labelNames.length + suggestions.literals.length) {
|
|
66
|
+
return suggestions.literals[index - suggestions.labelNames.length];
|
|
67
|
+
}
|
|
68
|
+
return suggestions.labelValues[index - suggestions.labelNames.length - suggestions.literals.length];
|
|
69
|
+
}, [suggestions]);
|
|
70
|
+
var resetHighlight = useCallback(function () { return setHighlightedSuggestionIndex(-1); }, [setHighlightedSuggestionIndex]);
|
|
71
|
+
var applyHighlightedSuggestion = useCallback(function () {
|
|
72
|
+
applySuggestion(getSuggestion(highlightedSuggestionIndex));
|
|
73
|
+
resetHighlight();
|
|
74
|
+
}, [resetHighlight, applySuggestion, highlightedSuggestionIndex, getSuggestion]);
|
|
75
|
+
var applySuggestionWithIndex = useCallback(function (index) {
|
|
76
|
+
applySuggestion(getSuggestion(index));
|
|
77
|
+
resetHighlight();
|
|
78
|
+
}, [resetHighlight, applySuggestion, getSuggestion]);
|
|
79
|
+
var highlightNext = useCallback(function () {
|
|
80
|
+
var nextIndex = highlightedSuggestionIndex + 1;
|
|
81
|
+
if (nextIndex === suggestionsLength) {
|
|
82
|
+
resetHighlight();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
setHighlightedSuggestionIndex(nextIndex);
|
|
86
|
+
}, [highlightedSuggestionIndex, suggestionsLength, resetHighlight]);
|
|
87
|
+
var highlightPrevious = useCallback(function () {
|
|
88
|
+
if (highlightedSuggestionIndex === -1) {
|
|
89
|
+
// Didn't select anything, so starting at the bottom.
|
|
90
|
+
setHighlightedSuggestionIndex(suggestionsLength - 1);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
setHighlightedSuggestionIndex(highlightedSuggestionIndex - 1);
|
|
94
|
+
}, [highlightedSuggestionIndex, suggestionsLength]);
|
|
95
|
+
var handleKeyPress = useCallback(function (event) {
|
|
96
|
+
if (event.key === 'Enter') {
|
|
97
|
+
// Disable new line in the text area
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
}
|
|
100
|
+
// If there is a highlighted suggestion and enter is hit, we complete
|
|
101
|
+
// with the highlighted suggestion.
|
|
102
|
+
if (highlightedSuggestionIndex >= 0 && event.key === 'Enter') {
|
|
103
|
+
applyHighlightedSuggestion();
|
|
104
|
+
}
|
|
105
|
+
// If no suggestions is highlighted and we hit enter, we run the query,
|
|
106
|
+
// and hide suggestions until another actions enables them again.
|
|
107
|
+
if (highlightedSuggestionIndex === -1 && event.key === 'Enter') {
|
|
108
|
+
setShowSuggest(false);
|
|
109
|
+
runQuery();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setShowSuggest(true);
|
|
113
|
+
}, [highlightedSuggestionIndex, applyHighlightedSuggestion, runQuery]);
|
|
114
|
+
var handleKeyDown = useCallback(function (event) {
|
|
115
|
+
// Don't need to handle any key interactions if no suggestions there.
|
|
116
|
+
if (suggestionsLength === 0 || !['Tab', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
// Handle tabbing through suggestions.
|
|
121
|
+
if (event.key === 'Tab' && suggestionsLength > 0) {
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
if (event.shiftKey) {
|
|
124
|
+
// Shift + tab goes up.
|
|
125
|
+
highlightPrevious();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Just tab goes down.
|
|
129
|
+
highlightNext();
|
|
130
|
+
}
|
|
131
|
+
// Up arrow highlights previous suggestions.
|
|
132
|
+
if (event.key === 'ArrowUp') {
|
|
133
|
+
highlightPrevious();
|
|
134
|
+
}
|
|
135
|
+
// Down arrow highlights next suggestions.
|
|
136
|
+
if (event.key === 'ArrowDown') {
|
|
137
|
+
highlightNext();
|
|
138
|
+
}
|
|
139
|
+
}, [suggestionsLength, highlightNext, highlightPrevious]);
|
|
140
|
+
useEffect(function () {
|
|
141
|
+
if (inputRef == null) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
inputRef.addEventListener('keydown', handleKeyDown);
|
|
145
|
+
inputRef.addEventListener('keypress', handleKeyPress);
|
|
146
|
+
return function () {
|
|
147
|
+
inputRef.removeEventListener('keydown', handleKeyDown);
|
|
148
|
+
inputRef.removeEventListener('keypress', handleKeyPress);
|
|
149
|
+
};
|
|
150
|
+
}, [inputRef, highlightedSuggestionIndex, suggestions, handleKeyPress, handleKeyDown]);
|
|
151
|
+
return (_jsx(_Fragment, { children: suggestionsLength > 0 && (_jsx("div", __assign({ ref: setPopperElement, style: __assign(__assign({}, styles.popper), { marginLeft: 0 }) }, attributes.popper, { className: "z-50" }, { children: _jsx(Transition, __assign({ show: focusedInput && showSuggest, as: Fragment, leave: "transition ease-in duration-100", leaveFrom: "opacity-100", leaveTo: "opacity-0" }, { children: _jsxs("div", __assign({ style: { width: inputRef === null || inputRef === void 0 ? void 0 : inputRef.offsetWidth }, className: "absolute z-10 max-h-[400px] mt-1 bg-gray-50 dark:bg-gray-900 shadow-lg rounded-md text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" }, { children: [isLabelNamesLoading ? (_jsx(LoadingSpinner, {})) : (_jsx(_Fragment, { children: suggestions.labelNames.map(function (l, i) { return (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex === i, onHighlight: function () { return setHighlightedSuggestionIndex(i); }, onApplySuggestion: function () { return applySuggestionWithIndex(i); }, onResetHighlight: function () { return resetHighlight(); }, value: l.value }, l.value)); }) })), suggestions.literals.map(function (l, i) { return (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex === i + suggestions.labelNames.length, onHighlight: function () {
|
|
152
|
+
return setHighlightedSuggestionIndex(i + suggestions.labelNames.length);
|
|
153
|
+
}, onApplySuggestion: function () {
|
|
154
|
+
return applySuggestionWithIndex(i + suggestions.labelNames.length);
|
|
155
|
+
}, onResetHighlight: function () { return resetHighlight(); }, value: l.value }, l.value)); }), isLabelValuesLoading ? (_jsx(LoadingSpinner, {})) : (_jsx(_Fragment, { children: suggestions.labelValues.map(function (l, i) { return (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
|
|
156
|
+
i + suggestions.labelNames.length + suggestions.literals.length, onHighlight: function () {
|
|
157
|
+
return setHighlightedSuggestionIndex(i + suggestions.labelNames.length + suggestions.literals.length);
|
|
158
|
+
}, onApplySuggestion: function () {
|
|
159
|
+
return applySuggestionWithIndex(i + suggestions.labelNames.length + suggestions.literals.length);
|
|
160
|
+
}, onResetHighlight: function () { return resetHighlight(); }, value: l.value }, l.value)); }) }))] })) })) }))) }));
|
|
161
|
+
};
|
|
162
|
+
export default SuggestionsList;
|
|
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
9
9
|
};
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx,
|
|
12
|
+
import { 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,13 +22,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
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 {
|
|
26
|
-
import
|
|
27
|
-
import { Query } from '@parca/parser';
|
|
28
|
-
import { usePopper } from 'react-popper';
|
|
25
|
+
import { useState, useEffect, useMemo, useRef } from 'react';
|
|
26
|
+
import TextareaAutosize from 'react-textarea-autosize';
|
|
29
27
|
import cx from 'classnames';
|
|
30
|
-
import {
|
|
31
|
-
import
|
|
28
|
+
import { useGrpcMetadata } from '@parca/components';
|
|
29
|
+
import { sanitizeLabelValue } from '@parca/functions';
|
|
30
|
+
import { Query } from '@parca/parser';
|
|
31
|
+
import SuggestionsList, { Suggestion, Suggestions } from './SuggestionsList';
|
|
32
32
|
export var useLabelNames = function (client) {
|
|
33
33
|
var _a = useState(true), loading = _a[0], setLoading = _a[1];
|
|
34
34
|
var _b = useState({}), result = _b[0], setResult = _b[1];
|
|
@@ -43,202 +43,108 @@ export var useLabelNames = function (client) {
|
|
|
43
43
|
}, [client, metadata]);
|
|
44
44
|
return { result: result, loading: loading };
|
|
45
45
|
};
|
|
46
|
-
var Suggestion = /** @class */ (function () {
|
|
47
|
-
function Suggestion(type, typeahead, value) {
|
|
48
|
-
this.type = type;
|
|
49
|
-
this.typeahead = typeahead;
|
|
50
|
-
this.value = value;
|
|
51
|
-
}
|
|
52
|
-
return Suggestion;
|
|
53
|
-
}());
|
|
54
|
-
var Suggestions = /** @class */ (function () {
|
|
55
|
-
function Suggestions() {
|
|
56
|
-
this.literals = [];
|
|
57
|
-
this.labelNames = [];
|
|
58
|
-
this.labelValues = [];
|
|
59
|
-
}
|
|
60
|
-
return Suggestions;
|
|
61
|
-
}());
|
|
62
46
|
var MatchersInput = function (_a) {
|
|
63
47
|
var queryClient = _a.queryClient, setMatchersString = _a.setMatchersString, runQuery = _a.runQuery, currentQuery = _a.currentQuery;
|
|
64
|
-
var
|
|
65
|
-
var
|
|
66
|
-
var
|
|
67
|
-
var
|
|
68
|
-
var
|
|
69
|
-
var
|
|
70
|
-
var _h = useState(null), popperElement = _h[0], setPopperElement = _h[1];
|
|
71
|
-
var _j = useState(null), labelValues = _j[0], setLabelValues = _j[1];
|
|
72
|
-
var _k = useState(null), currentLabelName = _k[0], setCurrentLabelName = _k[1];
|
|
73
|
-
var _l = usePopper(inputRef, popperElement, {
|
|
74
|
-
placement: 'bottom-start',
|
|
75
|
-
}), styles = _l.styles, attributes = _l.attributes;
|
|
48
|
+
var inputRef = useRef(null);
|
|
49
|
+
var _b = useState(false), focusedInput = _b[0], setFocusedInput = _b[1];
|
|
50
|
+
var _c = useState(false), labelValuesLoading = _c[0], setLabelValuesLoading = _c[1];
|
|
51
|
+
var _d = useState(new Suggestion('', '', '')), lastCompleted = _d[0], setLastCompleted = _d[1];
|
|
52
|
+
var _e = useState(null), labelValues = _e[0], setLabelValues = _e[1];
|
|
53
|
+
var _f = useState(null), currentLabelName = _f[0], setCurrentLabelName = _f[1];
|
|
76
54
|
var metadata = useGrpcMetadata();
|
|
77
|
-
var
|
|
78
|
-
var _m = useLabelNames(queryClient), labelNamesLoading = _m.loading, result = _m.result;
|
|
55
|
+
var _g = useLabelNames(queryClient), labelNamesLoading = _g.loading, result = _g.result;
|
|
79
56
|
var labelNamesResponse = result.response, labelNamesError = result.error;
|
|
80
|
-
var LoadingSpinner = function () {
|
|
81
|
-
return _jsx("div", __assign({ className: "pt-2 pb-4" }, { children: Spinner }));
|
|
82
|
-
};
|
|
83
57
|
useEffect(function () {
|
|
84
58
|
if (currentLabelName !== null) {
|
|
85
59
|
var call = queryClient.values({ labelName: currentLabelName, match: [] }, { meta: metadata });
|
|
86
60
|
setLabelValuesLoading(true);
|
|
87
61
|
call.response
|
|
88
62
|
.then(function (response) {
|
|
89
|
-
|
|
63
|
+
// replace single `\` in the `labelValues` string with doubles `\\` if available.
|
|
64
|
+
var newValues = sanitizeLabelValue(response.labelValues);
|
|
65
|
+
setLabelValues(newValues);
|
|
90
66
|
})
|
|
91
67
|
.catch(function () { return setLabelValues(null); })
|
|
92
68
|
.finally(function () { return setLabelValuesLoading(false); });
|
|
93
69
|
}
|
|
94
70
|
}, [currentLabelName, queryClient, metadata]);
|
|
95
|
-
var labelNames = (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
71
|
+
var labelNames = useMemo(function () {
|
|
72
|
+
return (labelNamesError === undefined || labelNamesError == null) &&
|
|
73
|
+
labelNamesResponse !== undefined &&
|
|
74
|
+
labelNamesResponse != null
|
|
75
|
+
? labelNamesResponse.labelNames.filter(function (e) { return e !== '__name__'; })
|
|
76
|
+
: [];
|
|
77
|
+
}, [labelNamesError, labelNamesResponse]);
|
|
100
78
|
var value = currentQuery.matchersString();
|
|
101
|
-
var suggestionSections =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
typeahead: s.typeahead,
|
|
116
|
-
value: s.value,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if (s.type === 'labelName') {
|
|
120
|
-
var inputValue_1 = s.typeahead.trim().toLowerCase();
|
|
121
|
-
var inputLength_1 = inputValue_1.length;
|
|
122
|
-
var matches = labelNames.filter(function (label) {
|
|
123
|
-
return label.toLowerCase().slice(0, inputLength_1) === inputValue_1;
|
|
124
|
-
});
|
|
125
|
-
matches.forEach(function (m) {
|
|
126
|
-
return suggestionSections.labelNames.push({
|
|
79
|
+
var suggestionSections = useMemo(function () {
|
|
80
|
+
var suggestionSections = new Suggestions();
|
|
81
|
+
Query.suggest("".concat(currentQuery.profileName(), "{").concat(value)).forEach(function (s) {
|
|
82
|
+
// Skip suggestions that we just completed. This really only works,
|
|
83
|
+
// because we know the language is not repetitive. For a language that
|
|
84
|
+
// has a repeating word, this would not work.
|
|
85
|
+
if (lastCompleted !== null && lastCompleted.type === s.type) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Need to figure out if any literal suggestions make sense, but a
|
|
89
|
+
// closing bracket doesn't in the guided query experience because all
|
|
90
|
+
// we have the user do is type the matchers.
|
|
91
|
+
if (s.type === 'literal' && s.value !== '}') {
|
|
92
|
+
suggestionSections.literals.push({
|
|
127
93
|
type: s.type,
|
|
128
94
|
typeahead: s.typeahead,
|
|
129
|
-
value:
|
|
95
|
+
value: s.value,
|
|
130
96
|
});
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
if (s.type === 'labelValue') {
|
|
134
|
-
if (currentLabelName === null || s.labelName !== currentLabelName) {
|
|
135
|
-
setCurrentLabelName(s.labelName);
|
|
136
|
-
return;
|
|
137
97
|
}
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return
|
|
98
|
+
if (s.type === 'labelName') {
|
|
99
|
+
var inputValue_1 = s.typeahead.trim().toLowerCase();
|
|
100
|
+
var inputLength_1 = inputValue_1.length;
|
|
101
|
+
var matches = labelNames.filter(function (label) {
|
|
102
|
+
return label.toLowerCase().slice(0, inputLength_1) === inputValue_1;
|
|
103
|
+
});
|
|
104
|
+
matches.forEach(function (m) {
|
|
105
|
+
return suggestionSections.labelNames.push({
|
|
143
106
|
type: s.type,
|
|
144
107
|
typeahead: s.typeahead,
|
|
145
|
-
value:
|
|
108
|
+
value: m,
|
|
146
109
|
});
|
|
147
110
|
});
|
|
148
111
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
112
|
+
if (s.type === 'labelValue') {
|
|
113
|
+
if (currentLabelName === null || s.labelName !== currentLabelName) {
|
|
114
|
+
setCurrentLabelName(s.labelName);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (labelValues !== null) {
|
|
118
|
+
labelValues
|
|
119
|
+
.filter(function (v) { return v.slice(0, s.typeahead.length) === s.typeahead; })
|
|
120
|
+
.forEach(function (v) {
|
|
121
|
+
return suggestionSections.labelValues.push({
|
|
122
|
+
type: s.type,
|
|
123
|
+
typeahead: s.typeahead,
|
|
124
|
+
value: v,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return suggestionSections;
|
|
131
|
+
}, [currentQuery, lastCompleted, labelNames, labelValues, currentLabelName, value]);
|
|
155
132
|
var resetLastCompleted = function () { return setLastCompleted(new Suggestion('', '', '')); };
|
|
156
133
|
var onChange = function (e) {
|
|
157
134
|
var newValue = e.target.value;
|
|
158
135
|
setMatchersString(newValue);
|
|
159
136
|
resetLastCompleted();
|
|
160
|
-
resetHighlight();
|
|
161
137
|
};
|
|
162
138
|
var complete = function (suggestion) {
|
|
163
139
|
return value.slice(0, value.length - suggestion.typeahead.length) + suggestion.value;
|
|
164
140
|
};
|
|
165
|
-
var
|
|
166
|
-
if (index < suggestionSections.labelNames.length) {
|
|
167
|
-
return suggestionSections.labelNames[index];
|
|
168
|
-
}
|
|
169
|
-
if (index < suggestionSections.labelNames.length + suggestionSections.literals.length) {
|
|
170
|
-
return suggestionSections.literals[index - suggestionSections.labelNames.length];
|
|
171
|
-
}
|
|
172
|
-
return suggestionSections.labelValues[index - suggestionSections.labelNames.length - suggestionSections.literals.length];
|
|
173
|
-
};
|
|
174
|
-
var highlightNext = function () {
|
|
175
|
-
var nextIndex = highlightedSuggestionIndex + 1;
|
|
176
|
-
if (nextIndex === suggestionsLength) {
|
|
177
|
-
resetHighlight();
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
setHighlightedSuggestionIndex(nextIndex);
|
|
181
|
-
};
|
|
182
|
-
var highlightPrevious = function () {
|
|
183
|
-
if (highlightedSuggestionIndex === -1) {
|
|
184
|
-
// Didn't select anything, so starting at the bottom.
|
|
185
|
-
setHighlightedSuggestionIndex(suggestionsLength - 1);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
setHighlightedSuggestionIndex(highlightedSuggestionIndex - 1);
|
|
189
|
-
};
|
|
190
|
-
var applySuggestion = function (suggestionIndex) {
|
|
191
|
-
var suggestion = getSuggestion(suggestionIndex);
|
|
141
|
+
var applySuggestion = function (suggestion) {
|
|
192
142
|
var newValue = complete(suggestion);
|
|
193
|
-
resetHighlight();
|
|
194
143
|
setLastCompleted(suggestion);
|
|
195
144
|
setMatchersString(newValue);
|
|
196
|
-
if (inputRef !== null) {
|
|
197
|
-
inputRef.value = newValue;
|
|
198
|
-
inputRef.focus();
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
var applyHighlightedSuggestion = function () {
|
|
202
|
-
applySuggestion(highlightedSuggestionIndex);
|
|
203
|
-
};
|
|
204
|
-
var handleKeyPress = function (event) {
|
|
205
|
-
// If there is a highlighted suggestion and enter is hit, we complete
|
|
206
|
-
// with the highlighted suggestion.
|
|
207
|
-
if (highlightedSuggestionIndex >= 0 && event.key === 'Enter') {
|
|
208
|
-
applyHighlightedSuggestion();
|
|
209
|
-
}
|
|
210
|
-
// If no suggestions is highlighted and we hit enter, we run the query,
|
|
211
|
-
// and hide suggestions until another actions enables them again.
|
|
212
|
-
if (highlightedSuggestionIndex === -1 && event.key === 'Enter') {
|
|
213
|
-
setShowSuggest(false);
|
|
214
|
-
runQuery();
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
setShowSuggest(true);
|
|
218
|
-
};
|
|
219
|
-
var handleKeyDown = function (event) {
|
|
220
|
-
// Don't need to handle any key interactions if no suggestions there.
|
|
221
|
-
if (suggestionsLength === 0) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
// Handle tabbing through suggestions.
|
|
225
|
-
if (event.key === 'Tab' && suggestionsLength > 0) {
|
|
226
|
-
event.preventDefault();
|
|
227
|
-
if (event.shiftKey) {
|
|
228
|
-
// Shift + tab goes up.
|
|
229
|
-
highlightPrevious();
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
// Just tab goes down.
|
|
233
|
-
highlightNext();
|
|
234
|
-
}
|
|
235
|
-
// Up arrow highlights previous suggestions.
|
|
236
|
-
if (event.key === 'ArrowUp') {
|
|
237
|
-
highlightPrevious();
|
|
238
|
-
}
|
|
239
|
-
// Down arrow highlights next suggestions.
|
|
240
|
-
if (event.key === 'ArrowDown') {
|
|
241
|
-
highlightNext();
|
|
145
|
+
if (inputRef.current !== null) {
|
|
146
|
+
inputRef.current.value = newValue;
|
|
147
|
+
inputRef.current.focus();
|
|
242
148
|
}
|
|
243
149
|
};
|
|
244
150
|
var focus = function () {
|
|
@@ -246,28 +152,12 @@ var MatchersInput = function (_a) {
|
|
|
246
152
|
};
|
|
247
153
|
var unfocus = function () {
|
|
248
154
|
setFocusedInput(false);
|
|
249
|
-
resetHighlight();
|
|
250
155
|
};
|
|
251
156
|
var profileSelected = currentQuery.profileName() === '';
|
|
252
|
-
return (_jsxs("div", __assign({ className: "font-mono flex-1 w-full block" }, { children: [_jsx(
|
|
157
|
+
return (_jsxs("div", __assign({ className: "font-mono flex-1 w-full block" }, { children: [_jsx(TextareaAutosize, { ref: inputRef, className: cx('bg-gray-50 dark:bg-gray-900 focus:ring-indigo-800 flex-1 block w-full px-2 py-2 text-sm outline-none rounded', profileSelected && 'cursor-not-allowed'), placeholder: profileSelected
|
|
253
158
|
? 'Select a profile first to enter a filter...'
|
|
254
|
-
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, onFocus: focus,
|
|
159
|
+
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, onFocus: focus, disabled: profileSelected, title: profileSelected
|
|
255
160
|
? 'Select a profile first to enter a filter...'
|
|
256
|
-
: 'filter profiles... eg. node="test"' }),
|
|
257
|
-
return setHighlightedSuggestionIndex(i + suggestionSections.labelNames.length);
|
|
258
|
-
}, onApplySuggestion: function () {
|
|
259
|
-
return applySuggestion(i + suggestionSections.labelNames.length);
|
|
260
|
-
}, onResetHighlight: function () { return resetHighlight(); }, value: l.value }, l.value)); }), labelValuesLoading && lastCompleted.type === 'literal' ? (_jsx(LoadingSpinner, {})) : (_jsx(_Fragment, { children: suggestionSections.labelValues.map(function (l, i) { return (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
|
|
261
|
-
i +
|
|
262
|
-
suggestionSections.labelNames.length +
|
|
263
|
-
suggestionSections.literals.length, onHighlight: function () {
|
|
264
|
-
return setHighlightedSuggestionIndex(i +
|
|
265
|
-
suggestionSections.labelNames.length +
|
|
266
|
-
suggestionSections.literals.length);
|
|
267
|
-
}, onApplySuggestion: function () {
|
|
268
|
-
return applySuggestion(i +
|
|
269
|
-
suggestionSections.labelNames.length +
|
|
270
|
-
suggestionSections.literals.length);
|
|
271
|
-
}, onResetHighlight: function () { return resetHighlight(); }, value: l.value }, l.value)); }) }))] })) })) })))] })));
|
|
161
|
+
: 'filter profiles... eg. node="test"' }), _jsx(SuggestionsList, { isLabelNamesLoading: labelNamesLoading, suggestions: suggestionSections, applySuggestion: applySuggestion, inputRef: inputRef.current, runQuery: runQuery, focusedInput: focusedInput, isLabelValuesLoading: labelValuesLoading && lastCompleted.type === 'literal' })] })));
|
|
272
162
|
};
|
|
273
163
|
export default MatchersInput;
|
|
@@ -41,7 +41,7 @@ import { timeFormat } from '..';
|
|
|
41
41
|
import { cutToMaxStringLength } from '@parca/functions/string';
|
|
42
42
|
import throttle from 'lodash.throttle';
|
|
43
43
|
import { usePopper } from 'react-popper';
|
|
44
|
-
import { valueFormatter, formatDate } from '@parca/functions';
|
|
44
|
+
import { valueFormatter, formatDate, sanitizeHighlightedValues } from '@parca/functions';
|
|
45
45
|
import { DateTimeRange } from '@parca/components';
|
|
46
46
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
47
47
|
import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
|
|
@@ -226,7 +226,8 @@ export var RawMetricsGraph = function (_a) {
|
|
|
226
226
|
};
|
|
227
227
|
var openClosestProfile = function () {
|
|
228
228
|
if (highlighted != null) {
|
|
229
|
-
onSampleClick(Math.round(highlighted.timestamp), highlighted.value, highlighted.labels)
|
|
229
|
+
onSampleClick(Math.round(highlighted.timestamp), highlighted.value, sanitizeHighlightedValues(highlighted.labels) // When a user clicks on any sample in the graph, replace single `\` in the `labelValues` string with doubles `\\` if available.
|
|
230
|
+
);
|
|
230
231
|
}
|
|
231
232
|
};
|
|
232
233
|
var onMouseUp = function (e) {
|