diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/OneGraphExplorer/utils.js b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/OneGraphExplorer/utils.js
index 361077e1d8e..7169f220a5f 100644
--- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/OneGraphExplorer/utils.js
+++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/OneGraphExplorer/utils.js
@@ -64,7 +64,6 @@ export const clickRunQueryButton = () => {
'Could not find run query button in the DOM (.execute-button)'
);
programmaticallyTraceError(error);
- console.warn(error);
}
};
diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/Data/DataSources/CreateDataSource/Neon/useCreateHasuraCloudDatasource.ts b/frontend/libs/console/legacy-ce/src/lib/components/Services/Data/DataSources/CreateDataSource/Neon/useCreateHasuraCloudDatasource.ts
index 61f5b244d63..6f9f3abd6db 100644
--- a/frontend/libs/console/legacy-ce/src/lib/components/Services/Data/DataSources/CreateDataSource/Neon/useCreateHasuraCloudDatasource.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/Data/DataSources/CreateDataSource/Neon/useCreateHasuraCloudDatasource.ts
@@ -164,13 +164,10 @@ export function useCreateHasuraCloudDatasource(
setState(prevState => {
if (prevState.status === 'adding-env-var') {
// this is an unexpected error; so we need alerts about this
- programmaticallyTraceError(
- new Error('Failed creating env vars in Hasura'),
- {
- sourceError: error,
- errorMessage: error.message ?? '',
- }
- );
+ programmaticallyTraceError({
+ error: 'Failed creating env vars in Hasura',
+ cause: error,
+ });
return {
status: 'adding-env-var-failed',
payload: { dbUrl },
@@ -178,13 +175,10 @@ export function useCreateHasuraCloudDatasource(
// if adding data-source fails unexpectedly, set the error state
} else if (prevState.status === 'adding-data-source') {
// this is an unexpected error; so we need alerts about this
- programmaticallyTraceError(
- new Error('Failed adding created data source in Hasura'),
- {
- sourceError: error,
- errorMessage: error.message ?? '',
- }
- );
+ programmaticallyTraceError({
+ error: 'Failed adding created data source in Hasura',
+ cause: error,
+ });
return {
status: 'adding-data-source-failed',
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/components/Analytics.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/components/Analytics.tsx
index 5c734e8c5c4..c2863036671 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/components/Analytics.tsx
+++ b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/components/Analytics.tsx
@@ -134,7 +134,6 @@ export function Analytics(props: AnalyticsProps) {
const overrideError = new Error(
`All the following attributes will be overridden: ${overrideHtmlAttributes} for the element with name "${name}"`
);
- console.error(overrideError);
programmaticallyTraceError(overrideError);
}
}
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/programmaticallyTraceError.ts b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/programmaticallyTraceError.ts
index 61959fb2548..8a69739c2b5 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/programmaticallyTraceError.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/programmaticallyTraceError.ts
@@ -1,13 +1,113 @@
-import type { ExceptionContext } from './sentry/captureException';
+import * as Sentry from '@sentry/react';
import { captureException } from './sentry/captureException';
+type HumanReadableString = string;
+
+type Options = {
+ level?: 'error' | 'warning';
+ /**
+ * Logging to the Console has a specific purpose: Sentry is NOT enabled for every type of Console
+ * (at the time of writing, Sentry is enabled only for the Cloud Console). Logging to the browser's
+ * console allows the eventual customers that is trying to understand the root cause of a problem,
+ * to report what they see in the browser's console in the issue they are going to open.
+ */
+ logToConsole?: boolean;
+};
+
+type HumanReadableStringWithErrorCauseAndOptions = Options & {
+ error: HumanReadableString;
+ cause?: Error;
+};
+type ErrorWithOptions = Options & {
+ error: Error;
+};
+
+const noop = () => {};
+
/**
* Programmatically trace a caught error.
+ *
+ * @example
Simplest usage: pass just a string.
+ * programmaticallyTraceError('Something went wrong when updating the metadata')
+ *
+ * @example Simplest usage: pass the error you receive.
+ * catch (error) {
+ * programmaticallyTraceError(error)
+ * }
+ *
+ * @example Pass a human-readable message, but also the causing error.
+ * catch (error) {
+ * programmaticallyTraceError({ error: 'Something went wrong when updating the metadata', cause: error })
+ * }
*/
export function programmaticallyTraceError(
- error: Error,
- exceptionContext: ExceptionContext = {},
- level: 'error' | 'warning' = 'error'
+ errorOrErrorWithOptions:
+ | HumanReadableString
+ | Error
+ | HumanReadableStringWithErrorCauseAndOptions
+ | ErrorWithOptions
) {
- captureException(error, exceptionContext, level);
+ // --------------------------------------------------
+ // SIMPLE USAGE
+ // --------------------------------------------------
+
+ // If you pass a string, it's converted to an error and passed to Sentry.
+ if (typeof errorOrErrorWithOptions === 'string') {
+ captureException(new Error(errorOrErrorWithOptions));
+
+ return;
+ }
+
+ // If you pass an error, it's passed to Sentry as is.
+ if (errorOrErrorWithOptions instanceof Error) {
+ captureException(errorOrErrorWithOptions);
+
+ return;
+ }
+
+ // --------------------------------------------------
+ // OPTIONS-RICH USAGE
+ // --------------------------------------------------
+
+ const {
+ error,
+ level = 'error',
+ logToConsole = true,
+ } = errorOrErrorWithOptions;
+
+ const consoleLog = logToConsole
+ ? level === 'warning'
+ ? console.warn
+ : console.error
+ : noop;
+
+ // If you pass a cause, the cause itself is the original error and IT IS the error that will be
+ // tracked to Sentry. Instead, the passed human-friendly string will be added as a breadcrumb that
+ // you can see in Sentry right after the error.
+ if ('cause' in errorOrErrorWithOptions && !!errorOrErrorWithOptions.cause) {
+ const { cause } = errorOrErrorWithOptions;
+
+ const message = typeof error === 'string' ? error : error.message;
+
+ Sentry.addBreadcrumb({ level, message });
+ captureException(cause);
+ consoleLog(message);
+ consoleLog(cause);
+
+ return;
+ }
+
+ // The string will be converted to an error and tracked in Sentry
+ if (typeof error === 'string') {
+ const errorToLog = new Error(error);
+
+ captureException(errorToLog, level);
+ consoleLog(errorToLog);
+
+ return;
+ }
+
+ // The error is tracked in Sentry
+ captureException(error, level);
+ consoleLog(error);
}
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/captureException.ts b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/captureException.ts
index 1670edf06e4..ab98264ca9b 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/captureException.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/captureException.ts
@@ -1,23 +1,15 @@
import * as Sentry from '@sentry/react';
-export type ExceptionContext = {
- sourceError?: Error;
- errorMessage?: string;
-};
-
/**
- * This function allows us to capture caught exceptions that we want the engineering team to be
- * alerted about
+ * A simple wrapper around Sentry's captureException.
*
* @see https://docs.sentry.io/platforms/javascript/enriching-events/context/
*/
export function captureException(
error: Error,
- exceptionContext: ExceptionContext = {},
level: 'error' | 'warning' = 'error'
) {
Sentry.captureException(error, {
level,
- contexts: { debug: exceptionContext },
});
}
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/startSentryTracing.ts b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/startSentryTracing.ts
index d897a11a344..df37f520e13 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/startSentryTracing.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/Analytics/core/sentry/startSentryTracing.ts
@@ -56,6 +56,12 @@ export function startSentryTracing(globalVars: Globals, envVars: EnvVars) {
// sensitive data
dom: false,
}),
+
+ // ATTENTION: functions like programmaticallyTraceError could internally log errors to the
+ // browser's console, causing an infinite loop!
+ // new CaptureConsoleIntegration({
+ // levels: ['error'],
+ // }),
],
// Allow grouping logs by environment
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/components/QueryScreen/TemplateSummary.tsx b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/components/QueryScreen/TemplateSummary.tsx
index 6b5b42b4ac5..caabab644ba 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/components/QueryScreen/TemplateSummary.tsx
+++ b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/components/QueryScreen/TemplateSummary.tsx
@@ -62,13 +62,10 @@ export function TemplateSummary(props: Props) {
staleTime,
onError: (e: any) => {
// this is unexpected; so get alerted
- programmaticallyTraceError(
- new Error('failed to get a sample query in template summary'),
- {
- sourceError: e,
- errorMessage: e.message ?? '',
- }
- );
+ programmaticallyTraceError({
+ error: 'failed to get a sample query in template summary',
+ cause: e,
+ });
},
});
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/utils.ts b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/utils.ts
index 3c7e7cc787f..44884d95c8e 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/utils.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OnboardingWizard/utils.ts
@@ -118,7 +118,6 @@ export const emitOnboardingEvent = (variables: Record) => {
variables,
cloudHeaders
).catch(error => {
- console.error(error);
programmaticallyTraceError(error);
});
};
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OneClickDeployment/components/WorkflowProgress/WorkflowProgress.tsx b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OneClickDeployment/components/WorkflowProgress/WorkflowProgress.tsx
index 5da95e87a64..7d0d098c8bd 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OneClickDeployment/components/WorkflowProgress/WorkflowProgress.tsx
+++ b/frontend/libs/console/legacy-ce/src/lib/features/CloudOnboarding/OneClickDeployment/components/WorkflowProgress/WorkflowProgress.tsx
@@ -159,14 +159,10 @@ export function WorkflowProgress(props: WorkflowProgressProps) {
);
},
error => {
- programmaticallyTraceError(
- new Error('failed subscribing to one click deployment status'),
- {
- errorMessage: error.message,
- sourceError: error,
- },
- 'error'
- );
+ programmaticallyTraceError({
+ error: 'failed subscribing to one click deployment status',
+ cause: error,
+ });
}
);
return () => {
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useOnSetOpenTelemetryError.ts b/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useOnSetOpenTelemetryError.ts
index 66d74acedd0..54e21d2086c 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useOnSetOpenTelemetryError.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useOnSetOpenTelemetryError.ts
@@ -80,12 +80,9 @@ export function useOnSetOpenTelemetryError(
}
);
- programmaticallyTraceError(
- new Error(
- 'OpenTelemetry set_opentelemetry_config error not parsed',
- // @ts-expect-error This error will automatically disappear with Nx that targets new browsers by default
- { cause: err }
- )
- );
+ programmaticallyTraceError({
+ error: 'OpenTelemetry set_opentelemetry_config error not parsed',
+ cause: err instanceof Error ? err : undefined,
+ });
};
}
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useTrackTypeMisalignments.ts b/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useTrackTypeMisalignments.ts
index bcc0ae97216..a3b87c61119 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useTrackTypeMisalignments.ts
+++ b/frontend/libs/console/legacy-ce/src/lib/features/OpenTelemetry/OpenTelemetryProvider/hooks/useTrackTypeMisalignments.ts
@@ -58,11 +58,8 @@ export function useTrackTypeMisalignments(
}
);
- programmaticallyTraceError(
- new Error(
- 'OpenTelemetry metadata not parsed',
- // @ts-expect-error This error will automatically disappear with Nx that targets new browsers by default
- { cause: result.error }
- )
- );
+ programmaticallyTraceError({
+ error: 'OpenTelemetry metadata not parsed',
+ cause: result.error,
+ });
}