@parca/profile 0.16.335 → 0.16.336

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 (31) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/ProfileIcicleGraph/ActionButtons/GroupByDropdown.d.ts +6 -0
  3. package/dist/ProfileIcicleGraph/ActionButtons/GroupByDropdown.js +57 -0
  4. package/dist/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.d.ts +10 -0
  5. package/dist/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.js +23 -0
  6. package/dist/ProfileIcicleGraph/ActionButtons/SortBySelect.d.ts +7 -0
  7. package/dist/ProfileIcicleGraph/ActionButtons/SortBySelect.js +44 -0
  8. package/dist/ProfileIcicleGraph/index.d.ts +2 -1
  9. package/dist/ProfileIcicleGraph/index.js +19 -86
  10. package/dist/ProfileMetricsGraph/index.js +10 -8
  11. package/dist/ProfileView/VisualizationPanel.js +1 -1
  12. package/dist/ProfileView/index.js +6 -30
  13. package/dist/SourceView/index.js +5 -4
  14. package/dist/Table/ColumnsVisibility.d.ts +9 -0
  15. package/dist/Table/ColumnsVisibility.js +22 -0
  16. package/dist/Table/index.d.ts +13 -0
  17. package/dist/Table/index.js +13 -12
  18. package/dist/styles.css +1 -1
  19. package/package.json +4 -3
  20. package/src/ProfileIcicleGraph/ActionButtons/GroupByDropdown.tsx +127 -0
  21. package/src/ProfileIcicleGraph/ActionButtons/RuntimeFilterDropdown.tsx +123 -0
  22. package/src/ProfileIcicleGraph/ActionButtons/SortBySelect.tsx +80 -0
  23. package/src/ProfileIcicleGraph/index.tsx +123 -341
  24. package/src/ProfileMetricsGraph/index.tsx +37 -21
  25. package/src/ProfileView/VisualizationPanel.tsx +19 -8
  26. package/src/ProfileView/index.tsx +52 -81
  27. package/src/SourceView/index.tsx +23 -8
  28. package/src/Table/ColumnsVisibility.tsx +87 -0
  29. package/src/Table/index.tsx +53 -86
  30. package/dist/QueryBrowser/index.d.ts +0 -12
  31. package/dist/QueryBrowser/index.js +0 -51
@@ -53,7 +53,6 @@ import {ProfileSource} from '../ProfileSource';
53
53
  import {SourceView} from '../SourceView';
54
54
  import Table from '../Table';
55
55
  import ProfileShareButton from '../components/ProfileShareButton';
56
- import useDelayedLoader from '../useDelayedLoader';
57
56
  import FilterByFunctionButton from './FilterByFunctionButton';
58
57
  import {ProfileViewContextProvider} from './ProfileViewContext';
59
58
  import ViewSelector from './ViewSelector';
