@parca/profile 0.16.253 → 0.16.254

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
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.254 (2023-09-14)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
6
10
  ## [0.16.253](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.252...@parca/profile@0.16.253) (2023-09-11)
7
11
 
8
12
  **Note:** Version bump only for package @parca/profile
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { QueryServiceClient } from '@parca/client';
3
- import type { NavigateFunction } from '@parca/utilities';
3
+ import { type NavigateFunction } from '@parca/utilities';
4
4
  interface ProfileExplorerProps {
5
5
  queryClient: QueryServiceClient;
6
6
  queryParams: any;
@@ -1,4 +1,4 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  // Copyright 2022 The Parca Authors
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -15,10 +15,14 @@ import { useEffect, useState } from 'react';
15
15
  import { Provider } from 'react-redux';
16
16
  import { DateTimeRange, KeyDownProvider, useParcaContext } from '@parca/components';
17
17
  import { store } from '@parca/store';
18
+ import { capitalizeOnlyFirstLetter } from '@parca/utilities';
18
19
  import { ProfileSelectionFromParams, SuffixParams } from '..';
19
20
  import { useProfileTypes } from '../ProfileSelector';
20
21
  import ProfileExplorerCompare from './ProfileExplorerCompare';
21
22
  import ProfileExplorerSingle from './ProfileExplorerSingle';
23
+ const ErrorContent = ({ errorMessage }) => {
24
+ return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
25
+ };
22
26
  const getExpressionAsAString = (expression) => {
23
27
  const x = Array.isArray(expression) ? expression.join() : expression;
24
28
  return x;
@@ -45,10 +49,10 @@ const swapQueryParameters = (o) => {
45
49
  };
46
50
  const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
47
51
  const { loading: profileTypesLoading, data: profileTypesData, error: profileTypesError, } = useProfileTypes(queryClient);
48
- const { loader, noDataPrompt, onError } = useParcaContext();
52
+ const { loader, noDataPrompt, onError, authenticationErrorMessage } = useParcaContext();
49
53
  useEffect(() => {
50
54
  if (profileTypesError !== undefined && profileTypesError !== null) {
51
- onError?.(profileTypesError, 'ProfileExplorer');
55
+ onError?.(profileTypesError);
52
56
  }
53
57
  }, [profileTypesError, onError]);
54
58
  /* eslint-disable @typescript-eslint/naming-convention */
@@ -83,7 +87,10 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
83
87
  return _jsx(_Fragment, { children: noDataPrompt });
84
88
  }
85
89
  if (profileTypesError !== undefined && profileTypesError !== null) {
86
- return (_jsxs("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: [_jsx("strong", { className: "font-bold", children: "Error! " }), _jsx("span", { className: "block sm:inline", children: profileTypesError.message })] }));
90
+ if (authenticationErrorMessage !== undefined && profileTypesError.code === 'UNAUTHENTICATED') {
91
+ return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
92
+ }
93
+ return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(profileTypesError.message) });
87
94
  }
88
95
  const sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
89
96
  time_selection_a = sanitizedRange.time_selection_a;
@@ -16,11 +16,14 @@ import { Menu, Transition } from '@headlessui/react';
16
16
  import { Icon } from '@iconify/react';
17
17
  import { Button, Select, useParcaContext, useURLState } from '@parca/components';
18
18
  import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
19
- import { divide, selectQueryParam } from '@parca/utilities';
19
+ import { capitalizeOnlyFirstLetter, divide, selectQueryParam, } from '@parca/utilities';
20
20
  import DiffLegend from '../components/DiffLegend';
21
21
  import IcicleGraph from './IcicleGraph';
22
22
  import IcicleGraphArrow, { FIELD_CUMULATIVE, FIELD_DIFF, FIELD_FUNCTION_NAME, FIELD_LABELS, } from './IcicleGraphArrow';
23
23
  const numberFormatter = new Intl.NumberFormat('en-US');
24
+ const ErrorContent = ({ errorMessage }) => {
25
+ return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
26
+ };
24
27
  const ShowHideLegendButton = ({ navigateTo }) => {
25
28
  const [colorStackLegend, setStoreColorStackLegend] = useURLState({
26
29
  param: 'color_stack_legend',
@@ -64,7 +67,7 @@ const GroupAndSortActionButtons = ({ navigateTo }) => {
64
67
  return (_jsxs(_Fragment, { children: [_jsx(GroupByDropdown, { groupBy: groupBy, toggleGroupBy: toggleGroupBy }), _jsx(SortBySelect, { compareMode: compareMode, sortBy: storeSortBy, setSortBy: setStoreSortBy })] }));
65
68
  };
66
69
  const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, sampleUnit, navigateTo, loading, setActionButtons, error, width, }) {
67
- const { loader } = useParcaContext();
70
+ const { loader, onError, authenticationErrorMessage } = useParcaContext();
68
71
  const compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
69
72
  const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState({
70
73
  param: 'sort_by',
@@ -98,8 +101,11 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
98
101
  return _jsx("div", { className: "h-96", children: loader });
99
102
  }
100
103
  if (error != null) {
101
- console.error('Error: ', error);
102
- return _jsxs("div", { className: "flex justify-center p-10", children: ["An error occurred: ", error.message] });
104
+ onError?.(error);
105
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
106
+ return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
107
+ }
108
+ return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(error.message) });
103
109
  }
104
110
  if (graph === undefined && arrow === undefined)
105
111
  return _jsx("div", { className: "mx-auto text-center", children: "No data..." });
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  // Copyright 2022 The Parca Authors
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -15,10 +15,13 @@ import { useEffect, useState } from 'react';
15
15
  import { Duration, Timestamp } from '@parca/client';
16
16
  import { useGrpcMetadata, useParcaContext } from '@parca/components';
17
17
  import { Query } from '@parca/parser';
18
- import { getStepDuration } from '@parca/utilities';
18
+ import { capitalizeOnlyFirstLetter, getStepDuration } from '@parca/utilities';
19
19
  import MetricsGraph from '../MetricsGraph';
20
20
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
21
21
  import useDelayedLoader from '../useDelayedLoader';
22
+ const ErrorContent = ({ errorMessage }) => {
23
+ return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
24
+ };
22
25
  export const ProfileMetricsEmptyState = ({ message }) => {
23
26
  return (_jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: _jsx("p", { children: message }) }));
