From 9e1ea8c990d4d52d3db518ec6e3e75422730be3a Mon Sep 17 00:00:00 2001 From: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com> Date: Thu, 2 Mar 2023 16:48:44 +0100 Subject: [PATCH] Alerting: Avoid printing [object][Object] in error message (#64023) Avoid printing [object][Object] in error message --- .../features/alerting/unified/Analytics.ts | 1 + .../unified/utils/messageFromError.test.ts | 35 +++++++++++++++++++ .../features/alerting/unified/utils/redux.ts | 13 ++++++- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 public/app/features/alerting/unified/utils/messageFromError.test.ts diff --git a/public/app/features/alerting/unified/Analytics.ts b/public/app/features/alerting/unified/Analytics.ts index 51c150d968b..ca8481e5136 100644 --- a/public/app/features/alerting/unified/Analytics.ts +++ b/public/app/features/alerting/unified/Analytics.ts @@ -14,6 +14,7 @@ export const LogMessages = { clickingAlertStateFilters: 'clicking alert state filters', cancelSavingAlertRule: 'user canceled alert rule creation', successSavingAlertRule: 'alert rule saved successfully', + unknownMessageFromError: 'unknown messageFromError', }; // logInfo from '@grafana/runtime' should be used, but it doesn't handle Grafana JS Agent and Sentry correctly diff --git a/public/app/features/alerting/unified/utils/messageFromError.test.ts b/public/app/features/alerting/unified/utils/messageFromError.test.ts new file mode 100644 index 00000000000..7197e9a6340 --- /dev/null +++ b/public/app/features/alerting/unified/utils/messageFromError.test.ts @@ -0,0 +1,35 @@ +import { FetchError } from '@grafana/runtime'; + +import { messageFromError, UNKNOW_ERROR } from './redux'; + +describe('messageFromError method', () => { + it('should return UNKNOW_ERROR message when error is an object and not having neither in the e.data.message and nor in e.message', () => { + const error: FetchError = { + config: { + url: '', + }, + data: { message: '', error: '', response: '' }, + status: 502, + statusText: '', + }; + + expect(messageFromError(error)).toBe(UNKNOW_ERROR); + }); + it('should return correct message in case of having message info in the e object (in e.data.message or in e.message)', () => { + const error: FetchError = { + config: { + url: '', + }, + data: { message: 'BLA BLA', error: 'this is the error', response: '' }, + status: 502, + statusText: 'BLu BLu', + }; + expect(messageFromError(error)).toBe('BLA BLA; this is the error'); + + const error2: Error = { + name: 'bla bla', + message: 'THIS IS THE MESSAGE ERROR', + }; + expect(messageFromError(error2)).toBe('THIS IS THE MESSAGE ERROR'); + }); +}); diff --git a/public/app/features/alerting/unified/utils/redux.ts b/public/app/features/alerting/unified/utils/redux.ts index 7333116bf9a..54a8eb757a6 100644 --- a/public/app/features/alerting/unified/utils/redux.ts +++ b/public/app/features/alerting/unified/utils/redux.ts @@ -4,6 +4,8 @@ import { AppEvents } from '@grafana/data'; import { FetchError, isFetchError } from '@grafana/runtime'; import { appEvents } from 'app/core/core'; +import { logInfo, LogMessages } from '../Analytics'; + export interface AsyncRequestState { result?: T; loading: boolean; @@ -137,6 +139,7 @@ export function withAppEvents( }); } +export const UNKNOW_ERROR = 'Unknown Error'; export function messageFromError(e: Error | FetchError | SerializedError): string { if (isFetchError(e)) { if (e.data?.message) { @@ -154,7 +157,15 @@ export function messageFromError(e: Error | FetchError | SerializedError): strin return e.statusText; } } - return (e as Error)?.message || String(e); + // message in e object, return message + const errorMessage = (e as Error)?.message; + if (errorMessage) { + return errorMessage; + } + // for some reason (upstream this code), sometimes we get an object without the message field neither in the e.data and nor in e.message + // in this case we want to avoid String(e) printing [object][object] + logInfo(LogMessages.unknownMessageFromError, { error: JSON.stringify(e) }); + return UNKNOW_ERROR; } export function isAsyncRequestMapSliceSettled(slice: AsyncRequestMapSlice): boolean {