@@ -153,8 +152,7 @@ export const ProfileView = ({
153
152
  const isDarkMode = useAppSelector(selectDarkMode);
154
153
  const isMultiPanelView = dashboardItems.length > 1;
155
154
 
156
- const {loader, perf, profileViewExternalMainActions, profileViewExternalSubActions} =
157
- useParcaContext();
155
+ const {perf, profileViewExternalMainActions, profileViewExternalSubActions} = useParcaContext();
158
156
 
159
157
  useEffect(() => {
160
158
  // Reset the current path when the profile source changes
@@ -169,31 +167,6 @@ export const ProfileView = ({
169
167
  void loadGraphviz();
170
168
  }, []);
171
169
 
172
- const isLoading = useMemo(() => {
173
- if (dashboardItems.includes('icicle')) {
174
- return Boolean(flamegraphData?.loading);
175
- }
176
- if (dashboardItems.includes('callgraph')) {
177
- return Boolean(callgraphData?.loading) || Boolean(callgraphSVG === undefined);
178
- }
179
- if (dashboardItems.includes('table')) {
180
- return Boolean(topTableData?.loading);
181
- }
182
- if (dashboardItems.includes('source')) {
183
- return Boolean(sourceData?.loading);
184
- }
185
- return false;
186
- }, [
187
- dashboardItems,
188
- callgraphData?.loading,
189
- flamegraphData?.loading,
190
- topTableData?.loading,
191
- sourceData?.loading,
192
- callgraphSVG,
193
- ]);
194
-
195
- const isLoaderVisible = useDelayedLoader(isLoading);
196
-
197
170
  const maxColor: string = getNewSpanColor(isDarkMode);
198
171
  const minColor: string = scaleLinear([isDarkMode ? 'black' : 'white', maxColor])(0.3);
199
172
  const colorRange: [string, string] = [minColor, maxColor];
@@ -269,6 +242,7 @@ export const ProfileView = ({
269
242
  loading={flamegraphData.loading}
270
243
  setActionButtons={setActionButtons}
271
244
  error={flamegraphData.error}
245
+ isHalfScreen={isHalfScreen}
272
246
  width={
273
247
  dimensions?.width !== undefined
274
248
  ? isHalfScreen
@@ -305,6 +279,7 @@ export const ProfileView = ({
305
279
  navigateTo={navigateTo}
306
280
  setActionButtons={setActionButtons}
307
281
  currentSearchString={currentSearchString as string}
282
+ isHalfScreen={isHalfScreen}
308
283
  />
309
284
  ) : (
310
285
  <></>
@@ -432,59 +407,55 @@ export const ProfileView = ({
432
407
  </div>
433
408
 
434
409
  <div className="w-full" ref={ref}>
435
- {isLoaderVisible ? (
436
- <>{loader}</>
437
- ) : (
438
- <DragDropContext onDragEnd={onDragEnd}>
439
- <Droppable droppableId="droppable" direction="horizontal">
440
- {provided => (
441
- <div
442
- ref={provided.innerRef}
443
- className={cx(
444
- 'grid w-full gap-2',
445
- isMultiPanelView ? 'grid-cols-2' : 'grid-cols-1'
446
- )}
447
- {...provided.droppableProps}
448
- >
449
- {dashboardItems.map((dashboardItem, index) => {
450
- return (
451
- <Draggable
452
- key={dashboardItem}
453
- draggableId={dashboardItem}
454
- index={index}
455
- isDragDisabled={!isMultiPanelView}
456
- >
457
- {(provided, snapshot: {isDragging: boolean}) => (
458
- <div
459
- ref={provided.innerRef}
460
- {...provided.draggableProps}
461
- key={dashboardItem}
462
- className={cx(
463
- 'min-h-[200px] w-full rounded p-2 shadow dark:border dark:border-gray-700 dark:bg-gray-700',
464
- snapshot.isDragging
465
- ? 'bg-gray-200 dark:bg-gray-500'
466
- : 'bg-white dark:bg-gray-700'
467
- )}
468
- >
469
- <VisualizationPanel
470
- handleClosePanel={handleClosePanel}
471
- isMultiPanelView={isMultiPanelView}
472
- dashboardItem={dashboardItem}
473
- getDashboardItemByType={getDashboardItemByType}
474
- dragHandleProps={provided.dragHandleProps}
475
- navigateTo={navigateTo}
476
- index={index}
477
- />
478
- </div>
479
- )}
480
- </Draggable>
481
- );
482
- })}
483
- </div>
484
- )}
485
- </Droppable>
486
- </DragDropContext>
487
- )}
410
+ <DragDropContext onDragEnd={onDragEnd}>
411
+ <Droppable droppableId="droppable" direction="horizontal">
412
+ {provided => (
413
+ <div
414
+ ref={provided.innerRef}
415
+ className={cx(
416
+ 'grid w-full gap-2',
417
+ isMultiPanelView ? 'grid-cols-2' : 'grid-cols-1'
418
+ )}
419
+ {...provided.droppableProps}
420
+ >
421
+ {dashboardItems.map((dashboardItem, index) => {
422
+ return (
423
+ <Draggable
424
+ key={dashboardItem}
425
+ draggableId={dashboardItem}
426
+ index={index}
427
+ isDragDisabled={!isMultiPanelView}
428
+ >
429
+ {(provided, snapshot: {isDragging: boolean}) => (
430
+ <div
431
+ ref={provided.innerRef}
432
+ {...provided.draggableProps}
433
+ key={dashboardItem}
434
+ className={cx(
435
+ 'w-full rounded p-2 shadow dark:border dark:border-gray-700 dark:bg-gray-700 min-h-96',
436
+ snapshot.isDragging
437
+ ? 'bg-gray-200 dark:bg-gray-500'
438
+ : 'bg-white dark:bg-gray-700'
439
+ )}
440
+ >
441
+ <VisualizationPanel
442
+ handleClosePanel={handleClosePanel}
443
+ isMultiPanelView={isMultiPanelView}
444
+ dashboardItem={dashboardItem}
445
+ getDashboardItemByType={getDashboardItemByType}
446
+ dragHandleProps={provided.dragHandleProps}
447
+ navigateTo={navigateTo}
448
+ index={index}
449
+ />
450
+ </div>
451
+ )}
452
+ </Draggable>
453
+ );
454
+ })}
455
+ </div>
456
+ )}
457
+ </Droppable>
458
+ </DragDropContext>
488
459
  </div>
489
460
  </ProfileViewContextProvider>
490
461
  </KeyDownProvider>
@@ -14,9 +14,10 @@
14
14
  import React, {useEffect} from 'react';
15
15
 
16
16
  import {tableFromIPC} from 'apache-arrow';
17
+ import {AnimatePresence, motion} from 'framer-motion';
17
18
 
18
19
  import {Source} from '@parca/client';
19
- import {useParcaContext, useURLState} from '@parca/components';
20
+ import {SourceSkeleton, useParcaContext, useURLState} from '@parca/components';
20
21
 
21
22
  import {ExpandOnHover} from '../GraphTooltipArrow/ExpandOnHoverValue';
22
23
  import {truncateStringReverse} from '../utils';
@@ -38,7 +39,7 @@ export const SourceView = React.memo(function SourceView({
38
39
  setActionButtons,
39
40
  }: SourceViewProps): JSX.Element {
40
41
  const [sourceFileName] = useURLState({param: 'source_filename', navigateTo: () => {}});
41
- const {loader} = useParcaContext();
42
+ const {isDarkMode} = useParcaContext();
42
43
 
43
44
  useEffect(() => {
44
45
  setActionButtons?.(
@@ -52,7 +53,11 @@ export const SourceView = React.memo(function SourceView({
52
53
  }, [sourceFileName, setActionButtons]);
53
54
 
54
55
  if (loading) {
55
- return <div className="h-96">{loader}</div>;
56
+ return (
57
+ <div className="h-auto overflow-clip">
58
+ <SourceSkeleton isDarkMode={isDarkMode} />
59
+ </div>
60
+ );
56
61
  }
57
62
 
58
63
  if (data === undefined) {
@@ -64,11 +69,21 @@ export const SourceView = React.memo(function SourceView({
64
69
  const flat = table.getChild('flat');
65
70
 
66
71
  return (
67
- <Highlighter
68
- file={sourceFileName as string}
69
- content={data.source}
70
- renderer={profileAwareRenderer(cumulative, flat, total, filtered)}
71
- />
72
+ <AnimatePresence>
73
+ <motion.div
74
+ className="h-full w-full"
75
+ key="source-view-loaded"
76
+ initial={{display: 'none', opacity: 0}}
77
+ animate={{display: 'block', opacity: 1}}
78
+ transition={{duration: 0.5}}
79
+ >
80
+ <Highlighter
81
+ file={sourceFileName as string}
82
+ content={data.source}
83
+ renderer={profileAwareRenderer(cumulative, flat, total, filtered)}
84
+ />
85
+ </motion.div>
86
+ </AnimatePresence>
72
87
  );
73
88
  });
74
89
 
@@ -0,0 +1,87 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {Fragment} from 'react';
15
+
16
+ import {Menu, Transition} from '@headlessui/react';
17
+ import {Icon} from '@iconify/react';
18
+ import {type VisibilityState} from '@tanstack/react-table';
19
+
20
+ import {ColumnDef} from '.';
21
+
22
+ const ColumnsVisibility = ({
23
+ columns,
24
+ visibility,
25
+ setVisibility,
26
+ }: {
27
+ columns: ColumnDef[];
28
+ visibility: VisibilityState;
29
+ setVisibility: (id: string, visible: boolean) => void;
30
+ }): React.JSX.Element => {
31
+ return (
32
+ <div>
33
+ <Menu as="div" className="relative text-left">
34
+ <div>
35
+ <Menu.Button className="relative w-full cursor-default rounded-md border bg-white py-2 pl-3 pr-10 text-left text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 sm:text-sm">
36
+ <span className="block overflow-x-hidden text-ellipsis">Columns</span>
37
+ <span className="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2 text-gray-400">
38
+ <Icon icon="heroicons:chevron-down-20-solid" aria-hidden="true" />
39
+ </span>
40
+ </Menu.Button>
41
+ </div>
42
+
43
+ <Transition
44
+ as={Fragment}
45
+ leave="transition ease-in duration-100"
46
+ leaveFrom="opacity-100"
47
+ leaveTo="opacity-0"
48
+ >
49
+ <Menu.Items className="absolute left-0 z-10 mt-1 min-w-[400px] overflow-auto rounded-md bg-gray-50 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:ring-white dark:ring-opacity-20 sm:text-sm">
50
+ <div className="p-4">
51
+ <fieldset>
52
+ <div className="space-y-5">
53
+ {columns.map(col => (
54
+ <div key={col.id} className="relative flex items-start">
55
+ <div className="flex h-6 items-center">
56
+ <input
57
+ id={col.id}
58
+ name={col.id}
59
+ type="checkbox"
60
+ className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
61
+ checked={visibility[col.id ?? ''] ?? false}
62
+ onChange={() => {
63
+ setVisibility(col.id ?? '', !visibility[col.id ?? '']);
64
+ }}
65
+ />
66
+ </div>
67
+ <div className="ml-3 text-sm leading-6">
68
+ <label
69
+ htmlFor={col.id}
70
+ className="font-medium text-gray-900 dark:text-gray-200"
71
+ >
72
+ {col.header}
73
+ </label>
74
+ </div>
75
+ </div>
76
+ ))}
77
+ </div>
78
+ </fieldset>
79
+ </div>
80
+ </Menu.Items>
81
+ </Transition>
82
+ </Menu>
83
+ </div>
84
+ );
85
+ };
86
+
87
+ export default ColumnsVisibility;
@@ -11,14 +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, {Fragment, useCallback, useEffect, useMemo, useState} from 'react';
14
+ import React, {useCallback, useEffect, useMemo, useState} from 'react';
15
15
 
16
- import {Menu, Transition} from '@headlessui/react';
17
- import {Icon} from '@iconify/react';
18
- import {type VisibilityState} from '@tanstack/react-table';
19
16
  import {Vector, tableFromIPC} from 'apache-arrow';
17
+ import {AnimatePresence, motion} from 'framer-motion';
20
18
 
21
- import {Button, Table as TableComponent, useURLState} from '@parca/components';
19
+ import {
20
+ Button,
21
+ TableActionButtonPlaceholder,
22
+ Table as TableComponent,
23
+ TableSkeleton,
24
+ useParcaContext,
25
+ useURLState,
26
+ } from '@parca/components';
22
27
  import {
23
28
  getLastItem,
24
29
  isSearchMatch,
@@ -29,6 +34,7 @@ import {
29
34
 
30
35
  import {useProfileViewContext} from '../ProfileView/ProfileViewContext';
31
36
  import {hexifyAddress} from '../utils';
37
+ import ColumnsVisibility from './ColumnsVisibility';
32
38
 
33
39
  const FIELD_MAPPING_FILE = 'mapping_file';
34
40
  const FIELD_LOCATION_ADDRESS = 'location_address';
@@ -51,7 +57,7 @@ interface row {
51
57
  functionFileName: string;
52
58
  }
53
59
 
54
- interface ColumnDef {
60
+ export interface ColumnDef {
55
61
  id: string;
56
62
  header: string;
57
63
  accessorKey: string;
@@ -71,6 +77,7 @@ interface TableProps {
71
77
  loading: boolean;
72
78
  currentSearchString?: string;
73
79
  setActionButtons?: (buttons: React.JSX.Element) => void;
80
+ isHalfScreen: boolean;
74
81
  }
75
82
 
76
83
  export const Table = React.memo(function Table({
@@ -82,10 +89,12 @@ export const Table = React.memo(function Table({
82
89
  loading,
83
90
  currentSearchString,
84
91
  setActionButtons,
92
+ isHalfScreen,
85
93
  }: TableProps): React.JSX.Element {
86
94
  const router = parseParams(window?.location.search);
87
95
  const [rawDashboardItems] = useURLState({param: 'dashboard_items'});
88
96
  const [filterByFunctionInput] = useURLState({param: 'filter_by_function'});
97
+ const {isDarkMode} = useParcaContext();
89
98
 
90
99
  const {compareMode} = useProfileViewContext();
91
100
 
@@ -298,9 +307,15 @@ export const Table = React.memo(function Table({
298
307
  }, [navigateTo, router, filterByFunctionInput]);
299
308
 
300
309
  useEffect(() => {
310
+ if (loading && setActionButtons !== undefined) {
311
+ setActionButtons(<TableActionButtonPlaceholder />);
312
+ return;
313
+ }
314
+
301
315
  if (setActionButtons === undefined) {
302
316
  return;
303
317
  }
318
+
304
319
  setActionButtons(
305
320
  <>
306
321
  <ColumnsVisibility
@@ -330,6 +345,7 @@ export const Table = React.memo(function Table({
330
345
  setActionButtons,
331
346
  columns,
332
347
  columnVisibility,
348
+ loading,
333
349
  ]);
334
350
 
335
351
  const initialSorting = useMemo(() => {
@@ -341,7 +357,13 @@ export const Table = React.memo(function Table({
341
357
  ];
342
358
  }, [compareMode]);
343
359
 
344
- if (loading) return <div className="mx-auto text-center">Loading...</div>;
360
+ if (loading)
361
+ return (
362
+ <div className="overflow-clip h-[700px] min-h-[700px]">
363
+ <TableSkeleton isHalfScreen={isHalfScreen} isDarkMode={isDarkMode} />
364
+ </div>
365
+ );
366
+
345
367
  if (data === undefined) return <div className="mx-auto text-center">Profile has no samples</div>;
346
368
 
347
369
  const table = tableFromIPC(data);
@@ -380,87 +402,32 @@ export const Table = React.memo(function Table({
380
402
  }
381
403
 
382
404
  return (
383
- <div className="relative">
384
- <div className="font-robotoMono h-[80vh] w-full">
385
- <TableComponent
386
- data={rows}
387
- columns={columns}
388
- initialSorting={initialSorting}
389
- columnVisibility={columnVisibility}
390
- onRowClick={onRowClick}
391
- enableHighlighting={enableHighlighting}
392
- shouldHighlightRow={shouldHighlightRow}
393
- usePointerCursor={dashboardItems.length > 1}
394
- />
395
- </div>
396
- </div>
397
- );
398
- });
399
-
400
- const ColumnsVisibility = ({
401
- columns,
402
- visibility,
403
- setVisibility,
404
- }: {
405
- columns: ColumnDef[];
406
- visibility: VisibilityState;
407
- setVisibility: (id: string, visible: boolean) => void;
408
- }): React.JSX.Element => {
409
- return (
410
- <div>
411
- <Menu as="div" className="relative text-left">
412
- <div>
413
- <Menu.Button className="relative w-full cursor-default rounded-md border bg-white py-2 pl-3 pr-10 text-left text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 sm:text-sm">
414
- <span className="ml-3 block overflow-x-hidden text-ellipsis">Columns</span>
415
- <span className="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2 text-gray-400">
416
- <Icon icon="heroicons:chevron-down-20-solid" aria-hidden="true" />
417
- </span>
418
- </Menu.Button>
405
+ <AnimatePresence>
406
+ <motion.div
407
+ className="h-full w-full"
408
+ key="table-loaded"
409
+ initial={{display: 'none', opacity: 0}}
410
+ animate={{display: 'block', opacity: 1}}
411
+ transition={{duration: 0.5}}
412
+ >
413
+ <div className="relative">
414
+ <div className="font-robotoMono h-[80vh] w-full">
415
+ <TableComponent
416
+ data={rows}
417
+ columns={columns}
418
+ initialSorting={initialSorting}
419
+ columnVisibility={columnVisibility}
420
+ onRowClick={onRowClick}
421
+ enableHighlighting={enableHighlighting}
422
+ shouldHighlightRow={shouldHighlightRow}
423
+ usePointerCursor={dashboardItems.length > 1}
424
+ />
425
+ </div>
419
426
  </div>
420
-
421
- <Transition
422
- as={Fragment}
423
- leave="transition ease-in duration-100"
424
- leaveFrom="opacity-100"
425
- leaveTo="opacity-0"
426
- >
427
- <Menu.Items className="absolute left-0 z-10 mt-1 min-w-[400px] overflow-auto rounded-md bg-gray-50 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:ring-white dark:ring-opacity-20 sm:text-sm">
428
- <div className="p-4">
429
- <fieldset>
430
- <div className="space-y-5">
431
- {columns.map(col => (
432
- <div key={col.id} className="relative flex items-start">
433
- <div className="flex h-6 items-center">
434
- <input
435
- id={col.id}
436
- name={col.id}
437
- type="checkbox"
438
- className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
439
- checked={visibility[col.id ?? ''] ?? false}
440
- onChange={() => {
441
- setVisibility(col.id ?? '', !visibility[col.id ?? '']);
442
- }}
443
- />
444
- </div>
445
- <div className="ml-3 text-sm leading-6">
446
- <label
447
- htmlFor={col.id}
448
- className="font-medium text-gray-900 dark:text-gray-200"
449
- >
450
- {col.header}
451
- </label>
452
- </div>
453
- </div>
454
- ))}
455
- </div>
456
- </fieldset>
457
- </div>
458
- </Menu.Items>
459
- </Transition>
460
- </Menu>
461
- </div>
427
+ </motion.div>
428
+ </AnimatePresence>
462
429
  );
463
- };
430
+ });
464
431
 
465
432
  const addPlusSign = (num: string): string => {
466
433
  if (num.charAt(0) === '0' || num.charAt(0) === '-') {
@@ -1,12 +0,0 @@
1
- import { QueryServiceClient } from '@parca/client';
2
- import { DateTimeRange } from '@parca/components';
3
- import { QuerySelection } from '../ProfileSelector';
4
- interface Props {
5
- queryClient: QueryServiceClient;
6
- selectQuery: (query: QuerySelection) => void;
7
- enforcedProfileName: string;
8
- timeRangeSelection: DateTimeRange;
9
- querySelection: QuerySelection;
10
- }
11
- declare const QueryBrowser: ({ queryClient, enforcedProfileName, timeRangeSelection, selectQuery, querySelection, }: Props) => import("react/jsx-runtime").JSX.Element;
12
- export default QueryBrowser;
@@ -1,51 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState } from 'react';
3
- import { Query } from '@parca/parser';
4
- import MatchersInput from '../MatchersInput';
5
- const QueryBrowser = ({ queryClient, enforcedProfileName, timeRangeSelection, selectQuery, querySelection, }) => {
6
- const [queryExpressionString, setQueryExpressionString] = useState(querySelection.expression);
7
- useEffect(() => {
8
- if (enforcedProfileName !== '') {
9
- const [q, changed] = Query.parse(querySelection.expression).setProfileName(enforcedProfileName);
10
- if (changed) {
11
- setQueryExpressionString(q.toString());
12
- return;
13
- }
14
- }
15
- setQueryExpressionString(querySelection.expression);
16
- }, [enforcedProfileName, querySelection.expression]);
17
- const enforcedProfileNameQuery = () => {
18
- const pq = Query.parse(queryExpressionString);
19
- const [q] = pq.setProfileName(enforcedProfileName);
20
- return q;
21
- };
22
- const setMatchersString = (matchers) => {
23
- const newExpressionString = `${''}{${matchers}}`;
24
- setQueryExpressionString(newExpressionString);
25
- };
26
- const setNewQueryExpression = (expr) => {
27
- const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(expr);
28
- const delta = query.profileType().delta;
29
- const from = timeRangeSelection.getFromMs();
30
- const to = timeRangeSelection.getToMs();
31
- const mergeParams = delta
32
- ? {
33
- mergeFrom: from,
34
- mergeTo: to,
35
- }
36
- : {};
37
- selectQuery({
38
- expression: expr,
39
- from,
40
- to,
41
- timeSelection: timeRangeSelection.getRangeKey(),
42
- ...mergeParams,
43
- });
44
- };
45
- const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
46
- const setQueryExpression = () => {
47
- setNewQueryExpression(query.toString());
48
- };
49
- return (_jsx(_Fragment, { children: _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query }) }));
50
- };
51
- export default QueryBrowser;