@parca/profile 0.19.43 → 0.19.45
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/GraphTooltipArrow/Content.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/Content.js +1 -1
- package/dist/MetricsGraph/MetricsContextMenu/index.d.ts +20 -11
- package/dist/MetricsGraph/MetricsContextMenu/index.d.ts.map +1 -1
- package/dist/MetricsGraph/MetricsContextMenu/index.js +16 -20
- package/dist/MetricsGraph/MetricsTooltip/index.d.ts +2 -8
- package/dist/MetricsGraph/MetricsTooltip/index.d.ts.map +1 -1
- package/dist/MetricsGraph/MetricsTooltip/index.js +46 -55
- package/dist/MetricsGraph/UtilizationMetrics/Throughput.d.ts +2 -5
- package/dist/MetricsGraph/UtilizationMetrics/Throughput.d.ts.map +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/Throughput.js +126 -205
- package/dist/MetricsGraph/UtilizationMetrics/index.d.ts +9 -17
- package/dist/MetricsGraph/UtilizationMetrics/index.d.ts.map +1 -1
- package/dist/MetricsGraph/UtilizationMetrics/index.js +149 -208
- package/dist/MetricsGraph/index.d.ts +19 -26
- package/dist/MetricsGraph/index.d.ts.map +1 -1
- package/dist/MetricsGraph/index.js +50 -115
- package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/index.js +3 -1
- package/dist/ProfileMetricsGraph/index.d.ts +1 -1
- package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
- package/dist/ProfileMetricsGraph/index.js +232 -23
- package/dist/ProfileSelector/MetricsGraphSection.d.ts +1 -4
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +8 -4
- package/dist/ProfileSelector/QueryControls.d.ts.map +1 -1
- package/dist/ProfileSelector/QueryControls.js +3 -2
- package/dist/ProfileSelector/index.d.ts +3 -6
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +2 -2
- package/dist/ProfileSource.d.ts +9 -6
- package/dist/ProfileSource.d.ts.map +1 -1
- package/dist/ProfileSource.js +23 -8
- package/dist/styles.css +1 -1
- package/dist/useQuery.js +1 -1
- package/package.json +6 -6
- package/src/GraphTooltipArrow/Content.tsx +2 -4
- package/src/MetricsGraph/MetricsContextMenu/index.tsx +78 -66
- package/src/MetricsGraph/MetricsTooltip/index.tsx +53 -210
- package/src/MetricsGraph/UtilizationMetrics/Throughput.tsx +242 -434
- package/src/MetricsGraph/UtilizationMetrics/index.tsx +312 -448
- package/src/MetricsGraph/index.tsx +99 -185
- package/src/ProfileFlameGraph/index.tsx +3 -1
- package/src/ProfileMetricsGraph/index.tsx +430 -37
- package/src/ProfileSelector/MetricsGraphSection.tsx +12 -8
- package/src/ProfileSelector/QueryControls.tsx +4 -1
- package/src/ProfileSelector/index.tsx +5 -5
- package/src/ProfileSource.tsx +34 -17
- package/src/useQuery.tsx +1 -1
|
@@ -13,262 +13,105 @@
|
|
|
13
13
|
|
|
14
14
|
import {useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
|
-
import {Icon} from '@iconify/react';
|
|
17
|
-
import type {VirtualElement} from '@popperjs/core';
|
|
18
16
|
import {usePopper} from 'react-popper';
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
import {HighlightedSeries} from '../';
|
|
18
|
+
interface VirtualElement {
|
|
19
|
+
getBoundingClientRect: () => DOMRect;
|
|
20
|
+
}
|
|
25
21
|
|
|
26
22
|
interface Props {
|
|
27
23
|
x: number;
|
|
28
24
|
y: number;
|
|
29
|
-
highlighted: HighlightedSeries;
|
|
30
25
|
contextElement: Element | null;
|
|
31
|
-
|
|
32
|
-
sampleUnit: string;
|
|
33
|
-
delta: boolean;
|
|
34
|
-
utilizationMetrics?: boolean;
|
|
35
|
-
valuePrefix?: string;
|
|
26
|
+
content: React.ReactNode;
|
|
36
27
|
}
|
|
37
28
|
|
|
38
29
|
const virtualElement: VirtualElement = {
|
|
39
30
|
getBoundingClientRect: () => {
|
|
40
|
-
|
|
41
|
-
return {
|
|
31
|
+
const emptyRect: DOMRect = {
|
|
42
32
|
width: 0,
|
|
43
33
|
height: 0,
|
|
44
34
|
top: 0,
|
|
45
|
-
left: 0,
|
|
46
35
|
right: 0,
|
|
47
36
|
bottom: 0,
|
|
48
|
-
|
|
37
|
+
left: 0,
|
|
38
|
+
x: 0,
|
|
39
|
+
y: 0,
|
|
40
|
+
toJSON: () => ({}),
|
|
41
|
+
};
|
|
42
|
+
return emptyRect;
|
|
49
43
|
},
|
|
50
44
|
};
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
const domRect =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const MetricsTooltip = ({
|
|
67
|
-
x,
|
|
68
|
-
y,
|
|
69
|
-
highlighted,
|
|
70
|
-
contextElement,
|
|
71
|
-
sampleType,
|
|
72
|
-
sampleUnit,
|
|
73
|
-
delta,
|
|
74
|
-
utilizationMetrics = false,
|
|
75
|
-
valuePrefix,
|
|
76
|
-
}: Props): JSX.Element => {
|
|
77
|
-
const {timezone} = useParcaContext();
|
|
46
|
+
const createDomRect = (x: number, y: number): DOMRect => {
|
|
47
|
+
const domRect: DOMRect = {
|
|
48
|
+
width: 0,
|
|
49
|
+
height: 0,
|
|
50
|
+
top: y,
|
|
51
|
+
right: x,
|
|
52
|
+
bottom: y,
|
|
53
|
+
left: x,
|
|
54
|
+
x,
|
|
55
|
+
y,
|
|
56
|
+
toJSON: () => ({}),
|
|
57
|
+
};
|
|
58
|
+
return domRect;
|
|
59
|
+
};
|
|
78
60
|
|
|
61
|
+
const MetricsTooltip = ({x, y, contextElement, content}: Props): JSX.Element => {
|
|
79
62
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
80
63
|
|
|
81
|
-
const {styles, attributes,
|
|
64
|
+
const {styles, attributes, update} = usePopper(virtualElement, popperElement, {
|
|
82
65
|
placement: 'auto-start',
|
|
83
66
|
strategy: 'absolute',
|
|
84
67
|
modifiers: [
|
|
85
68
|
{
|
|
86
69
|
name: 'preventOverflow',
|
|
87
70
|
options: {
|
|
88
|
-
|
|
89
|
-
altAxis: true,
|
|
71
|
+
boundary: contextElement ?? undefined,
|
|
90
72
|
},
|
|
91
73
|
},
|
|
92
74
|
{
|
|
93
75
|
name: 'offset',
|
|
94
76
|
options: {
|
|
95
|
-
offset: [
|
|
77
|
+
offset: [15, 15],
|
|
96
78
|
},
|
|
97
79
|
},
|
|
98
80
|
],
|
|
99
81
|
});
|
|
100
82
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return highlighted.labels
|
|
118
|
-
.filter(label => label.name.startsWith('attributes_resource.'))
|
|
119
|
-
.reduce<Record<string, string>>((acc, label) => {
|
|
120
|
-
const key = label.name.replace('attributes_resource.', '');
|
|
121
|
-
acc[key] = label.value;
|
|
122
|
-
return acc;
|
|
123
|
-
}, {});
|
|
124
|
-
}, [highlighted.labels]);
|
|
83
|
+
useMemo(() => {
|
|
84
|
+
virtualElement.getBoundingClientRect = (): DOMRect => {
|
|
85
|
+
const domRect: DOMRect = (contextElement as Element)?.getBoundingClientRect() ?? {
|
|
86
|
+
width: 0,
|
|
87
|
+
height: 0,
|
|
88
|
+
top: 0,
|
|
89
|
+
right: 0,
|
|
90
|
+
bottom: 0,
|
|
91
|
+
left: 0,
|
|
92
|
+
x: 0,
|
|
93
|
+
y: 0,
|
|
94
|
+
toJSON: () => ({}),
|
|
95
|
+
};
|
|
96
|
+
return createDomRect(domRect.x + x, domRect.y + y);
|
|
97
|
+
};
|
|
98
|
+
}, [x, y, contextElement]);
|
|
125
99
|
|
|
126
100
|
useEffect(() => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
void update?.();
|
|
130
|
-
}
|
|
131
|
-
}, [x, y, contextElement, update]);
|
|
101
|
+
void update?.();
|
|
102
|
+
}, [x, y, update]);
|
|
132
103
|
|
|
133
|
-
|
|
134
|
-
|
|
104
|
+
// Don't render anything if content is null or undefined
|
|
105
|
+
if (content == null) {
|
|
106
|
+
return <></>;
|
|
107
|
+
}
|
|
135
108
|
|
|
136
109
|
return (
|
|
137
110
|
<div ref={setPopperElement} style={styles.popper} {...attributes.popper} className="z-50">
|
|
138
111
|
<div className="flex max-w-lg">
|
|
139
112
|
<div className="m-auto">
|
|
140
|
-
<div
|
|
141
|
-
|
|
142
|
-
style={{borderWidth: 1}}
|
|
143
|
-
>
|
|
144
|
-
<div className="flex flex-row">
|
|
145
|
-
<div className="ml-2 mr-6">
|
|
146
|
-
<span className="font-semibold">{highlightedNameLabel.value}</span>
|
|
147
|
-
<span className="my-2 block text-gray-700 dark:text-gray-300">
|
|
148
|
-
<table className="table-auto">
|
|
149
|
-
<tbody>
|
|
150
|
-
{delta ? (
|
|
151
|
-
<>
|
|
152
|
-
<tr>
|
|
153
|
-
<td className="w-1/4 pr-3">Per Second</td>
|
|
154
|
-
<td className="w-3/4">
|
|
155
|
-
{valueFormatter(
|
|
156
|
-
highlighted.valuePerSecond,
|
|
157
|
-
sampleUnit === 'nanoseconds' && sampleType === 'cpu'
|
|
158
|
-
? 'CPU Cores'
|
|
159
|
-
: sampleUnit,
|
|
160
|
-
5
|
|
161
|
-
)}
|
|
162
|
-
</td>
|
|
163
|
-
</tr>
|
|
164
|
-
<tr>
|
|
165
|
-
<td className="w-1/4">Total</td>
|
|
166
|
-
<td className="w-3/4">
|
|
167
|
-
{valueFormatter(highlighted.value, sampleUnit, 2)}
|
|
168
|
-
</td>
|
|
169
|
-
</tr>
|
|
170
|
-
</>
|
|
171
|
-
) : (
|
|
172
|
-
<tr>
|
|
173
|
-
<td className="w-1/4">
|
|
174
|
-
{valuePrefix ?? ''}
|
|
175
|
-
Value
|
|
176
|
-
</td>
|
|
177
|
-
<td className="w-3/4">
|
|
178
|
-
{valueFormatter(highlighted.valuePerSecond, sampleUnit, 5)}
|
|
179
|
-
</td>
|
|
180
|
-
</tr>
|
|
181
|
-
)}
|
|
182
|
-
{highlighted.duration > 0 && (
|
|
183
|
-
<tr>
|
|
184
|
-
<td className="w-1/4">Duration</td>
|
|
185
|
-
<td className="w-3/4">
|
|
186
|
-
{valueFormatter(highlighted.duration, 'nanoseconds', 2)}
|
|
187
|
-
</td>
|
|
188
|
-
</tr>
|
|
189
|
-
)}
|
|
190
|
-
<tr>
|
|
191
|
-
<td className="w-1/4">At</td>
|
|
192
|
-
<td className="w-3/4">
|
|
193
|
-
{formatDate(
|
|
194
|
-
highlighted.timestamp,
|
|
195
|
-
timePattern(timezone as string),
|
|
196
|
-
timezone
|
|
197
|
-
)}
|
|
198
|
-
</td>
|
|
199
|
-
</tr>
|
|
200
|
-
</tbody>
|
|
201
|
-
</table>
|
|
202
|
-
</span>
|
|
203
|
-
<span className="my-2 block text-gray-500">
|
|
204
|
-
{utilizationMetrics ? (
|
|
205
|
-
<>
|
|
206
|
-
{Object.keys(attributesResourceMap).length > 0 && (
|
|
207
|
-
<span className="text-sm font-bold text-gray-700 dark:text-white">
|
|
208
|
-
Resource Attributes
|
|
209
|
-
</span>
|
|
210
|
-
)}
|
|
211
|
-
<span className="my-2 block text-gray-500">
|
|
212
|
-
{Object.keys(attributesResourceMap).map(name => (
|
|
213
|
-
<div
|
|
214
|
-
key={name}
|
|
215
|
-
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"
|
|
216
|
-
>
|
|
217
|
-
<TextWithTooltip
|
|
218
|
-
text={`${name.replace('attributes.', '')}="${
|
|
219
|
-
attributesResourceMap[name]
|
|
220
|
-
}"`}
|
|
221
|
-
maxTextLength={48}
|
|
222
|
-
id={`tooltip-${name}-${attributesResourceMap[name]}`}
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
))}
|
|
226
|
-
</span>
|
|
227
|
-
{Object.keys(attributesMap).length > 0 && (
|
|
228
|
-
<span className="text-sm font-bold text-gray-700 dark:text-white">
|
|
229
|
-
Attributes
|
|
230
|
-
</span>
|
|
231
|
-
)}
|
|
232
|
-
<span className="my-2 block text-gray-500">
|
|
233
|
-
{Object.keys(attributesMap).map(name => (
|
|
234
|
-
<div
|
|
235
|
-
key={name}
|
|
236
|
-
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"
|
|
237
|
-
>
|
|
238
|
-
<TextWithTooltip
|
|
239
|
-
text={`${name.replace('attributes.', '')}="${attributesMap[name]}"`}
|
|
240
|
-
maxTextLength={48}
|
|
241
|
-
id={`tooltip-${name}-${attributesMap[name]}`}
|
|
242
|
-
/>
|
|
243
|
-
</div>
|
|
244
|
-
))}
|
|
245
|
-
</span>
|
|
246
|
-
</>
|
|
247
|
-
) : (
|
|
248
|
-
<>
|
|
249
|
-
{highlighted.labels
|
|
250
|
-
.filter((label: Label) => label.name !== '__name__')
|
|
251
|
-
.map((label: Label) => (
|
|
252
|
-
<div
|
|
253
|
-
key={label.name}
|
|
254
|
-
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"
|
|
255
|
-
>
|
|
256
|
-
<TextWithTooltip
|
|
257
|
-
text={`${label.name}="${label.value}"`}
|
|
258
|
-
maxTextLength={37}
|
|
259
|
-
id={`tooltip-${label.name}`}
|
|
260
|
-
/>
|
|
261
|
-
</div>
|
|
262
|
-
))}
|
|
263
|
-
</>
|
|
264
|
-
)}
|
|
265
|
-
</span>
|
|
266
|
-
<div className="flex w-full items-center gap-1 text-xs text-gray-500">
|
|
267
|
-
<Icon icon="iconoir:mouse-button-right" />
|
|
268
|
-
<div>Right click to add labels to query.</div>
|
|
269
|
-
</div>
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
113
|
+
<div className="border border-gray-300 bg-gray-50 dark:border-gray-500 dark:bg-gray-900 rounded-lg shadow-lg px-3 py-2">
|
|
114
|
+
{content}
|
|
272
115
|
</div>
|
|
273
116
|
</div>
|
|
274
117
|
</div>
|