@parca/profile 0.19.81 → 0.19.82

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/MatchersInput/index.d.ts +2 -34
  3. package/dist/MatchersInput/index.d.ts.map +1 -1
  4. package/dist/MatchersInput/index.js +14 -91
  5. package/dist/MetricsGraph/index.d.ts.map +1 -1
  6. package/dist/MetricsGraph/index.js +13 -1
  7. package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
  8. package/dist/ProfileMetricsGraph/index.js +6 -29
  9. package/dist/ProfileSelector/MetricsGraphSection.d.ts +2 -9
  10. package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
  11. package/dist/ProfileSelector/MetricsGraphSection.js +3 -38
  12. package/dist/ProfileSelector/index.d.ts +1 -29
  13. package/dist/ProfileSelector/index.d.ts.map +1 -1
  14. package/dist/ProfileSelector/index.js +12 -9
  15. package/dist/QueryControls/index.d.ts +42 -0
  16. package/dist/QueryControls/index.d.ts.map +1 -0
  17. package/dist/{ProfileSelector/QueryControls.js → QueryControls/index.js} +16 -13
  18. package/dist/SimpleMatchers/Select.js +1 -1
  19. package/dist/SimpleMatchers/index.d.ts +2 -11
  20. package/dist/SimpleMatchers/index.d.ts.map +1 -1
  21. package/dist/SimpleMatchers/index.js +34 -45
  22. package/dist/ViewMatchers/index.d.ts +0 -9
  23. package/dist/ViewMatchers/index.d.ts.map +1 -1
  24. package/dist/ViewMatchers/index.js +20 -12
  25. package/dist/contexts/LabelsQueryProvider.d.ts +35 -0
  26. package/dist/contexts/LabelsQueryProvider.d.ts.map +1 -0
  27. package/dist/contexts/LabelsQueryProvider.js +70 -0
  28. package/dist/contexts/UnifiedLabelsContext.d.ts +37 -0
  29. package/dist/contexts/UnifiedLabelsContext.d.ts.map +1 -0
  30. package/dist/contexts/UnifiedLabelsContext.js +88 -0
  31. package/dist/contexts/utils.d.ts +10 -0
  32. package/dist/contexts/utils.d.ts.map +1 -0
  33. package/dist/contexts/utils.js +31 -0
  34. package/dist/hooks/useLabels.d.ts +23 -0
  35. package/dist/hooks/useLabels.d.ts.map +1 -0
  36. package/dist/hooks/useLabels.js +75 -0
  37. package/dist/hooks/useQueryState.d.ts +2 -0
  38. package/dist/hooks/useQueryState.d.ts.map +1 -1
  39. package/dist/hooks/useQueryState.js +18 -0
  40. package/dist/index.d.ts +9 -3
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +9 -3
  43. package/dist/styles.css +1 -1
  44. package/dist/useSumBy.js +1 -1
  45. package/package.json +2 -2
  46. package/src/MatchersInput/index.tsx +17 -163
  47. package/src/MetricsGraph/index.tsx +17 -1
  48. package/src/ProfileMetricsGraph/index.tsx +17 -98
  49. package/src/ProfileSelector/MetricsGraphSection.tsx +14 -115
  50. package/src/ProfileSelector/index.tsx +106 -109
  51. package/src/{ProfileSelector/QueryControls.tsx → QueryControls/index.tsx} +66 -84
  52. package/src/SimpleMatchers/Select.tsx +1 -1
  53. package/src/SimpleMatchers/index.tsx +46 -85
  54. package/src/ViewMatchers/index.tsx +22 -30
  55. package/src/contexts/LabelsQueryProvider.tsx +142 -0
  56. package/src/contexts/UnifiedLabelsContext.tsx +155 -0
  57. package/src/contexts/utils.ts +43 -0
  58. package/src/hooks/useLabels.ts +121 -0
  59. package/src/hooks/useQueryState.ts +25 -0
  60. package/src/index.tsx +29 -3
  61. package/src/useSumBy.ts +1 -1
  62. package/dist/MetricsGraph/UtilizationMetrics/Throughput.d.ts +0 -29
  63. package/dist/MetricsGraph/UtilizationMetrics/Throughput.d.ts.map +0 -1
  64. package/dist/MetricsGraph/UtilizationMetrics/Throughput.js +0 -175
  65. package/dist/MetricsGraph/UtilizationMetrics/index.d.ts +0 -28
  66. package/dist/MetricsGraph/UtilizationMetrics/index.d.ts.map +0 -1
  67. package/dist/MetricsGraph/UtilizationMetrics/index.js +0 -186
  68. package/dist/ProfileSelector/QueryControls.d.ts +0 -43
  69. package/dist/ProfileSelector/QueryControls.d.ts.map +0 -1
  70. package/dist/contexts/MatchersInputLabelsContext.d.ts +0 -29
  71. package/dist/contexts/MatchersInputLabelsContext.d.ts.map +0 -1
  72. package/dist/contexts/MatchersInputLabelsContext.js +0 -79
  73. package/dist/contexts/SimpleMatchersLabelContext.d.ts +0 -25
  74. package/dist/contexts/SimpleMatchersLabelContext.d.ts.map +0 -1
  75. package/dist/contexts/SimpleMatchersLabelContext.js +0 -115
  76. package/dist/contexts/UtilizationLabelsContext.d.ts +0 -15
  77. package/dist/contexts/UtilizationLabelsContext.d.ts.map +0 -1
  78. package/dist/contexts/UtilizationLabelsContext.js +0 -25
  79. package/src/MetricsGraph/UtilizationMetrics/Throughput.tsx +0 -405
  80. package/src/MetricsGraph/UtilizationMetrics/index.tsx +0 -426
  81. package/src/contexts/MatchersInputLabelsContext.tsx +0 -141
  82. package/src/contexts/SimpleMatchersLabelContext.tsx +0 -189
  83. package/src/contexts/UtilizationLabelsContext.tsx +0 -45
