Logs Volume: update timeout message (#95277)
* Logs Volume: update timeout message * SupplementaryResultError: add list styles * Address lint issues * Update public/app/features/explore/Logs/LogsVolumePanelList.tsx Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com> --------- Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>
This commit is contained in:
co-authored by
Sven Grossmann
parent
5c9071a6c6
commit
142797032b
@@ -52,7 +52,7 @@ describe('LogsVolumePanelList', () => {
|
||||
expect(screen.getByText(message)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('a custom message for timeout errors', async () => {
|
||||
it('has a custom message for timeout errors', async () => {
|
||||
const onLoadCallback = jest.fn();
|
||||
renderPanel(
|
||||
{
|
||||
@@ -62,7 +62,8 @@ describe('LogsVolumePanelList', () => {
|
||||
},
|
||||
onLoadCallback
|
||||
);
|
||||
expect(screen.getByText('The logs volume query has timed out')).toBeInTheDocument();
|
||||
expect(screen.getByText('Unable to show log volume')).toBeInTheDocument();
|
||||
expect(screen.getByText(/The query is trying to access too much data/)).toBeInTheDocument();
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Retry' }));
|
||||
expect(onLoadCallback).toHaveBeenCalled();
|
||||
});
|
||||
@@ -72,4 +73,9 @@ describe('LogsVolumePanelList', () => {
|
||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||
expect(screen.getByText('No logs volume available')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show an info message with empty responses when the current state is streaming', async () => {
|
||||
renderPanel({ state: LoadingState.Streaming, data: [] });
|
||||
expect(screen.queryByText('No logs volume available')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
TimeZone,
|
||||
} from '@grafana/data';
|
||||
import { Button, InlineField, Alert, useStyles2, SeriesVisibilityChangeMode } from '@grafana/ui';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
|
||||
import { mergeLogsVolumeDataFrames, isLogsVolumeLimited, getLogsVolumeMaximumRange } from '../../logs/utils';
|
||||
import { SupplementaryResultError } from '../SupplementaryResultError';
|
||||
@@ -97,8 +98,29 @@ export const LogsVolumePanelList = ({
|
||||
} else if (timeoutError) {
|
||||
return (
|
||||
<SupplementaryResultError
|
||||
title="The logs volume query has timed out"
|
||||
title="Unable to show log volume"
|
||||
// Using info to avoid users thinking that the actual query has failed.
|
||||
message={
|
||||
<>
|
||||
<p>
|
||||
<Trans i18nKey="explore.logs.logs-volume.much-data">
|
||||
The query is trying to access too much data. Try one or more of the following:
|
||||
</Trans>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<Trans i18nKey="explore.logs.logs-volume.add-filters">
|
||||
Add more labels to your query to narrow down your search.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="explore.logs.logs-volume.decrease-timerange">
|
||||
Decrease the time range of your query.
|
||||
</Trans>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
}
|
||||
severity="info"
|
||||
suggestedAction="Retry"
|
||||
onSuggestedAction={onLoadLogsVolume}
|
||||
|
||||
@@ -27,4 +27,10 @@ describe('SupplementaryResultError', () => {
|
||||
await userEvent.click(button);
|
||||
expect(screen.getByText(message)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('allows arbitrary components in the message', async () => {
|
||||
const error = { data: { message: 'error' } };
|
||||
render(<SupplementaryResultError error={error} message={<div data-testid="custom-stuff" />} title={'Error'} />);
|
||||
expect(screen.getByTestId('custom-stuff')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,53 +1,59 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useState } from 'react';
|
||||
import { ReactNode, useState } from 'react';
|
||||
|
||||
import { DataQueryError, GrafanaTheme2 } from '@grafana/data';
|
||||
import { Alert, AlertVariant, Button, useTheme2 } from '@grafana/ui';
|
||||
|
||||
type Props = {
|
||||
error?: DataQueryError;
|
||||
message?: ReactNode;
|
||||
title: string;
|
||||
severity?: AlertVariant;
|
||||
suggestedAction?: string;
|
||||
onSuggestedAction?(): void;
|
||||
onRemove?(): void;
|
||||
};
|
||||
const SHORT_ERROR_MESSAGE_LIMIT = 100;
|
||||
export function SupplementaryResultError(props: Props) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const SHORT_ERROR_MESSAGE_LIMIT = 100;
|
||||
|
||||
const { error, title, suggestedAction, onSuggestedAction, onRemove, severity = 'warning' } = props;
|
||||
// generic get-error-message-logic, taken from
|
||||
// /public/app/features/explore/ErrorContainer.tsx
|
||||
const message = error?.message || error?.data?.message || '';
|
||||
const showButton = !isOpen && message.length > SHORT_ERROR_MESSAGE_LIMIT;
|
||||
const message = props.message ?? error?.message ?? error?.data?.message ?? '';
|
||||
const showButton = typeof message === 'string' && message.length > SHORT_ERROR_MESSAGE_LIMIT;
|
||||
const theme = useTheme2();
|
||||
const styles = getStyles(theme);
|
||||
|
||||
return (
|
||||
<div className={styles.supplementaryErrorContainer}>
|
||||
<Alert title={title} severity={severity} onRemove={onRemove}>
|
||||
<div className={styles.suggestedActionWrapper}>
|
||||
{showButton ? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
>
|
||||
Show details
|
||||
</Button>
|
||||
) : (
|
||||
message
|
||||
)}
|
||||
{suggestedAction && onSuggestedAction && (
|
||||
<div className={styles.suggestedActionWrapper}>
|
||||
{showButton ? (
|
||||
<div className={styles.suggestedActionWrapper}>
|
||||
{!isOpen ? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="xs"
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
>
|
||||
Show details
|
||||
</Button>
|
||||
) : (
|
||||
message
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.suggestedActionWrapper}>
|
||||
{message}
|
||||
{suggestedAction && onSuggestedAction && (
|
||||
<Button variant="primary" size="xs" onClick={onSuggestedAction}>
|
||||
{suggestedAction}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
@@ -59,13 +65,22 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
width: '50%',
|
||||
minWidth: `${theme.breakpoints.values.sm}px`,
|
||||
margin: '0 auto',
|
||||
[theme.breakpoints.down('lg')]: {
|
||||
width: '70%',
|
||||
},
|
||||
[theme.breakpoints.down('md')]: {
|
||||
width: '100%',
|
||||
},
|
||||
}),
|
||||
suggestedActionWrapper: css({
|
||||
height: theme.spacing(6),
|
||||
minHeight: theme.spacing(3),
|
||||
['button']: {
|
||||
position: 'absolute',
|
||||
right: theme.spacing(2),
|
||||
top: theme.spacing(7),
|
||||
bottom: theme.spacing(2),
|
||||
},
|
||||
['ul']: {
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -856,6 +856,11 @@
|
||||
"explore": {
|
||||
"add-to-dashboard": "Add to dashboard",
|
||||
"logs": {
|
||||
"logs-volume": {
|
||||
"add-filters": "Add more labels to your query to narrow down your search.",
|
||||
"decrease-timerange": "Decrease the time range of your query.",
|
||||
"much-data": "The query is trying to access too much data. Try one or more of the following:"
|
||||
},
|
||||
"maximum-pinned-logs": "Maximum of {{PINNED_LOGS_LIMIT}} pinned logs reached. Unpin a log to add another.",
|
||||
"no-logs-found": "No logs found.",
|
||||
"scan-for-older-logs": "Scan for older logs",
|
||||
|
||||
@@ -856,6 +856,11 @@
|
||||
"explore": {
|
||||
"add-to-dashboard": "Åđđ ŧő đäşĥþőäřđ",
|
||||
"logs": {
|
||||
"logs-volume": {
|
||||
"add-filters": "Åđđ mőřę ľäþęľş ŧő yőūř qūęřy ŧő ʼnäřřőŵ đőŵʼn yőūř şęäřčĥ.",
|
||||
"decrease-timerange": "Đęčřęäşę ŧĥę ŧįmę řäʼnģę őƒ yőūř qūęřy.",
|
||||
"much-data": "Ŧĥę qūęřy įş ŧřyįʼnģ ŧő äččęşş ŧőő mūčĥ đäŧä. Ŧřy őʼnę őř mőřę őƒ ŧĥę ƒőľľőŵįʼnģ:"
|
||||
},
|
||||
"maximum-pinned-logs": "Mäχįmūm őƒ {{PINNED_LOGS_LIMIT}} pįʼnʼnęđ ľőģş řęäčĥęđ. Ůʼnpįʼn ä ľőģ ŧő äđđ äʼnőŧĥęř.",
|
||||
"no-logs-found": "Ńő ľőģş ƒőūʼnđ.",
|
||||
"scan-for-older-logs": "Ŝčäʼn ƒőř őľđęř ľőģş",
|
||||
|
||||
Reference in New Issue
Block a user