24
27
  };
@@ -58,11 +61,11 @@ export const useQueryRange = (client, queryExpression, start, end) => {
58
61
  const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, }) => {
59
62
  const { isLoading, response, error } = useQueryRange(queryClient, queryExpression, from, to);
60
63
  const isLoaderVisible = useDelayedLoader(isLoading);
61
- const { loader, onError, perf } = useParcaContext();
64
+ const { loader, onError, perf, authenticationErrorMessage } = useParcaContext();
62
65
  const { width, height, margin } = useMetricsGraphDimensions(comparing);
63
66
  useEffect(() => {
64
67
  if (error !== null) {
65
- onError?.(error, 'metricsGraph');
68
+ onError?.(error);
66
69
  }
67
70
  }, [error, onError]);
68
71
  useEffect(() => {
@@ -77,7 +80,10 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to,
77
80
  return _jsx(_Fragment, { children: loader });
78
81
  }
79
82
  if (error !== null) {
80
- return (_jsxs("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: [_jsx("strong", { className: "font-bold", children: "Error! " }), _jsx("span", { className: "block sm:inline", children: error.message })] }));
83
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
84
+ return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
85
+ }
86
+ return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(error.message) });
81
87
  }
82
88
  if (dataAvailable) {
83
89
  const handleSampleClick = (timestamp, _value, labels) => {
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.253",
3
+ "version": "0.16.254",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.86",
7
- "@parca/components": "^0.16.191",
7
+ "@parca/components": "^0.16.192",
8
8
  "@parca/dynamicsize": "^0.16.54",
9
9
  "@parca/hooks": "^0.0.23",
10
10
  "@parca/parser": "^0.16.55",
11
- "@parca/store": "^0.16.102",
12
- "@parca/utilities": "^0.0.30",
11
+ "@parca/store": "^0.16.103",
12
+ "@parca/utilities": "^0.0.31",
13
13
  "@tanstack/react-query": "^4.0.5",
14
14
  "@types/react-beautiful-dnd": "^13.1.3",
15
15
  "apache-arrow": "^12.0.0",
@@ -49,5 +49,5 @@
49
49
  "access": "public",
50
50
  "registry": "https://registry.npmjs.org/"
51
51
  },
52
- "gitHead": "b79ac4f2315e2fa9dc46a44f231ad328955bfd25"
52
+ "gitHead": "0ca31b9ddf1c2db1ccd5cd3c5e7d7f0e572299fd"
53
53
  }
@@ -18,7 +18,7 @@ import {Provider} from 'react-redux';
18
18
  import {QueryServiceClient} from '@parca/client';
19
19
  import {DateTimeRange, KeyDownProvider, useParcaContext} from '@parca/components';
20
20
  import {store} from '@parca/store';
21
- import type {NavigateFunction} from '@parca/utilities';
21
+ import {capitalizeOnlyFirstLetter, type NavigateFunction} from '@parca/utilities';
22
22
 
23
23
  import {ProfileSelection, ProfileSelectionFromParams, SuffixParams} from '..';
24
24
  import {QuerySelection, useProfileTypes} from '../ProfileSelector';
@@ -31,6 +31,17 @@ interface ProfileExplorerProps {
31
31
  navigateTo: NavigateFunction;
32
32
  }
33
33
 
34
+ const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
35
+ return (
36
+ <div
37
+ className="relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
38
+ role="alert"
39
+ >
40
+ <span className="block sm:inline">{errorMessage}</span>
41
+ </div>
42
+ );
43
+ };
44
+
34
45
  const getExpressionAsAString = (expression: string | []): string => {
35
46
  const x = Array.isArray(expression) ? expression.join() : expression;
36
47
  return x;
@@ -81,11 +92,11 @@ const ProfileExplorerApp = ({
81
92
  error: profileTypesError,
82
93
  } = useProfileTypes(queryClient);
83
94
 
84
- const {loader, noDataPrompt, onError} = useParcaContext();
95
+ const {loader, noDataPrompt, onError, authenticationErrorMessage} = useParcaContext();
85
96
 
86
97
  useEffect(() => {
87
98
  if (profileTypesError !== undefined && profileTypesError !== null) {
88
- onError?.(profileTypesError, 'ProfileExplorer');
99
+ onError?.(profileTypesError);
89
100
  }
90
101
  }, [profileTypesError, onError]);
91
102
 
@@ -166,15 +177,11 @@ const ProfileExplorerApp = ({
166
177
  }
167
178
 
168
179
  if (profileTypesError !== undefined && profileTypesError !== null) {
169
- return (
170
- <div
171
- className="relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
172
- role="alert"
173
- >
174
- <strong className="font-bold">Error! </strong>
175
- <span className="block sm:inline">{profileTypesError.message}</span>
176
- </div>
177
- );
180
+ if (authenticationErrorMessage !== undefined && profileTypesError.code === 'UNAUTHENTICATED') {
181
+ return <ErrorContent errorMessage={authenticationErrorMessage} />;
182
+ }
183
+
184
+ return <ErrorContent errorMessage={capitalizeOnlyFirstLetter(profileTypesError.message)} />;
178
185
  }
179
186
 
180
187
  const sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
@@ -19,7 +19,12 @@ import {Icon} from '@iconify/react';
19
19
  import {Flamegraph, FlamegraphArrow} from '@parca/client';
20
20
  import {Button, Select, useParcaContext, useURLState} from '@parca/components';
21
21
  import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
22
- import {divide, selectQueryParam, type NavigateFunction} from '@parca/utilities';
22
+ import {
23
+ capitalizeOnlyFirstLetter,
24
+ divide,
25
+ selectQueryParam,
26
+ type NavigateFunction,
27
+ } from '@parca/utilities';
23
28
 
24
29
  import DiffLegend from '../components/DiffLegend';
25
30
  import IcicleGraph from './IcicleGraph';
@@ -49,6 +54,10 @@ interface ProfileIcicleGraphProps {
49
54
  error?: any;
50
55
  }
51
56
 
57
+ const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
58
+ return <div className="flex justify-center p-10">{errorMessage}</div>;
59
+ };
60
+
52
61
  const ShowHideLegendButton = ({navigateTo}: {navigateTo?: NavigateFunction}): JSX.Element => {
53
62
  const [colorStackLegend, setStoreColorStackLegend] = useURLState({
54
63
  param: 'color_stack_legend',
@@ -152,7 +161,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
152
161
  error,
153
162
  width,
154
163
  }: ProfileIcicleGraphProps): JSX.Element {
155
- const {loader} = useParcaContext();
164
+ const {loader, onError, authenticationErrorMessage} = useParcaContext();
156
165
  const compareMode: boolean =
157
166
  selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
158
167
 
@@ -217,8 +226,13 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
217
226
  }
218
227
 
219
228
  if (error != null) {
220
- console.error('Error: ', error);
221
- return <div className="flex justify-center p-10">An error occurred: {error.message}</div>;
229
+ onError?.(error);
230
+
231
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
232
+ return <ErrorContent errorMessage={authenticationErrorMessage} />;
233
+ }
234
+
235
+ return <ErrorContent errorMessage={capitalizeOnlyFirstLetter(error.message)} />;
222
236
  }
223
237
 
224
238
  if (graph === undefined && arrow === undefined)
@@ -18,7 +18,7 @@ import {RpcError} from '@protobuf-ts/runtime-rpc';
18
18
  import {Duration, Label, QueryRangeResponse, QueryServiceClient, Timestamp} from '@parca/client';
19
19
  import {DateTimeRange, useGrpcMetadata, useParcaContext} from '@parca/components';
20
20
  import {Query} from '@parca/parser';
21
- import {getStepDuration} from '@parca/utilities';
21
+ import {capitalizeOnlyFirstLetter, getStepDuration} from '@parca/utilities';
22
22
 
23
23
  import {MergedProfileSelection, ProfileSelection} from '..';
24
24
  import MetricsGraph from '../MetricsGraph';
@@ -29,6 +29,17 @@ interface ProfileMetricsEmptyStateProps {
29
29
  message: string;
30
30
  }
31
31
 
32
+ const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
33
+ return (
34
+ <div
35
+ className="relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
36
+ role="alert"
37
+ >
38
+ <span className="block sm:inline">{errorMessage}</span>
39
+ </div>
40
+ );
41
+ };
42
+
32
43
  export const ProfileMetricsEmptyState = ({message}: ProfileMetricsEmptyStateProps): JSX.Element => {
33
44
  return (
34
45
  <div className="flex h-full w-full flex-col items-center justify-center">
@@ -114,12 +125,12 @@ const ProfileMetricsGraph = ({
114
125
  }: ProfileMetricsGraphProps): JSX.Element => {
115
126
  const {isLoading, response, error} = useQueryRange(queryClient, queryExpression, from, to);
116
127
  const isLoaderVisible = useDelayedLoader(isLoading);
117
- const {loader, onError, perf} = useParcaContext();
128
+ const {loader, onError, perf, authenticationErrorMessage} = useParcaContext();
118
129
  const {width, height, margin} = useMetricsGraphDimensions(comparing);
119
130
 
120
131
  useEffect(() => {
121
132
  if (error !== null) {
122
- onError?.(error, 'metricsGraph');
133
+ onError?.(error);
123
134
  }
124
135
  }, [error, onError]);
125
136
 
@@ -139,15 +150,11 @@ const ProfileMetricsGraph = ({
139
150
  }
140
151
 
141
152
  if (error !== null) {
142
- return (
143
- <div
144
- className="relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
145
- role="alert"
146
- >
147
- <strong className="font-bold">Error! </strong>
148
- <span className="block sm:inline">{error.message}</span>
149
- </div>
150
- );
153
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
154
+ return <ErrorContent errorMessage={authenticationErrorMessage} />;
155
+ }
156
+
157
+ return <ErrorContent errorMessage={capitalizeOnlyFirstLetter(error.message)} />;
151
158
  }
152
159
 
153
160
  if (dataAvailable) {