@@ -11,157 +11,19 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {useEffect, useMemo, useRef, useState} from 'react';
14
+ import React, {useMemo, useRef, useState} from 'react';
15
15
 
16
- import {useQuery} from '@tanstack/react-query';
17
16
  import cx from 'classnames';
18
17
  import TextareaAutosize from 'react-textarea-autosize';
19
18
 
20
- import {LabelsRequest, LabelsResponse, QueryServiceClient, ValuesRequest} from '@parca/client';
21
- import {useGrpcMetadata} from '@parca/components';
22
19
  import {Query} from '@parca/parser';
23
20
  import {TEST_IDS, testId} from '@parca/test-utils';
24
- import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
25
21
 
26
- import {UtilizationLabels} from '../ProfileSelector';
27
- import {LabelsProvider, useLabels} from '../contexts/MatchersInputLabelsContext';
28
- import useGrpcQuery from '../useGrpcQuery';
22
+ import {useUnifiedLabels} from '../contexts/UnifiedLabelsContext';
23
+ import {useQueryState} from '../hooks/useQueryState';
29
24
  import SuggestionsList, {Suggestion, Suggestions} from './SuggestionsList';
30
25
 
31
- interface MatchersInputProps {
32
- queryClient: QueryServiceClient;
33
- setMatchersString: (arg: string) => void;
34
- runQuery: () => void;
35
- currentQuery: Query;
36
- profileType: string;
37
- start?: number;
38
- end?: number;
39
- }
40
-
41
- export interface ILabelNamesResult {
42
- response?: LabelsResponse;
43
- error?: Error;
44
- }
45
-
46
- interface UseLabelNames {
47
- result: ILabelNamesResult;
48
- loading: boolean;
49
- refetch: () => Promise<void>;
50
- }
51
-
52
- export const useLabelNames = (
53
- client: QueryServiceClient,
54
- profileType: string,
55
- start?: number,
56
- end?: number,
57
- match?: string[]
58
- ): UseLabelNames => {
59
- const metadata = useGrpcMetadata();
60
-
61
- const {data, isLoading, error, refetch} = useGrpcQuery<LabelsResponse>({
62
- key: ['labelNames', profileType, match?.join(','), start, end],
63
- queryFn: async signal => {
64
- const request: LabelsRequest = {match: match !== undefined ? match : []};
65
- if (start !== undefined && end !== undefined) {
66
- request.start = millisToProtoTimestamp(start);
67
- request.end = millisToProtoTimestamp(end);
68
- }
69
- if (profileType !== undefined) {
70
- request.profileType = profileType;
71
- }
72
- const {response} = await client.labels(request, {meta: metadata, abort: signal});
73
- return response;
74
- },
75
- options: {
76
- enabled: profileType !== undefined && profileType !== '',
77
- keepPreviousData: false,
78
- },
79
- });
80
-
81
- useEffect(() => {
82
- console.log('Label names query result:', {data, error, isLoading});
83
- }, [data, error, isLoading]);
84
-
85
- return {
86
- result: {response: data, error: error as Error},
87
- loading: isLoading,
88
- refetch: async () => {
89
- await refetch();
90
- },
91
- };
92
- };
93
-
94
- interface UseLabelValues {
95
- result: {
96
- response: string[];
97
- error?: Error;
98
- };
99
- loading: boolean;
100
- refetch: () => Promise<void>;
101
- }
102
-
103
- export const useLabelValues = (
104
- client: QueryServiceClient,
105
- labelName: string,
106
- profileType: string,
107
- start?: number,
108
- end?: number
109
- ): UseLabelValues => {
110
- const metadata = useGrpcMetadata();
111
-
112
- const {data, isLoading, error, refetch} = useGrpcQuery<string[]>({
113
- key: ['labelValues', labelName, profileType, start, end],
114
- queryFn: async signal => {
115
- const request: ValuesRequest = {labelName, match: [], profileType};
116
- if (start !== undefined && end !== undefined) {
117
- request.start = millisToProtoTimestamp(start);
118
- request.end = millisToProtoTimestamp(end);
119
- }
120
- const {response} = await client.values(request, {meta: metadata, abort: signal});
121
- return sanitizeLabelValue(response.labelValues);
122
- },
123
- options: {
124
- enabled:
125
- profileType !== undefined &&
126
- profileType !== '' &&
127
- labelName !== undefined &&
128
- labelName !== '',
129
- keepPreviousData: false,
130
- },
131
- });
132
-
133
- console.log('Label values query result:', {data, error, isLoading, labelName});
134
-
135
- return {
136
- result: {response: data ?? [], error: error as Error},
137
- loading: isLoading,
138
- refetch: async () => {
139
- await refetch();
140
- },
141
- };
142
- };
143
-
144
- export const useFetchUtilizationLabelValues = (
145
- labelName: string,
146
- utilizationLabels?: UtilizationLabels
147
- ): string[] => {
148
- const {data} = useQuery({
149
- queryKey: ['utilizationLabelValues', labelName],
150
- queryFn: async () => {
151
- const result = await utilizationLabels?.utilizationFetchLabelValues?.(labelName);
152
- return result ?? [];
153
- },
154
- enabled: utilizationLabels?.utilizationFetchLabelValues != null && labelName !== '',
155
- });
156
-
157
- return data ?? [];
158
- };
159
-
160
- const MatchersInput = ({
161
- setMatchersString,
162
- runQuery,
163
- currentQuery,
164
- }: MatchersInputProps): JSX.Element => {
26
+ const MatchersInput = (): JSX.Element => {
165
27
  const inputRef = useRef<HTMLTextAreaElement | null>(null);
166
28
  const [focusedInput, setFocusedInput] = useState(false);
167
29
  const [lastCompleted, setLastCompleted] = useState<Suggestion>(new Suggestion('', '', ''));
@@ -169,7 +31,7 @@ const MatchersInput = ({
169
31
  const {
170
32
  labelNames,
171
33
  labelValues,
172
- labelNameMappings,
34
+ labelNameMappingsForMatchersInput: labelNameMappings,
173
35
  isLabelNamesLoading,
174
36
  isLabelValuesLoading,
175
37
  currentLabelName,
@@ -177,13 +39,16 @@ const MatchersInput = ({
177
39
  shouldHandlePrefixes,
178
40
  refetchLabelValues,
179
41
  refetchLabelNames,
180
- } = useLabels();
42
+ suffix,
43
+ } = useUnifiedLabels();
44
+
45
+ const {setDraftMatchers, commitDraft, draftParsedQuery} = useQueryState({suffix});
181
46
 
182
- const value = currentQuery.matchersString();
47
+ const value = draftParsedQuery != null ? draftParsedQuery.matchersString() : '';
183
48
 
184
49
  const suggestionSections = useMemo(() => {
185
50
  const suggestionSections = new Suggestions();
186
- Query.suggest(`${currentQuery.profileName()}{${value}`).forEach(function (s) {
51
+ Query.suggest(`${draftParsedQuery?.profileName() as string}{${value}`).forEach(function (s) {
187
52
  // Skip suggestions that we just completed. This really only works,
188
53
  // because we know the language is not repetitive. For a language that
189
54
  // has a repeating word, this would not work.
@@ -256,7 +121,7 @@ const MatchersInput = ({
256
121
  });
257
122
  return suggestionSections;
258
123
  }, [
259
- currentQuery,
124
+ draftParsedQuery,
260
125
  lastCompleted,
261
126
  labelNames,
262
127
  labelValues,
@@ -271,7 +136,7 @@ const MatchersInput = ({
271
136
 
272
137
  const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>): void => {
273
138
  const newValue = e.target.value;
274
- setMatchersString(newValue);
139
+ setDraftMatchers(newValue);
275
140
  resetLastCompleted();
276
141
  };
277
142
 
@@ -294,7 +159,7 @@ const MatchersInput = ({
294
159
  const applySuggestion = (suggestion: Suggestion): void => {
295
160
  const newValue = complete(suggestion);
296
161
  setLastCompleted(suggestion);
297
- setMatchersString(newValue);
162
+ setDraftMatchers(newValue);
298
163
  if (inputRef.current !== null) {
299
164
  inputRef.current.value = newValue;
300
165
  inputRef.current.focus();
@@ -309,7 +174,7 @@ const MatchersInput = ({
309
174
  setFocusedInput(false);
310
175
  };
311
176
 
312
- const profileSelected = currentQuery.profileName() === '';
177
+ const profileSelected = draftParsedQuery?.profileName() === '';
313
178
 
314
179
  return (
315
180
  <div
@@ -345,7 +210,7 @@ const MatchersInput = ({
345
210
  suggestions={suggestionSections}
346
211
  applySuggestion={applySuggestion}
347
212
  inputRef={inputRef.current}
348
- runQuery={runQuery}
213
+ runQuery={commitDraft}
349
214
  focusedInput={focusedInput}
350
215
  isLabelValuesLoading={
351
216
  isLabelValuesLoading && lastCompleted.type === 'literal' && lastCompleted.value !== ','
@@ -358,15 +223,4 @@ const MatchersInput = ({
358
223
  );
359
224
  };
360
225
 
361
- export default function MatchersInputWithProvider(props: MatchersInputProps): JSX.Element {
362
- return (
363
- <LabelsProvider
364
- queryClient={props.queryClient}
365
- profileType={props.profileType}
366
- start={props.start}
367
- end={props.end}
368
- >
369
- <MatchersInput {...props} />
370
- </LabelsProvider>
371
- );
372
- }
226
+ export default MatchersInput;
@@ -114,6 +114,7 @@ const MetricsGraph = ({
114
114
  };
115
115
 
116
116
  export default MetricsGraph;
117
+
117
118
  export type {ContextMenuItemOrSubmenu, ContextMenuItem, ContextMenuSubmenu};
118
119
 
119
120
  export const parseValue = (value: string): number | null => {
@@ -207,6 +208,13 @@ export const RawMetricsGraph = ({
207
208
  }
208
209
 
209
210
  const closestPointPerSeries = series.map(function (s) {
211
+ if (s.values.length === 0) {
212
+ return {
213
+ pointIndex: undefined,
214
+ distance: Infinity,
215
+ };
216
+ }
217
+
210
218
  const distances = s.values.map(d => {
211
219
  const x = xScale(d[0]) + margin / 2; // d[0] is timestamp_ms
212
220
  const y = yScale(d[1]) - margin / 3; // d[1] is value
@@ -216,7 +224,7 @@ export const RawMetricsGraph = ({
216
224
  });
217
225
 
218
226
  const pointIndex = d3.minIndex(distances);
219
- const minDistance = distances[pointIndex];
227
+ const minDistance = pointIndex != null ? distances[pointIndex] : Infinity;
220
228
 
221
229
  return {
222
230
  pointIndex,
@@ -225,7 +233,15 @@ export const RawMetricsGraph = ({
225
233
  });
226
234
 
227
235
  const closestSeriesIndex = d3.minIndex(closestPointPerSeries, s => s.distance);
236
+ if (closestSeriesIndex == null || closestPointPerSeries[closestSeriesIndex] == null) {
237
+ return null;
238
+ }
239
+
228
240
  const pointIndex = closestPointPerSeries[closestSeriesIndex].pointIndex;
241
+ if (pointIndex == null) {
242
+ return null;
243
+ }
244
+
229
245
  return {
230
246
  seriesIndex: closestSeriesIndex,
231
247
  pointIndex,
@@ -37,19 +37,11 @@ import MetricsGraph, {ContextMenuItemOrSubmenu, Series, SeriesPoint} from '../Me
37
37
  import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
38
38
  import {useQueryRange} from './hooks/useQueryRange';
39
39
 
40
- const transformUtilizationLabels = (label: string, utilizationMetrics: boolean): string => {
41
- if (utilizationMetrics) {
42
- return label.replace('attributes.', '').replace('attributes_resource.', '');
43
- }
44
- return label;
45
- };
46
-
47
40
  const createProfileContextMenuItems = (
48
41
  addLabelMatcher: (
49
42
  labels: {key: string; value: string} | Array<{key: string; value: string}>
50
43
  ) => void,
51
- data: MetricsSeriesPb[], // The original MetricsSeriesPb[] data
52
- utilizationMetrics = false
44
+ data: MetricsSeriesPb[] // The original MetricsSeriesPb[] data
53
45
  ): ContextMenuItemOrSubmenu[] => {
54
46
  return [
55
47
  {
@@ -107,7 +99,7 @@ const createProfileContextMenuItems = (
107
99
  id: `add-label-${label.name}`,
108
100
  label: (
109
101
  <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-300">
110
- {`${transformUtilizationLabels(label.name, utilizationMetrics)}="${label.value}"`}
102
+ {`${label.name}="${label.value}"`}
111
103
  </div>
112
104
  ),
113
105
  onClick: () => {
@@ -438,28 +430,6 @@ const ProfileMetricsGraph = ({
438
430
  const nameLabel = labels.find(e => e.name === '__name__');
439
431
  const highlightedNameLabel = nameLabel ?? {name: '', value: ''};
440
432
 
441
- // Calculate attributes maps for utilization metrics
442
- const utilizationMetrics = false; // This is for profile metrics, not utilization
443
- const attributesMap = labels
444
- .filter(
445
- label =>
446
- label.name.startsWith('attributes.') &&
447
- !label.name.startsWith('attributes_resource.')
448
- )
449
- .reduce<Record<string, string>>((acc, label) => {
450
- const key = label.name.replace('attributes.', '');
451
- acc[key] = label.value;
452
- return acc;
453
- }, {});
454
-
455
- const attributesResourceMap = labels
456
- .filter(label => label.name.startsWith('attributes_resource.'))
457
- .reduce<Record<string, string>>((acc, label) => {
458
- const key = label.name.replace('attributes_resource.', '');
459
- acc[key] = label.value;
460
- return acc;
461
- }, {});
462
-
463
433
  const isDeltaType =
464
434
  profile !== null
465
435
  ? (profile as MergedProfileSelection)?.query.profType.delta
@@ -528,72 +498,21 @@ const ProfileMetricsGraph = ({
528
498
  </table>
529
499
  </span>
530
500
  <span className="my-2 block text-gray-500">
531
- {utilizationMetrics ? (
532
- <>
533
- {Object.keys(attributesResourceMap).length > 0 && (
534
- <span className="text-sm font-bold text-gray-700 dark:text-white">
535
- Resource Attributes
536
- </span>
537
- )}
538
- <span className="my-2 block text-gray-500">
539
- {Object.keys(attributesResourceMap).map(name => (
540
- <div
541
- key={name}
542
- 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"
543
- {...testId(TEST_IDS.TOOLTIP_LABEL)}
544
- >
545
- <TextWithTooltip
546
- text={`${name.replace('attributes.', '')}="${
547
- attributesResourceMap[name]
548
- }"`}
549
- maxTextLength={48}
550
- id={`tooltip-${name}-${attributesResourceMap[name]}`}
551
- />
552
- </div>
553
- ))}
554
- </span>
555
- {Object.keys(attributesMap).length > 0 && (
556
- <span className="text-sm font-bold text-gray-700 dark:text-white">
557
- Attributes
558
- </span>
559
- )}
560
- <span className="my-2 block text-gray-500">
561
- {Object.keys(attributesMap).map(name => (
562
- <div
563
- key={name}
564
- 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"
565
- {...testId(TEST_IDS.TOOLTIP_LABEL)}
566
- >
567
- <TextWithTooltip
568
- text={`${name.replace('attributes.', '')}="${
569
- attributesMap[name]
570
- }"`}
571
- maxTextLength={48}
572
- id={`tooltip-${name}-${attributesMap[name]}`}
573
- />
574
- </div>
575
- ))}
576
- </span>
577
- </>
578
- ) : (
579
- <>
580
- {labels
581
- .filter((label: Label) => label.name !== '__name__')
582
- .map((label: Label) => (
583
- <div
584
- key={label.name}
585
- 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"
586
- {...testId(TEST_IDS.TOOLTIP_LABEL)}
587
- >
588
- <TextWithTooltip
589
- text={`${label.name}="${label.value}"`}
590
- maxTextLength={37}
591
- id={`tooltip-${label.name}`}
592
- />
593
- </div>
594
- ))}
595
- </>
596
- )}
501
+ {labels
502
+ .filter((label: Label) => label.name !== '__name__')
503
+ .map((label: Label) => (
504
+ <div
505
+ key={label.name}
506
+ 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"
507
+ {...testId(TEST_IDS.TOOLTIP_LABEL)}
508
+ >
509
+ <TextWithTooltip
510
+ text={`${label.name}="${label.value}"`}
511
+ maxTextLength={37}
512
+ id={`tooltip-${label.name}`}
513
+ />
514
+ </div>
515
+ ))}
597
516
  </span>
598
517
  <div className="flex w-full items-center gap-1 text-xs text-gray-500">
599
518
  <Icon icon="iconoir:mouse-button-right" />
@@ -18,11 +18,9 @@ import {DateTimeRange, useURLStateBatch} from '@parca/components';
18
18
  import {Query} from '@parca/parser';
19
19
 
20
20
  import {ProfileSelection} from '..';
21
- import UtilizationMetricsGraph from '../MetricsGraph/UtilizationMetrics';
22
- import AreaChart from '../MetricsGraph/UtilizationMetrics/Throughput';
23
21
  import ProfileMetricsGraph, {ProfileMetricsEmptyState} from '../ProfileMetricsGraph';
24
22
  import {useResetStateOnSeriesChange} from '../ProfileView/hooks/useResetStateOnSeriesChange';
25
- import {QuerySelection, type UtilizationMetrics as UtilizationMetricsType} from './index';
23
+ import {QuerySelection} from './index';
26
24
 
27
25
  interface MetricsGraphSectionProps {
28
26
  showMetricsGraph: boolean;
@@ -41,13 +39,6 @@ interface MetricsGraphSectionProps {
41
39
  query: Query;
42
40
  setNewQueryExpression: (queryExpression: string, commit?: boolean) => void;
43
41
  setQueryExpression: (updateTs?: boolean) => void;
44
- utilizationMetrics?: Array<{
45
- name: string;
46
- humanReadableName: string;
47
- data: UtilizationMetricsType[];
48
- }>;
49
- utilizationMetricsLoading?: boolean;
50
- onUtilizationSeriesSelect?: (name: string, seriesIndex: number) => void;
51
42
  }
52
43
 
53
44
  export function MetricsGraphSection({
@@ -66,9 +57,6 @@ export function MetricsGraphSection({
66
57
  setProfileSelection,
67
58
  query,
68
59
  setNewQueryExpression,
69
- utilizationMetrics,
70
- utilizationMetricsLoading,
71
- onUtilizationSeriesSelect,
72
60
  }: MetricsGraphSectionProps): JSX.Element {
73
61
  const resetStateOnSeriesChange = useResetStateOnSeriesChange();
74
62
  const batchUpdates = useURLStateBatch();
@@ -147,89 +135,6 @@ export function MetricsGraphSection({
147
135
  });
148
136
  };
149
137
 
150
- const UtilizationGraphToShow = ({
151
- utilizationMetrics,
152
- }: {
153
- utilizationMetrics: Array<{
154
- name: string;
155
- humanReadableName: string;
156
- data: UtilizationMetricsType[];
157
- }>;
158
- }): JSX.Element => {
159
- const throughputMetrics = utilizationMetrics.filter(
160
- metric =>
161
- metric.name === 'gpu_pcie_throughput_transmit_bytes' ||
162
- metric.name === 'gpu_pcie_throughput_receive_bytes'
163
- );
164
- const transmitData =
165
- throughputMetrics.find(metric => metric.name === 'gpu_pcie_throughput_transmit_bytes')
166
- ?.data ?? [];
167
- const receiveData =
168
- throughputMetrics.find(metric => metric.name === 'gpu_pcie_throughput_receive_bytes')?.data ??
169
- [];
170
-
171
- if (utilizationMetrics.length === 0) {
172
- return <></>;
173
- }
174
-
175
- return (
176
- <div>
177
- {utilizationMetrics.map(({name, humanReadableName, data}) => {
178
- if (
179
- name !== 'gpu_pcie_throughput_transmit_bytes' &&
180
- name !== 'gpu_pcie_throughput_receive_bytes'
181
- ) {
182
- return (
183
- <UtilizationMetricsGraph
184
- key={name}
185
- data={data}
186
- setTimeRange={handleTimeRangeChange}
187
- utilizationMetricsLoading={utilizationMetricsLoading}
188
- humanReadableName={humanReadableName}
189
- from={querySelection.from}
190
- to={querySelection.to}
191
- yAxisUnit="percentage"
192
- addLabelMatcher={addLabelMatcher}
193
- onSeriesClick={seriesIndex => {
194
- // For generic UtilizationMetrics, just pass the series index
195
- if (onUtilizationSeriesSelect != null) {
196
- onUtilizationSeriesSelect(name, seriesIndex);
197
- }
198
- }}
199
- />
200
- );
201
- }
202
- return null;
203
- })}
204
- {throughputMetrics.length > 0 && (
205
- <AreaChart
206
- transmitData={transmitData}
207
- receiveData={receiveData}
208
- addLabelMatcher={addLabelMatcher}
209
- setTimeRange={handleTimeRangeChange}
210
- name={throughputMetrics[0].name}
211
- humanReadableName={throughputMetrics[0].humanReadableName}
212
- from={querySelection.from}
213
- to={querySelection.to}
214
- utilizationMetricsLoading={utilizationMetricsLoading}
215
- selectedSeries={undefined}
216
- onSeriesClick={(_, seriesIndex) => {
217
- // For throughput metrics, just pass the series index
218
- if (onUtilizationSeriesSelect != null) {
219
- let name = 'gpu_pcie_throughput_transmit_bytes';
220
- if (seriesIndex > transmitData.length - 1) {
221
- name = 'gpu_pcie_throughput_receive_bytes';
222
- seriesIndex -= transmitData.length;
223
- }
224
- onUtilizationSeriesSelect(name, seriesIndex);
225
- }
226
- }}
227
- />
228
- )}
229
- </div>
230
- );
231
- };
232
-
233
138
  return (
234
139
  <div className={cx('relative', {'py-4': !showMetricsGraph})}>
235
140
  {setDisplayHideMetricsGraphButton != null ? (
@@ -251,25 +156,19 @@ export function MetricsGraphSection({
251
156
  querySelection.from !== undefined &&
252
157
  querySelection.to !== undefined ? (
253
158
  <>
254
- {utilizationMetrics !== undefined ? (
255
- <UtilizationGraphToShow utilizationMetrics={utilizationMetrics} />
256
- ) : (
257
- <>
258
- <ProfileMetricsGraph
259
- queryClient={queryClient}
260
- queryExpression={querySelection.expression}
261
- from={querySelection.from}
262
- to={querySelection.to}
263
- profile={profileSelection}
264
- comparing={comparing}
265
- sumBy={querySelection.sumBy ?? sumBy ?? []}
266
- sumByLoading={defaultSumByLoading}
267
- setTimeRange={handleTimeRangeChange}
268
- addLabelMatcher={addLabelMatcher}
269
- onPointClick={handlePointClick}
270
- />
271
- </>
272
- )}
159
+ <ProfileMetricsGraph
160
+ queryClient={queryClient}
161
+ queryExpression={querySelection.expression}
162
+ from={querySelection.from}
163
+ to={querySelection.to}
164
+ profile={profileSelection}
165
+ comparing={comparing}
166
+ sumBy={querySelection.sumBy ?? sumBy ?? []}
167
+ sumByLoading={defaultSumByLoading}
168
+ setTimeRange={handleTimeRangeChange}
169
+ addLabelMatcher={addLabelMatcher}
170
+ onPointClick={handlePointClick}
171
+ />
273
172
  </>
274
173
  ) : (
275
174
  profileSelection === null && (