From 5f1f7a826654ca2d7081e4d52c5e954eb1f7e29a Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Tue, 3 Nov 2020 13:40:44 -0800 Subject: [PATCH] Refactor error handling part 2 (#313) --- src/Common/DocumentClientUtilityBase.ts | 16 +-- src/Common/ErrorHandlingUtils.ts | 20 +-- src/Common/Logger.ts | 6 +- src/Common/QueriesClient.ts | 15 +-- src/Common/dataAccess/createCollection.ts | 2 +- src/Common/dataAccess/createDatabase.ts | 2 +- .../dataAccess/createStoredProcedure.ts | 2 +- src/Common/dataAccess/createTrigger.ts | 2 +- .../dataAccess/createUserDefinedFunction.ts | 4 +- src/Common/dataAccess/deleteCollection.ts | 2 +- src/Common/dataAccess/deleteDatabase.ts | 2 +- .../dataAccess/deleteStoredProcedure.ts | 2 +- src/Common/dataAccess/deleteTrigger.ts | 2 +- .../dataAccess/deleteUserDefinedFunction.ts | 2 +- .../getIndexTransformationProgress.ts | 2 +- src/Common/dataAccess/readCollection.ts | 2 +- src/Common/dataAccess/readCollectionOffer.ts | 2 +- .../dataAccess/readCollectionQuotaInfo.ts | 2 +- src/Common/dataAccess/readCollections.ts | 2 +- src/Common/dataAccess/readDatabaseOffer.ts | 2 +- src/Common/dataAccess/readDatabases.ts | 2 +- .../dataAccess/readMongoDBCollection.tsx | 2 +- src/Common/dataAccess/readOffers.ts | 2 +- src/Common/dataAccess/readStoredProcedures.ts | 2 +- src/Common/dataAccess/readTriggers.ts | 2 +- .../dataAccess/readUserDefinedFunctions.ts | 4 +- src/Common/dataAccess/updateCollection.ts | 2 +- src/Common/dataAccess/updateOffer.ts | 2 +- .../updateOfferThroughputBeyondLimit.ts | 4 +- .../dataAccess/updateStoredProcedure.ts | 2 +- src/Common/dataAccess/updateTrigger.ts | 2 +- .../dataAccess/updateUserDefinedFunction.ts | 4 +- src/Contracts/Diagnostics.ts | 2 +- .../Controls/Arcadia/ArcadiaMenuPicker.tsx | 9 +- .../Notebook/NotebookTerminalComponent.tsx | 11 +- .../CodeOfConductComponent.tsx | 7 +- .../GalleryViewerComponent.tsx | 20 +-- .../NotebookViewerComponent.tsx | 5 +- .../IndexingPolicyRefreshComponent.tsx | 2 +- src/Explorer/Explorer.ts | 53 ++++---- .../GremlinClient.test.ts | 6 +- .../GraphExplorerComponent/GremlinClient.ts | 32 ++--- .../Notebook/NotebookContainerClient.ts | 7 +- src/Explorer/Notebook/NotebookManager.ts | 3 +- src/Explorer/Panes/CopyNotebookPane.tsx | 14 +-- src/Explorer/Panes/GitHubReposPane.ts | 24 +--- .../Panes/PublishNotebookPaneAdapter.tsx | 24 ++-- src/Explorer/Tables/TableDataClient.ts | 114 +++++------------- src/GitHub/GitHubClient.ts | 11 +- src/GitHub/GitHubContentProvider.ts | 18 +-- src/GitHub/GitHubOAuthService.ts | 6 +- src/HostedExplorer.ts | 8 +- .../NotebookWorkspaceManager.ts | 13 +- src/Platform/Hosted/ArmResourceUtils.ts | 11 +- .../ArcadiaResourceManager.ts | 10 +- src/Utils/AuthorizationUtils.ts | 3 +- src/Utils/GalleryUtils.ts | 26 ++-- src/Utils/NotebookConfigurationUtils.ts | 5 +- 58 files changed, 229 insertions(+), 336 deletions(-) diff --git a/src/Common/DocumentClientUtilityBase.ts b/src/Common/DocumentClientUtilityBase.ts index bc5e3ed33..ded90cf05 100644 --- a/src/Common/DocumentClientUtilityBase.ts +++ b/src/Common/DocumentClientUtilityBase.ts @@ -58,8 +58,8 @@ export function executeStoredProcedure( (error: any) => { handleError( error, - `Failed to execute stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}`, - "ExecuteStoredProcedure" + "ExecuteStoredProcedure", + `Failed to execute stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}` ); deferred.reject(error); } @@ -88,7 +88,7 @@ export function queryDocumentsPage( deferred.resolve(result); }, (error: any) => { - handleError(error, `Failed to query ${entityName} for container ${resourceName}`, "QueryDocumentsPage"); + handleError(error, "QueryDocumentsPage", `Failed to query ${entityName} for container ${resourceName}`); deferred.reject(error); } ) @@ -109,7 +109,7 @@ export function readDocument(collection: ViewModels.CollectionBase, documentId: deferred.resolve(document); }, (error: any) => { - handleError(error, `Failed to read ${entityName} ${documentId.id()}`, "ReadDocument"); + handleError(error, "ReadDocument", `Failed to read ${entityName} ${documentId.id()}`); deferred.reject(error); } ) @@ -135,7 +135,7 @@ export function updateDocument( deferred.resolve(updatedDocument); }, (error: any) => { - handleError(error, `Failed to update ${entityName} ${documentId.id()}`, "UpdateDocument"); + handleError(error, "UpdateDocument", `Failed to update ${entityName} ${documentId.id()}`); deferred.reject(error); } ) @@ -157,7 +157,7 @@ export function createDocument(collection: ViewModels.CollectionBase, newDocumen deferred.resolve(savedDocument); }, (error: any) => { - handleError(error, `Error while creating new ${entityName} for container ${collection.id()}`, "CreateDocument"); + handleError(error, "CreateDocument", `Error while creating new ${entityName} for container ${collection.id()}`); deferred.reject(error); } ) @@ -179,7 +179,7 @@ export function deleteDocument(collection: ViewModels.CollectionBase, documentId deferred.resolve(response); }, (error: any) => { - handleError(error, `Error while deleting ${entityName} ${documentId.id()}`, "DeleteDocument"); + handleError(error, "DeleteDocument", `Error while deleting ${entityName} ${documentId.id()}`); deferred.reject(error); } ) @@ -205,7 +205,7 @@ export function deleteConflict( deferred.resolve(response); }, (error: any) => { - handleError(error, `Error while deleting conflict ${conflictId.id()}`, "DeleteConflict"); + handleError(error, "DeleteConflict", `Error while deleting conflict ${conflictId.id()}`); deferred.reject(error); } ) diff --git a/src/Common/ErrorHandlingUtils.ts b/src/Common/ErrorHandlingUtils.ts index e5acc6b49..2e2f51365 100644 --- a/src/Common/ErrorHandlingUtils.ts +++ b/src/Common/ErrorHandlingUtils.ts @@ -1,3 +1,4 @@ +import { ARMError } from "../Utils/arm/request"; import { HttpStatusCodes } from "./Constants"; import { MessageTypes } from "../Contracts/ExplorerContracts"; import { SubscriptionType } from "../Contracts/ViewModels"; @@ -5,28 +6,27 @@ import { logConsoleError } from "../Utils/NotificationConsoleUtils"; import { logError } from "./Logger"; import { sendMessage } from "./MessageHandler"; -export interface CosmosError { - code: number; - message?: string; -} - -export const handleError = (error: string | CosmosError, consoleErrorPrefix: string, area: string): void => { +export const handleError = (error: string | ARMError | Error, area: string, consoleErrorPrefix?: string): void => { const errorMessage = getErrorMessage(error); - const errorCode = typeof error === "string" ? undefined : error.code; + const errorCode = error instanceof ARMError ? error.code : undefined; + // logs error to data explorer console - logConsoleError(`${consoleErrorPrefix}:\n ${errorMessage}`); + const consoleErrorMessage = consoleErrorPrefix ? `${consoleErrorPrefix}:\n ${errorMessage}` : errorMessage; + logConsoleError(consoleErrorMessage); + // logs error to both app insight and kusto logError(errorMessage, area, errorCode); + // checks for errors caused by firewall and sends them to portal to handle sendNotificationForError(errorMessage, errorCode); }; -export const getErrorMessage = (error: string | CosmosError | Error): string => { +export const getErrorMessage = (error: string | Error): string => { const errorMessage = typeof error === "string" ? error : error.message; return replaceKnownError(errorMessage); }; -const sendNotificationForError = (errorMessage: string, errorCode: number): void => { +const sendNotificationForError = (errorMessage: string, errorCode: number | string): void => { if (errorCode === HttpStatusCodes.Forbidden) { if (errorMessage?.toLowerCase().indexOf("sharedoffer is disabled for your account") > 0) { return; diff --git a/src/Common/Logger.ts b/src/Common/Logger.ts index 39b3196c5..58186d21e 100644 --- a/src/Common/Logger.ts +++ b/src/Common/Logger.ts @@ -1,4 +1,3 @@ -import { CosmosError, getErrorMessage } from "./ErrorHandlingUtils"; import { sendMessage } from "./MessageHandler"; import { Diagnostics, MessageTypes } from "../Contracts/ExplorerContracts"; import { appInsights } from "../Shared/appInsights"; @@ -22,8 +21,7 @@ export function logWarning(message: string, area: string, code?: number): void { return _logEntry(entry); } -export function logError(error: string | CosmosError | Error, area: string, code?: number): void { - const errorMessage: string = getErrorMessage(error); +export function logError(errorMessage: string, area: string, code?: number | string): void { const entry: Diagnostics.LogEntry = _generateLogEntry(Diagnostics.LogEntryLevel.Error, errorMessage, area, code); return _logEntry(entry); } @@ -55,7 +53,7 @@ function _generateLogEntry( level: Diagnostics.LogEntryLevel, message: string, area: string, - code?: number + code?: number | string ): Diagnostics.LogEntry { return { timestamp: new Date().getUTCSeconds(), diff --git a/src/Common/QueriesClient.ts b/src/Common/QueriesClient.ts index 7a3106890..fb81d1c65 100644 --- a/src/Common/QueriesClient.ts +++ b/src/Common/QueriesClient.ts @@ -14,7 +14,6 @@ import { createDocument, deleteDocument, queryDocuments, queryDocumentsPage } fr import { createCollection } from "./dataAccess/createCollection"; import { handleError } from "./ErrorHandlingUtils"; import * as ErrorParserUtility from "./ErrorParserUtility"; -import * as Logger from "./Logger"; export class QueriesClient { private static readonly PartitionKey: DataModels.PartitionKey = { @@ -54,7 +53,7 @@ export class QueriesClient { return Promise.resolve(collection); }, (error: any) => { - handleError(error, "Failed to set up account for saving queries", "setupQueriesCollection"); + handleError(error, "setupQueriesCollection", "Failed to set up account for saving queries"); return Promise.reject(error); } ) @@ -105,11 +104,7 @@ export class QueriesClient { } else { errorMessage = parsedError.message; } - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Failed to save query ${query.queryName}: ${errorMessage}` - ); - Logger.logError(JSON.stringify(parsedError), "saveQuery"); + handleError(errorMessage, "saveQuery", `Failed to save query ${query.queryName}`); return Promise.reject(errorMessage); } ) @@ -159,14 +154,14 @@ export class QueriesClient { return Promise.resolve(queries); }, (error: any) => { - handleError(error, "Failed to fetch saved queries", "getSavedQueries"); + handleError(error, "getSavedQueries", "Failed to fetch saved queries"); return Promise.reject(error); } ); }, (error: any) => { // should never get into this state but we handle this regardless - handleError(error, "Failed to fetch saved queries", "getSavedQueries"); + handleError(error, "getSavedQueries", "Failed to fetch saved queries"); return Promise.reject(error); } ) @@ -218,7 +213,7 @@ export class QueriesClient { return Promise.resolve(); }, (error: any) => { - handleError(error, `Failed to delete query ${query.queryName}`, "deleteQuery"); + handleError(error, "deleteQuery", `Failed to delete query ${query.queryName}`); return Promise.reject(error); } ) diff --git a/src/Common/dataAccess/createCollection.ts b/src/Common/dataAccess/createCollection.ts index 6209a4b86..97a0c2a62 100644 --- a/src/Common/dataAccess/createCollection.ts +++ b/src/Common/dataAccess/createCollection.ts @@ -55,7 +55,7 @@ export const createCollection = async (params: DataModels.CreateCollectionParams logConsoleInfo(`Successfully created container ${params.collectionId}`); return collection; } catch (error) { - handleError(error, `Error while creating container ${params.collectionId}`, "CreateCollection"); + handleError(error, "CreateCollection", `Error while creating container ${params.collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/createDatabase.ts b/src/Common/dataAccess/createDatabase.ts index 22162e071..6f555b324 100644 --- a/src/Common/dataAccess/createDatabase.ts +++ b/src/Common/dataAccess/createDatabase.ts @@ -41,7 +41,7 @@ export async function createDatabase(params: DataModels.CreateDatabaseParams): P logConsoleInfo(`Successfully created database ${params.databaseId}`); return database; } catch (error) { - handleError(error, `Error while creating database ${params.databaseId}`, "CreateDatabase"); + handleError(error, "CreateDatabase", `Error while creating database ${params.databaseId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/createStoredProcedure.ts b/src/Common/dataAccess/createStoredProcedure.ts index a2281c213..d8f344ea3 100644 --- a/src/Common/dataAccess/createStoredProcedure.ts +++ b/src/Common/dataAccess/createStoredProcedure.ts @@ -70,7 +70,7 @@ export async function createStoredProcedure( .scripts.storedProcedures.create(storedProcedure); return response?.resource; } catch (error) { - handleError(error, `Error while creating stored procedure ${storedProcedure.id}`, "CreateStoredProcedure"); + handleError(error, "CreateStoredProcedure", `Error while creating stored procedure ${storedProcedure.id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/createTrigger.ts b/src/Common/dataAccess/createTrigger.ts index 179d0103e..a8c3f448f 100644 --- a/src/Common/dataAccess/createTrigger.ts +++ b/src/Common/dataAccess/createTrigger.ts @@ -65,7 +65,7 @@ export async function createTrigger( .scripts.triggers.create(trigger); return response.resource; } catch (error) { - handleError(error, `Error while creating trigger ${trigger.id}`, "CreateTrigger"); + handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/createUserDefinedFunction.ts b/src/Common/dataAccess/createUserDefinedFunction.ts index 30ff8be3a..bda4f0654 100644 --- a/src/Common/dataAccess/createUserDefinedFunction.ts +++ b/src/Common/dataAccess/createUserDefinedFunction.ts @@ -72,8 +72,8 @@ export async function createUserDefinedFunction( } catch (error) { handleError( error, - `Error while creating user defined function ${userDefinedFunction.id}`, - "CreateUserupdateUserDefinedFunction" + "CreateUserupdateUserDefinedFunction", + `Error while creating user defined function ${userDefinedFunction.id}` ); throw error; } finally { diff --git a/src/Common/dataAccess/deleteCollection.ts b/src/Common/dataAccess/deleteCollection.ts index cbe91b70f..5a5c4fd7d 100644 --- a/src/Common/dataAccess/deleteCollection.ts +++ b/src/Common/dataAccess/deleteCollection.ts @@ -23,7 +23,7 @@ export async function deleteCollection(databaseId: string, collectionId: string) } logConsoleInfo(`Successfully deleted container ${collectionId}`); } catch (error) { - handleError(error, `Error while deleting container ${collectionId}`, "DeleteCollection"); + handleError(error, "DeleteCollection", `Error while deleting container ${collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/deleteDatabase.ts b/src/Common/dataAccess/deleteDatabase.ts index e48f4ceb4..40029c0d2 100644 --- a/src/Common/dataAccess/deleteDatabase.ts +++ b/src/Common/dataAccess/deleteDatabase.ts @@ -25,7 +25,7 @@ export async function deleteDatabase(databaseId: string): Promise { } logConsoleInfo(`Successfully deleted database ${databaseId}`); } catch (error) { - handleError(error, `Error while deleting database ${databaseId}`, "DeleteDatabase"); + handleError(error, "DeleteDatabase", `Error while deleting database ${databaseId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/deleteStoredProcedure.ts b/src/Common/dataAccess/deleteStoredProcedure.ts index 317fb3167..fac47de33 100644 --- a/src/Common/dataAccess/deleteStoredProcedure.ts +++ b/src/Common/dataAccess/deleteStoredProcedure.ts @@ -34,7 +34,7 @@ export async function deleteStoredProcedure( .delete(); } } catch (error) { - handleError(error, `Error while deleting stored procedure ${storedProcedureId}`, "DeleteStoredProcedure"); + handleError(error, "DeleteStoredProcedure", `Error while deleting stored procedure ${storedProcedureId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/deleteTrigger.ts b/src/Common/dataAccess/deleteTrigger.ts index 0ec6ef4e1..f8a5713db 100644 --- a/src/Common/dataAccess/deleteTrigger.ts +++ b/src/Common/dataAccess/deleteTrigger.ts @@ -30,7 +30,7 @@ export async function deleteTrigger(databaseId: string, collectionId: string, tr .delete(); } } catch (error) { - handleError(error, `Error while deleting trigger ${triggerId}`, "DeleteTrigger"); + handleError(error, "DeleteTrigger", `Error while deleting trigger ${triggerId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/deleteUserDefinedFunction.ts b/src/Common/dataAccess/deleteUserDefinedFunction.ts index 83630169e..6160ac52c 100644 --- a/src/Common/dataAccess/deleteUserDefinedFunction.ts +++ b/src/Common/dataAccess/deleteUserDefinedFunction.ts @@ -30,7 +30,7 @@ export async function deleteUserDefinedFunction(databaseId: string, collectionId .delete(); } } catch (error) { - handleError(error, `Error while deleting user defined function ${id}`, "DeleteUserDefinedFunction"); + handleError(error, "DeleteUserDefinedFunction", `Error while deleting user defined function ${id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/getIndexTransformationProgress.ts b/src/Common/dataAccess/getIndexTransformationProgress.ts index 1c08fe847..fa0298fbc 100644 --- a/src/Common/dataAccess/getIndexTransformationProgress.ts +++ b/src/Common/dataAccess/getIndexTransformationProgress.ts @@ -20,7 +20,7 @@ export async function getIndexTransformationProgress(databaseId: string, collect response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string ); } catch (error) { - handleError(error, `Error while reading container ${collectionId}`, "ReadMongoDBCollection"); + handleError(error, "ReadMongoDBCollection", `Error while reading container ${collectionId}`); throw error; } clearMessage(); diff --git a/src/Common/dataAccess/readCollection.ts b/src/Common/dataAccess/readCollection.ts index 0b434ba03..ce886328d 100644 --- a/src/Common/dataAccess/readCollection.ts +++ b/src/Common/dataAccess/readCollection.ts @@ -13,7 +13,7 @@ export async function readCollection(databaseId: string, collectionId: string): .read(); collection = response.resource as DataModels.Collection; } catch (error) { - handleError(error, `Error while querying container ${collectionId}`, "ReadCollection"); + handleError(error, "ReadCollection", `Error while querying container ${collectionId}`); throw error; } clearMessage(); diff --git a/src/Common/dataAccess/readCollectionOffer.ts b/src/Common/dataAccess/readCollectionOffer.ts index ad4c8eef5..b98da68c6 100644 --- a/src/Common/dataAccess/readCollectionOffer.ts +++ b/src/Common/dataAccess/readCollectionOffer.ts @@ -56,7 +56,7 @@ export const readCollectionOffer = async ( } ); } catch (error) { - handleError(error, `Error while querying offer for collection ${params.collectionId}`, "ReadCollectionOffer"); + handleError(error, "ReadCollectionOffer", `Error while querying offer for collection ${params.collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/readCollectionQuotaInfo.ts b/src/Common/dataAccess/readCollectionQuotaInfo.ts index 574913f06..81565f821 100644 --- a/src/Common/dataAccess/readCollectionQuotaInfo.ts +++ b/src/Common/dataAccess/readCollectionQuotaInfo.ts @@ -37,7 +37,7 @@ export const readCollectionQuotaInfo = async ( return quota; } catch (error) { - handleError(error, `Error while querying quota info for container ${collection.id}`, "ReadCollectionQuotaInfo"); + handleError(error, "ReadCollectionQuotaInfo", `Error while querying quota info for container ${collection.id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/readCollections.ts b/src/Common/dataAccess/readCollections.ts index 405232f49..a6b741d91 100644 --- a/src/Common/dataAccess/readCollections.ts +++ b/src/Common/dataAccess/readCollections.ts @@ -29,7 +29,7 @@ export async function readCollections(databaseId: string): Promise { databases = sdkResponse.resources as DataModels.Database[]; } } catch (error) { - handleError(error, `Error while querying databases`, "ReadDatabases"); + handleError(error, "ReadDatabases", `Error while querying databases`); throw error; } clearMessage(); diff --git a/src/Common/dataAccess/readMongoDBCollection.tsx b/src/Common/dataAccess/readMongoDBCollection.tsx index 80013cf94..b66f8dc9c 100644 --- a/src/Common/dataAccess/readMongoDBCollection.tsx +++ b/src/Common/dataAccess/readMongoDBCollection.tsx @@ -22,7 +22,7 @@ export async function readMongoDBCollectionThroughRP( const response = await getMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId); collection = response.properties.resource; } catch (error) { - handleError(error, `Error while reading container ${collectionId}`, "ReadMongoDBCollection"); + handleError(error, "ReadMongoDBCollection", `Error while reading container ${collectionId}`); throw error; } clearMessage(); diff --git a/src/Common/dataAccess/readOffers.ts b/src/Common/dataAccess/readOffers.ts index 8fc743c9c..4afc452aa 100644 --- a/src/Common/dataAccess/readOffers.ts +++ b/src/Common/dataAccess/readOffers.ts @@ -17,7 +17,7 @@ export const readOffers = async (): Promise => { return []; } - handleError(error, `Error while querying offers`, "ReadOffers"); + handleError(error, "ReadOffers", `Error while querying offers`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/readStoredProcedures.ts b/src/Common/dataAccess/readStoredProcedures.ts index cb64654e6..75fb3111b 100644 --- a/src/Common/dataAccess/readStoredProcedures.ts +++ b/src/Common/dataAccess/readStoredProcedures.ts @@ -35,7 +35,7 @@ export async function readStoredProcedures( .fetchAll(); return response?.resources; } catch (error) { - handleError(error, `Failed to query stored procedures for container ${collectionId}`, "ReadStoredProcedures"); + handleError(error, "ReadStoredProcedures", `Failed to query stored procedures for container ${collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/readTriggers.ts b/src/Common/dataAccess/readTriggers.ts index d8b6f6469..85a96331f 100644 --- a/src/Common/dataAccess/readTriggers.ts +++ b/src/Common/dataAccess/readTriggers.ts @@ -35,7 +35,7 @@ export async function readTriggers( .fetchAll(); return response?.resources; } catch (error) { - handleError(error, `Failed to query triggers for container ${collectionId}`, "ReadTriggers"); + handleError(error, "ReadTriggers", `Failed to query triggers for container ${collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/readUserDefinedFunctions.ts b/src/Common/dataAccess/readUserDefinedFunctions.ts index 93d26f73a..f6990db7c 100644 --- a/src/Common/dataAccess/readUserDefinedFunctions.ts +++ b/src/Common/dataAccess/readUserDefinedFunctions.ts @@ -37,8 +37,8 @@ export async function readUserDefinedFunctions( } catch (error) { handleError( error, - `Failed to query user defined functions for container ${collectionId}`, - "ReadUserDefinedFunctions" + "ReadUserDefinedFunctions", + `Failed to query user defined functions for container ${collectionId}` ); throw error; } finally { diff --git a/src/Common/dataAccess/updateCollection.ts b/src/Common/dataAccess/updateCollection.ts index 3f317c069..3a45af694 100644 --- a/src/Common/dataAccess/updateCollection.ts +++ b/src/Common/dataAccess/updateCollection.ts @@ -59,7 +59,7 @@ export async function updateCollection( logConsoleInfo(`Successfully updated container ${collectionId}`); return collection; } catch (error) { - handleError(error, `Failed to update container ${collectionId}`, "UpdateCollection"); + handleError(error, "UpdateCollection", `Failed to update container ${collectionId}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/updateOffer.ts b/src/Common/dataAccess/updateOffer.ts index f7568abd1..24cd150c8 100644 --- a/src/Common/dataAccess/updateOffer.ts +++ b/src/Common/dataAccess/updateOffer.ts @@ -72,7 +72,7 @@ export const updateOffer = async (params: UpdateOfferParams): Promise => logConsoleInfo(`Successfully updated offer for ${offerResourceText}`); return updatedOffer; } catch (error) { - handleError(error, `Error updating offer for ${offerResourceText}`, "UpdateCollection"); + handleError(error, "UpdateCollection", `Error updating offer for ${offerResourceText}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/updateOfferThroughputBeyondLimit.ts b/src/Common/dataAccess/updateOfferThroughputBeyondLimit.ts index 1b713de85..93a8f8737 100644 --- a/src/Common/dataAccess/updateOfferThroughputBeyondLimit.ts +++ b/src/Common/dataAccess/updateOfferThroughputBeyondLimit.ts @@ -49,8 +49,8 @@ export async function updateOfferThroughputBeyondLimit(request: UpdateOfferThrou const error = await response.json(); handleError( error, - `Failed to request an increase in throughput for ${request.throughput}`, - "updateOfferThroughputBeyondLimit" + "updateOfferThroughputBeyondLimit", + `Failed to request an increase in throughput for ${request.throughput}` ); clearMessage(); throw error; diff --git a/src/Common/dataAccess/updateStoredProcedure.ts b/src/Common/dataAccess/updateStoredProcedure.ts index 17c498d66..4ca900905 100644 --- a/src/Common/dataAccess/updateStoredProcedure.ts +++ b/src/Common/dataAccess/updateStoredProcedure.ts @@ -64,7 +64,7 @@ export async function updateStoredProcedure( .replace(storedProcedure); return response?.resource; } catch (error) { - handleError(error, `Error while updating stored procedure ${storedProcedure.id}`, "UpdateStoredProcedure"); + handleError(error, "UpdateStoredProcedure", `Error while updating stored procedure ${storedProcedure.id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/updateTrigger.ts b/src/Common/dataAccess/updateTrigger.ts index 845e19274..49759bb2f 100644 --- a/src/Common/dataAccess/updateTrigger.ts +++ b/src/Common/dataAccess/updateTrigger.ts @@ -61,7 +61,7 @@ export async function updateTrigger( .replace(trigger); return response?.resource; } catch (error) { - handleError(error, `Error while updating trigger ${trigger.id}`, "UpdateTrigger"); + handleError(error, "UpdateTrigger", `Error while updating trigger ${trigger.id}`); throw error; } finally { clearMessage(); diff --git a/src/Common/dataAccess/updateUserDefinedFunction.ts b/src/Common/dataAccess/updateUserDefinedFunction.ts index 373cb1dcd..3e2ebab1b 100644 --- a/src/Common/dataAccess/updateUserDefinedFunction.ts +++ b/src/Common/dataAccess/updateUserDefinedFunction.ts @@ -66,8 +66,8 @@ export async function updateUserDefinedFunction( } catch (error) { handleError( error, - `Error while updating user defined function ${userDefinedFunction.id}`, - "UpdateUserupdateUserDefinedFunction" + "UpdateUserupdateUserDefinedFunction", + `Error while updating user defined function ${userDefinedFunction.id}` ); throw error; } finally { diff --git a/src/Contracts/Diagnostics.ts b/src/Contracts/Diagnostics.ts index 6a523bfd5..d6a54740a 100644 --- a/src/Contracts/Diagnostics.ts +++ b/src/Contracts/Diagnostics.ts @@ -46,7 +46,7 @@ export interface LogEntry { /** * The message code. */ - code?: number; + code?: number | string; /** * Any additional data to be logged. */ diff --git a/src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx b/src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx index c46dbebab..e4165421f 100644 --- a/src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx +++ b/src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx @@ -1,12 +1,9 @@ import * as React from "react"; import { ArcadiaWorkspace, SparkPool } from "../../../Contracts/DataModels"; import { DefaultButton, IButtonStyles } from "office-ui-fabric-react/lib/Button"; -import { - IContextualMenuItem, - IContextualMenuProps, - ContextualMenuItemType -} from "office-ui-fabric-react/lib/ContextualMenu"; +import { IContextualMenuItem, IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu"; import * as Logger from "../../../Common/Logger"; +import { getErrorMessage } from "../../../Common/ErrorHandlingUtils"; export interface ArcadiaMenuPickerProps { selectText?: string; @@ -47,7 +44,7 @@ export class ArcadiaMenuPicker extends React.Component ): string { if (!serverInfo.notebookServerEndpoint) { - const error = "Notebook server endpoint not defined. Terminal will fail to connect to jupyter server."; - Logger.logError(error, "NotebookTerminalComponent/createNotebookAppSrc"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError( + "Notebook server endpoint not defined. Terminal will fail to connect to jupyter server.", + "NotebookTerminalComponent/createNotebookAppSrc" + ); return ""; } diff --git a/src/Explorer/Controls/NotebookGallery/CodeOfConductComponent.tsx b/src/Explorer/Controls/NotebookGallery/CodeOfConductComponent.tsx index 02dc407e0..90ddf7b09 100644 --- a/src/Explorer/Controls/NotebookGallery/CodeOfConductComponent.tsx +++ b/src/Explorer/Controls/NotebookGallery/CodeOfConductComponent.tsx @@ -1,9 +1,8 @@ import * as React from "react"; import { JunoClient } from "../../../Juno/JunoClient"; import { HttpStatusCodes, CodeOfConductEndpoints } from "../../../Common/Constants"; -import * as Logger from "../../../Common/Logger"; -import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; import { Stack, Text, Checkbox, PrimaryButton, Link } from "office-ui-fabric-react"; +import { handleError } from "../../../Common/ErrorHandlingUtils"; export interface CodeOfConductComponentProps { junoClient: JunoClient; @@ -45,9 +44,7 @@ export class CodeOfConductComponent extends React.Component { - Logger.logError(error, "Explorer/getArcadiaToken"); + Logger.logError(getErrorMessage(error), "Explorer/getArcadiaToken"); resolve(undefined); } ); @@ -1551,7 +1551,7 @@ export default class Explorer { workspaceItems[i] = { ...workspace, sparkPools: sparkpools }; }, error => { - Logger.logError(error, "Explorer/this._arcadiaManager.listSparkPoolsAsync"); + Logger.logError(getErrorMessage(error), "Explorer/this._arcadiaManager.listSparkPoolsAsync"); } ); sparkPromises.push(promise); @@ -1559,7 +1559,7 @@ export default class Explorer { return Promise.all(sparkPromises).then(() => workspaceItems); } catch (error) { - handleError(error, "Get Arcadia workspaces failed", "Explorer/this._arcadiaManager.listWorkspacesAsync"); + handleError(error, "Explorer/this._arcadiaManager.listWorkspacesAsync", "Get Arcadia workspaces failed"); return Promise.resolve([]); } } @@ -1596,8 +1596,8 @@ export default class Explorer { this._isInitializingNotebooks = false; handleError( error, - `Failed to get notebook workspace connection info: ${getErrorMessage(error)}`, - "initNotebooks/getNotebookConnectionInfoAsync" + "initNotebooks/getNotebookConnectionInfoAsync", + `Failed to get notebook workspace connection info: ${getErrorMessage(error)}` ); throw error; } finally { @@ -1620,9 +1620,10 @@ export default class Explorer { public resetNotebookWorkspace() { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookClient) { - const error = "Attempt to reset notebook workspace, but notebook is not enabled"; - Logger.logError(error, "Explorer/resetNotebookWorkspace"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError( + "Attempt to reset notebook workspace, but notebook is not enabled", + "Explorer/resetNotebookWorkspace" + ); return; } const resetConfirmationDialogProps: DialogProps = { @@ -1647,7 +1648,7 @@ export default class Explorer { const workspaces = await this.notebookWorkspaceManager.getNotebookWorkspacesAsync(databaseAccount?.id); return workspaces && workspaces.length > 0 && workspaces.some(workspace => workspace.name === "default"); } catch (error) { - Logger.logError(error, "Explorer/_containsDefaultNotebookWorkspace"); + Logger.logError(getErrorMessage(error), "Explorer/_containsDefaultNotebookWorkspace"); return false; } } @@ -1673,7 +1674,7 @@ export default class Explorer { await this.notebookWorkspaceManager.startNotebookWorkspaceAsync(this.databaseAccount().id, "default"); } } catch (error) { - handleError(error, "Failed to initialize notebook workspace", "Explorer/ensureNotebookWorkspaceRunning"); + handleError(error, "Explorer/ensureNotebookWorkspaceRunning", "Failed to initialize notebook workspace"); } finally { clearMessage && clearMessage(); } @@ -2221,8 +2222,7 @@ export default class Explorer { public uploadFile(name: string, content: string, parent: NotebookContentItem): Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to upload notebook, but notebook is not enabled"; - Logger.logError(error, "Explorer/uploadFile"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/uploadFile"); throw new Error(error); } @@ -2403,8 +2403,7 @@ export default class Explorer { public renameNotebook(notebookFile: NotebookContentItem): Q.Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to rename notebook, but notebook is not enabled"; - Logger.logError(error, "Explorer/renameNotebook"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/renameNotebook"); throw new Error(error); } @@ -2452,8 +2451,7 @@ export default class Explorer { public onCreateDirectory(parent: NotebookContentItem): Q.Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to create notebook directory, but notebook is not enabled"; - Logger.logError(error, "Explorer/onCreateDirectory"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/onCreateDirectory"); throw new Error(error); } @@ -2474,8 +2472,7 @@ export default class Explorer { public readFile(notebookFile: NotebookContentItem): Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to read file, but notebook is not enabled"; - Logger.logError(error, "Explorer/downloadFile"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/downloadFile"); throw new Error(error); } @@ -2485,8 +2482,7 @@ export default class Explorer { public downloadFile(notebookFile: NotebookContentItem): Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to download file, but notebook is not enabled"; - Logger.logError(error, "Explorer/downloadFile"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/downloadFile"); throw new Error(error); } @@ -2567,7 +2563,7 @@ export default class Explorer { ); this.isNotebooksEnabledForAccount(isAccountInAllowedLocation); } catch (error) { - Logger.logError(error, "Explorer/isNotebooksEnabledForAccount"); + Logger.logError(getErrorMessage(error), "Explorer/isNotebooksEnabledForAccount"); this.isNotebooksEnabledForAccount(false); } } @@ -2596,7 +2592,7 @@ export default class Explorer { false; this.isSparkEnabledForAccount(isEnabled); } catch (error) { - Logger.logError(error, "Explorer/isSparkEnabledForAccount"); + Logger.logError(getErrorMessage(error), "Explorer/isSparkEnabledForAccount"); this.isSparkEnabledForAccount(false); } }; @@ -2621,7 +2617,7 @@ export default class Explorer { (featureStatus && featureStatus.properties && featureStatus.properties.state === "Registered") || false; return isEnabled; } catch (error) { - Logger.logError(error, "Explorer/isSparkEnabledForAccount"); + Logger.logError(getErrorMessage(error), "Explorer/isSparkEnabledForAccount"); return false; } }; @@ -2640,8 +2636,7 @@ export default class Explorer { public deleteNotebookFile(item: NotebookContentItem): Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to delete notebook file, but notebook is not enabled"; - Logger.logError(error, "Explorer/deleteNotebookFile"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/deleteNotebookFile"); throw new Error(error); } @@ -2690,8 +2685,7 @@ export default class Explorer { public onNewNotebookClicked(parent?: NotebookContentItem): void { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to create new notebook, but notebook is not enabled"; - Logger.logError(error, "Explorer/onNewNotebookClicked"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/onNewNotebookClicked"); throw new Error(error); } @@ -2776,8 +2770,7 @@ export default class Explorer { public refreshContentItem(item: NotebookContentItem): Promise { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { const error = "Attempt to refresh notebook list, but notebook is not enabled"; - Logger.logError(error, "Explorer/refreshContentItem"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error); + handleError(error, "Explorer/refreshContentItem"); return Promise.reject(new Error(error)); } @@ -2963,7 +2956,7 @@ export default class Explorer { } return tokenRefreshInterval; } catch (error) { - Logger.logError(error, "Explorer/getTokenRefreshInterval"); + Logger.logError(getErrorMessage(error), "Explorer/getTokenRefreshInterval"); return tokenRefreshInterval; } } diff --git a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts index f5256b9d5..5947c5439 100644 --- a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts +++ b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts @@ -94,7 +94,7 @@ describe("Gremlin Client", () => { it("should log and display error out on unknown requestId", () => { const gremlinClient = new GremlinClient(); - const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleMessage"); + const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError"); const logErrorSpy = sinon.spy(Logger, "logError"); gremlinClient.initialize(emptyParams); @@ -122,7 +122,7 @@ describe("Gremlin Client", () => { }); it("should not aggregate RU if not a number and reset totalRequestCharge to undefined", done => { - const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleMessage"); + const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError"); const logErrorSpy = sinon.spy(Logger, "logError"); const gremlinClient = new GremlinClient(); @@ -165,7 +165,7 @@ describe("Gremlin Client", () => { }); it("should not aggregate RU if undefined and reset totalRequestCharge to undefined", done => { - const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleMessage"); + const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError"); const logErrorSpy = sinon.spy(Logger, "logError"); const gremlinClient = new GremlinClient(); diff --git a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts index 7350f71d5..e66ae5cf2 100644 --- a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts +++ b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts @@ -7,8 +7,7 @@ import { GremlinSimpleClient, Result } from "./GremlinSimpleClient"; import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; import { HashMap } from "../../../Common/HashMap"; -import * as Logger from "../../../Common/Logger"; -import { getErrorMessage } from "../../../Common/ErrorHandlingUtils"; +import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils"; export interface GremlinClientParameters { endpoint: string; @@ -63,10 +62,10 @@ export class GremlinClient { const requestId = result.requestId; if (!requestId || !this.pendingResults.has(requestId)) { - const msg = `Error: ${errorMessage}, unknown requestId:${requestId} ${GremlinClient.getRequestChargeString( + const errorMsg = `Error: ${errorMessage}, unknown requestId:${requestId} ${GremlinClient.getRequestChargeString( result.requestCharge )}`; - GremlinClient.reportError(msg); + handleError(errorMsg, GremlinClient.LOG_AREA); // Fail all pending requests if no request id (fatal) if (!requestId) { @@ -130,15 +129,16 @@ export class GremlinClient { deferred.reject(error); this.pendingResults.delete(requestId); - GremlinClient.reportError( - `Aborting pending request ${requestId}. Error:${error} ${GremlinClient.getRequestChargeString(requestCharge)}` - ); + const errorMsg = `Aborting pending request ${requestId}. Error:${error} ${GremlinClient.getRequestChargeString( + requestCharge + )}`; + handleError(errorMsg, GremlinClient.LOG_AREA); } private flushResult(requestId: string) { if (!this.pendingResults.has(requestId)) { - const msg = `Unknown requestId:${requestId}`; - GremlinClient.reportError(msg); + const errorMsg = `Unknown requestId:${requestId}`; + handleError(errorMsg, GremlinClient.LOG_AREA); return; } @@ -156,8 +156,8 @@ export class GremlinClient { */ private storePendingResult(result: Result): boolean { if (!this.pendingResults.has(result.requestId)) { - const msg = `Dropping result for unknown requestId:${result.requestId}`; - GremlinClient.reportError(msg); + const errorMsg = `Dropping result for unknown requestId:${result.requestId}`; + handleError(errorMsg, GremlinClient.LOG_AREA); return false; } const pendingResults = this.pendingResults.get(result.requestId).result; @@ -177,9 +177,8 @@ export class GremlinClient { if (result.requestCharge === undefined || typeof result.requestCharge !== "number") { // Clear totalRequestCharge, even if it was a valid number as the total might be incomplete therefore incorrect pendingResults.totalRequestCharge = undefined; - GremlinClient.reportError( - `Unable to perform RU aggregation calculation with non numbers. Result request charge: ${result.requestCharge}. RequestId: ${result.requestId}` - ); + const errorMsg = `Unable to perform RU aggregation calculation with non numbers. Result request charge: ${result.requestCharge}. RequestId: ${result.requestId}`; + handleError(errorMsg, GremlinClient.LOG_AREA); } else { if (pendingResults.totalRequestCharge === undefined) { pendingResults.totalRequestCharge = 0; @@ -188,9 +187,4 @@ export class GremlinClient { } return pendingResults.isIncomplete; } - - private static reportError(msg: string): void { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); - Logger.logError(msg, GremlinClient.LOG_AREA); - } } diff --git a/src/Explorer/Notebook/NotebookContainerClient.ts b/src/Explorer/Notebook/NotebookContainerClient.ts index 78cfa0fa3..90f8a9a74 100644 --- a/src/Explorer/Notebook/NotebookContainerClient.ts +++ b/src/Explorer/Notebook/NotebookContainerClient.ts @@ -6,6 +6,7 @@ import * as Constants from "../../Common/Constants"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as Logger from "../../Common/Logger"; +import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; export class NotebookContainerClient { private reconnectingNotificationId: string; @@ -74,7 +75,7 @@ export class NotebookContainerClient { } return undefined; } catch (error) { - Logger.logError(error, "NotebookContainerClient/getMemoryUsage"); + Logger.logError(getErrorMessage(error), "NotebookContainerClient/getMemoryUsage"); if (!this.reconnectingNotificationId) { this.reconnectingNotificationId = NotificationConsoleUtils.logConsoleMessage( ConsoleDataType.InProgress, @@ -110,7 +111,7 @@ export class NotebookContainerClient { headers: { Authorization: authToken } }); } catch (error) { - Logger.logError(error, "NotebookContainerClient/resetWorkspace"); + Logger.logError(getErrorMessage(error), "NotebookContainerClient/resetWorkspace"); await this.recreateNotebookWorkspaceAsync(); } } @@ -140,7 +141,7 @@ export class NotebookContainerClient { await notebookWorkspaceManager.deleteNotebookWorkspaceAsync(explorer.databaseAccount().id, "default"); await notebookWorkspaceManager.createNotebookWorkspaceAsync(explorer.databaseAccount().id, "default"); } catch (error) { - Logger.logError(error, "NotebookContainerClient/recreateNotebookWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "NotebookContainerClient/recreateNotebookWorkspaceAsync"); return Promise.reject(error); } } diff --git a/src/Explorer/Notebook/NotebookManager.ts b/src/Explorer/Notebook/NotebookManager.ts index 2fe8748d0..932d80e13 100644 --- a/src/Explorer/Notebook/NotebookManager.ts +++ b/src/Explorer/Notebook/NotebookManager.ts @@ -26,6 +26,7 @@ import { ImmutableNotebook } from "@nteract/commutable"; import Explorer from "../Explorer"; import { ContextualPaneBase } from "../Panes/ContextualPaneBase"; import { CopyNotebookPaneAdapter } from "../Panes/CopyNotebookPane"; +import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; export interface NotebookManagerOptions { container: Explorer; @@ -147,7 +148,7 @@ export default class NotebookManager { // Octokit's error handler uses any // eslint-disable-next-line @typescript-eslint/no-explicit-any private onGitHubClientError = (error: any): void => { - Logger.logError(error, "NotebookManager/onGitHubClientError"); + Logger.logError(getErrorMessage(error), "NotebookManager/onGitHubClientError"); if (error.status === HttpStatusCodes.Unauthorized) { this.gitHubOAuthService.resetToken(); diff --git a/src/Explorer/Panes/CopyNotebookPane.tsx b/src/Explorer/Panes/CopyNotebookPane.tsx index 586af6318..1ef61eb3a 100644 --- a/src/Explorer/Panes/CopyNotebookPane.tsx +++ b/src/Explorer/Panes/CopyNotebookPane.tsx @@ -1,7 +1,6 @@ import ko from "knockout"; import * as React from "react"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; -import * as Logger from "../../Common/Logger"; import { JunoClient, IPinnedRepo } from "../../Juno/JunoClient"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import Explorer from "../Explorer"; @@ -13,6 +12,7 @@ import { HttpStatusCodes } from "../../Common/Constants"; import * as GitHubUtils from "../../Utils/GitHubUtils"; import { NotebookContentItemType, NotebookContentItem } from "../Notebook/NotebookContentItem"; import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; +import { handleError, getErrorMessage } from "../../Common/ErrorHandlingUtils"; interface Location { type: "MyNotebooks" | "GitHub"; @@ -90,9 +90,7 @@ export class CopyNotebookPaneAdapter implements ReactAdapter { if (this.gitHubOAuthService.isLoggedIn()) { const response = await this.junoClient.getPinnedRepos(this.gitHubOAuthService.getTokenObservable()()?.scope); if (response.status !== HttpStatusCodes.OK && response.status !== HttpStatusCodes.NoContent) { - const message = `Received HTTP ${response.status} when fetching pinned repos`; - Logger.logError(message, "CopyNotebookPaneAdapter/submit"); - NotificationConsoleUtils.logConsoleError(message); + handleError(`Received HTTP ${response.status} when fetching pinned repos`, "CopyNotebookPaneAdapter/submit"); } if (response.data?.length > 0) { @@ -134,12 +132,10 @@ export class CopyNotebookPaneAdapter implements ReactAdapter { NotificationConsoleUtils.logConsoleInfo(`Successfully copied ${this.name} to ${destination}`); } catch (error) { + const errorMessage = getErrorMessage(error); this.formError = `Failed to copy ${this.name} to ${destination}`; - this.formErrorDetail = `${error}`; - - const message = `${this.formError}: ${this.formErrorDetail}`; - Logger.logError(message, "CopyNotebookPaneAdapter/submit"); - NotificationConsoleUtils.logConsoleError(message); + this.formErrorDetail = `${errorMessage}`; + handleError(errorMessage, "CopyNotebookPaneAdapter/submit", this.formError); return; } finally { clearMessage && clearMessage(); diff --git a/src/Explorer/Panes/GitHubReposPane.ts b/src/Explorer/Panes/GitHubReposPane.ts index a18f7d867..403abfd75 100644 --- a/src/Explorer/Panes/GitHubReposPane.ts +++ b/src/Explorer/Panes/GitHubReposPane.ts @@ -1,6 +1,5 @@ import _ from "underscore"; import { Areas, HttpStatusCodes } from "../../Common/Constants"; -import * as Logger from "../../Common/Logger"; import * as ViewModels from "../../Contracts/ViewModels"; import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../GitHub/GitHubClient"; import { IPinnedRepo, JunoClient } from "../../Juno/JunoClient"; @@ -8,13 +7,12 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import * as GitHubUtils from "../../Utils/GitHubUtils"; import { JunoUtils } from "../../Utils/JunoUtils"; -import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import { AuthorizeAccessComponent } from "../Controls/GitHub/AuthorizeAccessComponent"; import { GitHubReposComponent, GitHubReposComponentProps, RepoListItem } from "../Controls/GitHub/GitHubReposComponent"; import { GitHubReposComponentAdapter } from "../Controls/GitHub/GitHubReposComponentAdapter"; import { BranchesProps, PinnedReposProps, UnpinnedReposProps } from "../Controls/GitHub/ReposListComponent"; -import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ContextualPaneBase } from "./ContextualPaneBase"; +import { handleError } from "../../Common/ErrorHandlingUtils"; interface GitHubReposPaneOptions extends ViewModels.PaneOptions { gitHubClient: GitHubClient; @@ -105,9 +103,7 @@ export class GitHubReposPane extends ContextualPaneBase { throw new Error(`Received HTTP ${response.status} when saving pinned repos`); } } catch (error) { - const message = `Failed to save pinned repos: ${error}`; - Logger.logError(message, "GitHubReposPane/submit"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubReposPane/submit", "Failed to save pinned repos"); } } } @@ -206,9 +202,7 @@ export class GitHubReposPane extends ContextualPaneBase { branchesProps.lastPageInfo = response.pageInfo; } } catch (error) { - const message = `Failed to fetch branches: ${error}`; - Logger.logError(message, "GitHubReposPane/loadMoreBranches"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubReposPane/loadMoreBranches", "Failed to fetch branches"); } branchesProps.isLoading = false; @@ -236,9 +230,7 @@ export class GitHubReposPane extends ContextualPaneBase { this.unpinnedReposProps.repos = this.calculateUnpinnedRepos(); } } catch (error) { - const message = `Failed to fetch unpinned repos: ${error}`; - Logger.logError(message, "GitHubReposPane/loadMoreUnpinnedRepos"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubReposPane/loadMoreUnpinnedRepos", "Failed to fetch unpinned repos"); } this.unpinnedReposProps.isLoading = false; @@ -255,9 +247,7 @@ export class GitHubReposPane extends ContextualPaneBase { return response.data; } catch (error) { - const message = `Failed to fetch repo: ${error}`; - Logger.logError(message, "GitHubReposPane/getRepo"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubReposPane/getRepo", "Failed to fetch repo"); return Promise.resolve(undefined); } } @@ -320,9 +310,7 @@ export class GitHubReposPane extends ContextualPaneBase { this.triggerRender(); } } catch (error) { - const message = `Failed to fetch pinned repos: ${error}`; - Logger.logError(message, "GitHubReposPane/refreshPinnedReposListItems"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubReposPane/refreshPinnedReposListItems", "Failed to fetch pinned repos"); } } diff --git a/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx b/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx index c8f94f7d2..967355251 100644 --- a/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx +++ b/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx @@ -1,17 +1,16 @@ import ko from "knockout"; import * as React from "react"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; -import * as Logger from "../../Common/Logger"; import Explorer from "../Explorer"; import { JunoClient } from "../../Juno/JunoClient"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; -import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent"; import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./PublishNotebookPaneComponent"; import { ImmutableNotebook } from "@nteract/commutable/src"; import { toJS } from "@nteract/commutable"; import { CodeOfConductComponent } from "../Controls/NotebookGallery/CodeOfConductComponent"; import { HttpStatusCodes } from "../../Common/Constants"; +import { handleError, getErrorMessage } from "../../Common/ErrorHandlingUtils"; export class PublishNotebookPaneAdapter implements ReactAdapter { parameters: ko.Observable; @@ -111,9 +110,11 @@ export class PublishNotebookPaneAdapter implements ReactAdapter { this.isCodeOfConductAccepted = response.data; } catch (error) { - const message = `Failed to check if code of conduct was accepted: ${error}`; - Logger.logError(message, "PublishNotebookPaneAdapter/isCodeOfConductAccepted"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError( + error, + "PublishNotebookPaneAdapter/isCodeOfConductAccepted", + "Failed to check if code of conduct was accepted" + ); } } else { this.isCodeOfConductAccepted = true; @@ -170,12 +171,10 @@ export class PublishNotebookPaneAdapter implements ReactAdapter { } } } catch (error) { + const errorMessage = getErrorMessage(error); this.formError = `Failed to publish ${this.name} to gallery`; - this.formErrorDetail = `${error}`; - - const message = `${this.formError}: ${this.formErrorDetail}`; - Logger.logError(message, "PublishNotebookPaneAdapter/submit"); - NotificationConsoleUtils.logConsoleError(message); + this.formErrorDetail = `${errorMessage}`; + handleError(errorMessage, "PublishNotebookPaneAdapter/submit", this.formError); return; } finally { clearPublishingMessage(); @@ -189,10 +188,7 @@ export class PublishNotebookPaneAdapter implements ReactAdapter { private createFormErrorForLargeImageSelection = (formError: string, formErrorDetail: string, area: string): void => { this.formError = formError; this.formErrorDetail = formErrorDetail; - - const message = `${this.formError}: ${this.formErrorDetail}`; - Logger.logError(message, area); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(formErrorDetail, area, formError); this.triggerRender(); }; diff --git a/src/Explorer/Tables/TableDataClient.ts b/src/Explorer/Tables/TableDataClient.ts index 1dda5b9b4..ba6ae246d 100644 --- a/src/Explorer/Tables/TableDataClient.ts +++ b/src/Explorer/Tables/TableDataClient.ts @@ -7,16 +7,14 @@ import { ConsoleDataType } from "../../Explorer/Menus/NotificationConsole/Notifi import * as Constants from "../../Common/Constants"; import * as Entities from "./Entities"; import * as HeadersUtility from "../../Common/HeadersUtility"; -import * as Logger from "../../Common/Logger"; import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; import * as TableConstants from "./Constants"; import * as TableEntityProcessor from "./TableEntityProcessor"; import * as ViewModels from "../../Contracts/ViewModels"; -import { MessageTypes } from "../../Contracts/ExplorerContracts"; -import { sendMessage } from "../../Common/MessageHandler"; import Explorer from "../Explorer"; import { queryDocuments, deleteDocument, updateDocument, createDocument } from "../../Common/DocumentClientUtilityBase"; import { configContext } from "../../ConfigContext"; +import { handleError } from "../../Common/ErrorHandlingUtils"; export interface CassandraTableKeys { partitionKeys: CassandraTableKey[]; @@ -188,14 +186,9 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(entity); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while adding new row to table ${collection.id()}:\n ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "AddRowCassandra", reason.code); - this._checkForbiddenError(reason); - deferred.reject(reason); + error => { + handleError(error, "AddRowCassandra", `Error while adding new row to table ${collection.id()}`); + deferred.reject(error); } ) .finally(() => { @@ -267,14 +260,9 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(newEntity); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Failed to update row ${newEntity.RowKey._}: ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "UpdateRowCassandra", reason.code); - this._checkForbiddenError(reason); - deferred.reject(reason); + error => { + handleError(error, "UpdateRowCassandra", `Failed to update row ${newEntity.RowKey._}`); + deferred.reject(error); } ) .finally(() => { @@ -332,16 +320,11 @@ export class CassandraAPIDataClient extends TableDataClient { ContinuationToken: data.paginationToken }); }, - reason => { + (error: any) => { if (shouldNotify) { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Failed to query rows for table ${collection.id()}: ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "QueryDocumentsCassandra", reason.status); - this._checkForbiddenError(reason); + handleError(error, "QueryDocumentsCassandra", `Failed to query rows for table ${collection.id()}`); } - deferred.reject(reason); + deferred.reject(error); } ) .done(() => { @@ -379,13 +362,8 @@ export class CassandraAPIDataClient extends TableDataClient { `Successfully deleted row ${currEntityToDelete.RowKey._}` ); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while deleting row ${currEntityToDelete.RowKey._}:\n ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "DeleteRowCassandra", reason.code); - this._checkForbiddenError(reason); + error => { + handleError(error, "DeleteRowCassandra", `Error while deleting row ${currEntityToDelete.RowKey._}`); } ) .finally(() => { @@ -420,14 +398,13 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while creating a keyspace with query ${createKeyspaceQuery}:\n ${JSON.stringify(reason)}` + error => { + handleError( + error, + "CreateKeyspaceCassandra", + `Error while creating a keyspace with query ${createKeyspaceQuery}` ); - Logger.logError(JSON.stringify(reason), "CreateKeyspaceCassandra", reason.code); - this._checkForbiddenError(reason); - deferred.reject(reason); + deferred.reject(error); } ) .finally(() => { @@ -467,14 +444,9 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while creating a table with query ${createTableQuery}:\n ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "CreateTableCassandra", reason.code); - this._checkForbiddenError(reason); - deferred.reject(reason); + error => { + handleError(error, "CreateTableCassandra", `Error while creating a table with query ${createTableQuery}`); + deferred.reject(error); } ) .finally(() => { @@ -508,14 +480,13 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while deleting resource with query ${deleteQuery}:\n ${JSON.stringify(reason)}` + error => { + handleError( + error, + "DeleteKeyspaceOrTableCassandra", + `Error while deleting resource with query ${deleteQuery}` ); - Logger.logError(JSON.stringify(reason), "DeleteKeyspaceOrTableCassandra", reason.code); - this._checkForbiddenError(reason); - deferred.reject(reason); + deferred.reject(error); } ) .finally(() => { @@ -563,14 +534,9 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(data); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error fetching keys for table ${collection.id()}:\n ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "FetchKeysCassandra", reason.status); - this._checkForbiddenError(reason); - deferred.reject(reason); + (error: any) => { + handleError(error, "FetchKeysCassandra", `Error fetching keys for table ${collection.id()}`); + deferred.reject(error); } ) .done(() => { @@ -618,14 +584,9 @@ export class CassandraAPIDataClient extends TableDataClient { ); deferred.resolve(data.columns); }, - reason => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error fetching schema for table ${collection.id()}:\n ${JSON.stringify(reason)}` - ); - Logger.logError(JSON.stringify(reason), "FetchSchemaCassandra", reason.status); - this._checkForbiddenError(reason); - deferred.reject(reason); + (error: any) => { + handleError(error, "FetchSchemaCassandra", `Error fetching schema for table ${collection.id()}`); + deferred.reject(error); } ) .done(() => { @@ -712,13 +673,4 @@ export class CassandraAPIDataClient extends TableDataClient { displayTokenRenewalPromptForStatus(xhrObj.status); }; - - private _checkForbiddenError(reason: any) { - if (reason && reason.code === Constants.HttpStatusCodes.Forbidden) { - sendMessage({ - type: MessageTypes.ForbiddenError, - reason: typeof reason === "string" ? "reason" : JSON.stringify(reason) - }); - } - } } diff --git a/src/GitHub/GitHubClient.ts b/src/GitHub/GitHubClient.ts index 64ed9e2d1..6125836cf 100644 --- a/src/GitHub/GitHubClient.ts +++ b/src/GitHub/GitHubClient.ts @@ -3,6 +3,7 @@ import { HttpStatusCodes } from "../Common/Constants"; import * as Logger from "../Common/Logger"; import UrlUtility from "../Common/UrlUtility"; import { NotebookUtil } from "../Explorer/Notebook/NotebookUtil"; +import { getErrorMessage } from "../Common/ErrorHandlingUtils"; export interface IGitHubPageInfo { endCursor: string; @@ -244,7 +245,7 @@ export class GitHubClient { data: GitHubClient.toGitHubRepo(response.repository) }; } catch (error) { - GitHubClient.log(Logger.logError, `GitHubClient.getRepoAsync failed: ${error}`); + Logger.logError(getErrorMessage(error), "GitHubClient.Octokit", "GitHubClient.getRepoAsync failed"); return { status: GitHubClient.SelfErrorCode, data: undefined @@ -265,7 +266,7 @@ export class GitHubClient { pageInfo: GitHubClient.toGitHubPageInfo(response.viewer.repositories.pageInfo) }; } catch (error) { - GitHubClient.log(Logger.logError, `GitHubClient.getReposAsync failed: ${error}`); + Logger.logError(getErrorMessage(error), "GitHubClient.Octokit", "GitHubClient.getRepoAsync failed"); return { status: GitHubClient.SelfErrorCode, data: undefined @@ -294,7 +295,7 @@ export class GitHubClient { pageInfo: GitHubClient.toGitHubPageInfo(response.repository.refs.pageInfo) }; } catch (error) { - GitHubClient.log(Logger.logError, `GitHubClient.getBranchesAsync failed: ${error}`); + Logger.logError(getErrorMessage(error), "GitHubClient.Octokit", "GitHubClient.getBranchesAsync failed"); return { status: GitHubClient.SelfErrorCode, data: undefined @@ -359,7 +360,7 @@ export class GitHubClient { data }; } catch (error) { - GitHubClient.log(Logger.logError, `GitHubClient.getContentsAsync failed: ${error}`); + Logger.logError(getErrorMessage(error), "GitHubClient.Octokit", "GitHubClient.getContentsAsync failed"); return { status: GitHubClient.SelfErrorCode, data: undefined @@ -503,7 +504,7 @@ export class GitHubClient { debug: () => {}, info: (message?: any) => GitHubClient.log(Logger.logInfo, message), warn: (message?: any) => GitHubClient.log(Logger.logWarning, message), - error: (message?: any) => GitHubClient.log(Logger.logError, message) + error: (error?: any) => Logger.logError(getErrorMessage(error), "GitHubClient.Octokit") } }); diff --git a/src/GitHub/GitHubContentProvider.ts b/src/GitHub/GitHubContentProvider.ts index 6142b7a6f..c406be440 100644 --- a/src/GitHub/GitHubContentProvider.ts +++ b/src/GitHub/GitHubContentProvider.ts @@ -41,7 +41,7 @@ export class GitHubContentProvider implements IContentProvider { return this.createSuccessAjaxResponse(HttpStatusCodes.NoContent, undefined); } catch (error) { - Logger.logError(error, "GitHubContentProvider/remove", error.errno); + Logger.logError(getErrorMessage(error), "GitHubContentProvider/remove", error.errno); return this.createErrorAjaxResponse(error); } }) @@ -65,7 +65,7 @@ export class GitHubContentProvider implements IContentProvider { return this.createSuccessAjaxResponse(HttpStatusCodes.OK, this.createContentModel(uri, content.data, params)); } catch (error) { - Logger.logError(error, "GitHubContentProvider/get", error.errno); + Logger.logError(getErrorMessage(error), "GitHubContentProvider/get", error.errno); return this.createErrorAjaxResponse(error); } }) @@ -105,7 +105,7 @@ export class GitHubContentProvider implements IContentProvider { this.createContentModel(newUri, gitHubFile, { content: 0 }) ); } catch (error) { - Logger.logError(error, "GitHubContentProvider/update", error.errno); + Logger.logError(getErrorMessage(error), "GitHubContentProvider/update", error.errno); return this.createErrorAjaxResponse(error); } }) @@ -182,7 +182,7 @@ export class GitHubContentProvider implements IContentProvider { this.createContentModel(newUri, newGitHubFile, { content: 0 }) ); } catch (error) { - Logger.logError(error, "GitHubContentProvider/create", error.errno); + Logger.logError(getErrorMessage(error), "GitHubContentProvider/create", error.errno); return this.createErrorAjaxResponse(error); } }) @@ -260,7 +260,7 @@ export class GitHubContentProvider implements IContentProvider { this.createContentModel(uri, gitHubFile, { content: 0 }) ); } catch (error) { - Logger.logError(error, "GitHubContentProvider/update", error.errno); + Logger.logError(getErrorMessage(error), "GitHubContentProvider/update", error.errno); return this.createErrorAjaxResponse(error); } }) @@ -269,25 +269,25 @@ export class GitHubContentProvider implements IContentProvider { public listCheckpoints(_: ServerConfig, path: string): Observable { const error = new GitHubContentProviderError("Not implemented"); - Logger.logError(error, "GitHubContentProvider/listCheckpoints", error.errno); + Logger.logError(error.message, "GitHubContentProvider/listCheckpoints", error.errno); return of(this.createErrorAjaxResponse(error)); } public createCheckpoint(_: ServerConfig, path: string): Observable { const error = new GitHubContentProviderError("Not implemented"); - Logger.logError(error, "GitHubContentProvider/createCheckpoint", error.errno); + Logger.logError(error.message, "GitHubContentProvider/createCheckpoint", error.errno); return of(this.createErrorAjaxResponse(error)); } public deleteCheckpoint(_: ServerConfig, path: string, checkpointID: string): Observable { const error = new GitHubContentProviderError("Not implemented"); - Logger.logError(error, "GitHubContentProvider/deleteCheckpoint", error.errno); + Logger.logError(error.message, "GitHubContentProvider/deleteCheckpoint", error.errno); return of(this.createErrorAjaxResponse(error)); } public restoreFromCheckpoint(_: ServerConfig, path: string, checkpointID: string): Observable { const error = new GitHubContentProviderError("Not implemented"); - Logger.logError(error, "GitHubContentProvider/restoreFromCheckpoint", error.errno); + Logger.logError(error.message, "GitHubContentProvider/restoreFromCheckpoint", error.errno); return of(this.createErrorAjaxResponse(error)); } diff --git a/src/GitHub/GitHubOAuthService.ts b/src/GitHub/GitHubOAuthService.ts index 746e79152..80a6d2c42 100644 --- a/src/GitHub/GitHubOAuthService.ts +++ b/src/GitHub/GitHubOAuthService.ts @@ -1,6 +1,5 @@ import ko from "knockout"; import { HttpStatusCodes } from "../Common/Constants"; -import * as Logger from "../Common/Logger"; import { configContext } from "../ConfigContext"; import { AuthorizeAccessComponent } from "../Explorer/Controls/GitHub/AuthorizeAccessComponent"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; @@ -8,6 +7,7 @@ import { JunoClient } from "../Juno/JunoClient"; import { isInvalidParentFrameOrigin } from "../Utils/MessageValidation"; import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils"; import { GitHubConnectorMsgType, IGitHubConnectorParams } from "./GitHubConnector"; +import { handleError } from "../Common/ErrorHandlingUtils"; window.addEventListener("message", (event: MessageEvent) => { if (isInvalidParentFrameOrigin(event)) { @@ -99,9 +99,7 @@ export class GitHubOAuthService { this.resetToken(); return true; } catch (error) { - const message = `Failed to delete app authorization: ${error}`; - Logger.logError(message, "GitHubOAuthService/logout"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GitHubOAuthService/logout", "Failed to delete app authorization"); return false; } } diff --git a/src/HostedExplorer.ts b/src/HostedExplorer.ts index ac24eeaea..30e97cf74 100644 --- a/src/HostedExplorer.ts +++ b/src/HostedExplorer.ts @@ -611,7 +611,7 @@ class HostedExplorer { return loadAccountResult; } catch (error) { LocalStorageUtility.removeEntry(StorageKey.DatabaseAccountId); - Logger.logError(error, "HostedExplorer/_getAccessCached"); + Logger.logError(getErrorMessage(error), "HostedExplorer/_getAccessCached"); throw error; } } @@ -637,7 +637,7 @@ class HostedExplorer { const accountResponse = this._getAccessAfterTenantSelection(defaultTenant.tenantId); return accountResponse; } catch (error) { - Logger.logError(error, "HostedExplorer/_getAccessNew"); + Logger.logError(getErrorMessage(error), "HostedExplorer/_getAccessNew"); throw error; } } @@ -658,7 +658,7 @@ class HostedExplorer { const keys = await this._getAccountKeysHelper(defaultAccount, true); return [defaultAccount, keys, authToken]; } catch (error) { - Logger.logError(error, "HostedExplorer/_getAccessAfterTenantSelection"); + Logger.logError(getErrorMessage(error), "HostedExplorer/_getAccessAfterTenantSelection"); throw error; } } @@ -1131,7 +1131,7 @@ class HostedExplorer { }); }, error => { - Logger.logError(error, "HostedExplorer/_onNewDirectorySelected"); + Logger.logError(getErrorMessage(error), "HostedExplorer/_onNewDirectorySelected"); } ); TelemetryProcessor.trace(Action.TenantSwitch); diff --git a/src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts b/src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts index 6e5a5d0a9..563645f25 100644 --- a/src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts +++ b/src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts @@ -7,6 +7,7 @@ import { NotebookWorkspaceFeedResponse } from "../Contracts/DataModels"; import { ResourceProviderClientFactory } from "../ResourceProvider/ResourceProviderClientFactory"; +import { getErrorMessage } from "../Common/ErrorHandlingUtils"; export class NotebookWorkspaceManager { private resourceProviderClientFactory: IResourceProviderClientFactory; @@ -24,7 +25,7 @@ export class NotebookWorkspaceManager { )) as NotebookWorkspaceFeedResponse; return response && response.value; } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/getNotebookWorkspacesAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/getNotebookWorkspacesAsync"); throw error; } } @@ -37,7 +38,7 @@ export class NotebookWorkspaceManager { try { return (await this.rpClient(uri).getAsync(uri, ArmApiVersions.documentDB)) as NotebookWorkspace; } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/getNotebookWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/getNotebookWorkspaceAsync"); throw error; } } @@ -47,7 +48,7 @@ export class NotebookWorkspaceManager { try { await this.rpClient(uri).putAsync(uri, ArmApiVersions.documentDB, { name: notebookWorkspaceId }); } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/createNotebookWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/createNotebookWorkspaceAsync"); throw error; } } @@ -57,7 +58,7 @@ export class NotebookWorkspaceManager { try { await this.rpClient(uri).deleteAsync(uri, ArmApiVersions.documentDB); } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/deleteNotebookWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/deleteNotebookWorkspaceAsync"); throw error; } } @@ -74,7 +75,7 @@ export class NotebookWorkspaceManager { undefined ); } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/getNotebookConnectionInfoAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/getNotebookConnectionInfoAsync"); throw error; } } @@ -86,7 +87,7 @@ export class NotebookWorkspaceManager { skipResourceValidation: true }); } catch (error) { - Logger.logError(error, "NotebookWorkspaceManager/startNotebookWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "NotebookWorkspaceManager/startNotebookWorkspaceAsync"); throw error; } } diff --git a/src/Platform/Hosted/ArmResourceUtils.ts b/src/Platform/Hosted/ArmResourceUtils.ts index 998fbe868..dbe9a5f64 100644 --- a/src/Platform/Hosted/ArmResourceUtils.ts +++ b/src/Platform/Hosted/ArmResourceUtils.ts @@ -3,6 +3,7 @@ import * as Constants from "../../Common/Constants"; import * as Logger from "../../Common/Logger"; import { Tenant, Subscription, DatabaseAccount, AccountKeys } from "../../Contracts/DataModels"; import { configContext } from "../../ConfigContext"; +import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; // TODO: 421864 - add a fetch wrapper export abstract class ArmResourceUtils { @@ -30,7 +31,7 @@ export abstract class ArmResourceUtils { } return tenants; } catch (error) { - Logger.logError(error, "ArmResourceUtils/listTenants"); + Logger.logError(getErrorMessage(error), "ArmResourceUtils/listTenants"); throw error; } } @@ -58,7 +59,7 @@ export abstract class ArmResourceUtils { } return subscriptions; } catch (error) { - Logger.logError(error, "ArmResourceUtils/listSubscriptions"); + Logger.logError(getErrorMessage(error), "ArmResourceUtils/listSubscriptions"); throw error; } } @@ -92,7 +93,7 @@ export abstract class ArmResourceUtils { } return accounts; } catch (error) { - Logger.logError(error, "ArmResourceUtils/listAccounts"); + Logger.logError(getErrorMessage(error), "ArmResourceUtils/listAccounts"); throw error; } } @@ -140,7 +141,7 @@ export abstract class ArmResourceUtils { } return result; } catch (error) { - Logger.logError(error, "ArmResourceUtils/getAccountKeys"); + Logger.logError(getErrorMessage(error), "ArmResourceUtils/getAccountKeys"); throw error; } } @@ -150,7 +151,7 @@ export abstract class ArmResourceUtils { const token = await AuthHeadersUtil.getAccessToken(ArmResourceUtils._armAuthArea, tenantId); return token; } catch (error) { - Logger.logError(error, "ArmResourceUtils/getAuthToken"); + Logger.logError(getErrorMessage(error), "ArmResourceUtils/getAuthToken"); throw error; } } diff --git a/src/SparkClusterManager/ArcadiaResourceManager.ts b/src/SparkClusterManager/ArcadiaResourceManager.ts index 28a699f64..68fa2318b 100644 --- a/src/SparkClusterManager/ArcadiaResourceManager.ts +++ b/src/SparkClusterManager/ArcadiaResourceManager.ts @@ -1,4 +1,3 @@ -import * as ViewModels from "../Contracts/ViewModels"; import { ArcadiaWorkspace, ArcadiaWorkspaceFeedResponse, @@ -10,6 +9,7 @@ import { IResourceProviderClient, IResourceProviderClientFactory } from "../Reso import * as Logger from "../Common/Logger"; import { ResourceProviderClientFactory } from "../ResourceProvider/ResourceProviderClientFactory"; import { configContext } from "../ConfigContext"; +import { getErrorMessage } from "../Common/ErrorHandlingUtils"; export class ArcadiaResourceManager { private resourceProviderClientFactory: IResourceProviderClientFactory; @@ -27,7 +27,7 @@ export class ArcadiaResourceManager { )) as ArcadiaWorkspaceFeedResponse; return response && response.value; } catch (error) { - Logger.logError(error, "ArcadiaResourceManager/getWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "ArcadiaResourceManager/getWorkspaceAsync"); throw error; } } @@ -37,7 +37,7 @@ export class ArcadiaResourceManager { try { return (await this._rpClient(uri).getAsync(uri, ArmApiVersions.arcadia)) as ArcadiaWorkspace; } catch (error) { - Logger.logError(error, "ArcadiaResourceManager/getWorkspaceAsync"); + Logger.logError(getErrorMessage(error), "ArcadiaResourceManager/getWorkspaceAsync"); throw error; } } @@ -56,7 +56,7 @@ export class ArcadiaResourceManager { )) as ArcadiaWorkspaceFeedResponse; return response && response.value; } catch (error) { - Logger.logError(error, "ArcadiaManager/listWorkspacesAsync"); + Logger.logError(getErrorMessage(error), "ArcadiaManager/listWorkspacesAsync"); throw error; } } @@ -68,7 +68,7 @@ export class ArcadiaResourceManager { const response = (await this._rpClient(uri).getAsync(uri, ArmApiVersions.arcadia)) as SparkPoolFeedResponse; return response && response.value; } catch (error) { - Logger.logError(error, "ArcadiaManager/listSparkPoolsAsync"); + Logger.logError(getErrorMessage(error), "ArcadiaManager/listSparkPoolsAsync"); throw error; } } diff --git a/src/Utils/AuthorizationUtils.ts b/src/Utils/AuthorizationUtils.ts index 73c66d0a3..48f023dc9 100644 --- a/src/Utils/AuthorizationUtils.ts +++ b/src/Utils/AuthorizationUtils.ts @@ -5,6 +5,7 @@ import { AuthType } from "../AuthType"; import * as Logger from "../Common/Logger"; import { configContext, Platform } from "../ConfigContext"; import { userContext } from "../UserContext"; +import { getErrorMessage } from "../Common/ErrorHandlingUtils"; export function getAuthorizationHeader(): ViewModels.AuthorizationTokenHeaderMetadata { if (window.authType === AuthType.EncryptedToken) { @@ -28,7 +29,7 @@ export async function getArcadiaAuthToken( const token = await AuthHeadersUtil.getAccessToken(arcadiaEndpoint, tenantId); return token; } catch (error) { - Logger.logError(error, "AuthorizationUtils/getArcadiaAuthToken"); + Logger.logError(getErrorMessage(error), "AuthorizationUtils/getArcadiaAuthToken"); throw error; } } diff --git a/src/Utils/GalleryUtils.ts b/src/Utils/GalleryUtils.ts index 723b04144..99dee0f07 100644 --- a/src/Utils/GalleryUtils.ts +++ b/src/Utils/GalleryUtils.ts @@ -1,7 +1,6 @@ import { IGalleryItem, JunoClient } from "../Juno/JunoClient"; import * as NotificationConsoleUtils from "./NotificationConsoleUtils"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; -import * as Logger from "../Common/Logger"; import { GalleryTab, SortBy, @@ -10,6 +9,7 @@ import { import Explorer from "../Explorer/Explorer"; import { IChoiceGroupOption, IChoiceGroupProps } from "office-ui-fabric-react"; import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent"; +import { handleError } from "../Common/ErrorHandlingUtils"; const defaultSelectedAbuseCategory = "Other"; const abuseCategories: IChoiceGroupOption[] = [ @@ -122,9 +122,11 @@ export function reportAbuse( ); onComplete(response.data); } catch (error) { - const message = `Failed to submit report on ${data.name} violating code of conduct: ${error}`; - Logger.logError(message, "GalleryUtils/reportAbuse"); - NotificationConsoleUtils.logConsoleInfo(message); + handleError( + error, + "GalleryUtils/reportAbuse", + `Failed to submit report on ${data.name} violating code of conduct` + ); } clearSubmitReportNotification(); @@ -185,9 +187,7 @@ export function downloadItem( onComplete(increaseDownloadResponse.data); } } catch (error) { - const message = `Failed to download ${data.name}: ${error}`; - Logger.logError(message, "GalleryUtils/downloadItem"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GalleryUtils/downloadItem", `Failed to download ${data.name}`); } NotificationConsoleUtils.clearInProgressMessageWithId(notificationId); @@ -212,9 +212,7 @@ export async function favoriteItem( onComplete(response.data); } catch (error) { - const message = `Failed to favorite ${data.name}: ${error}`; - Logger.logError(message, "GalleryUtils/favoriteItem"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GalleryUtils/favoriteItem", `Failed to favorite ${data.name}`); } } } @@ -234,9 +232,7 @@ export async function unfavoriteItem( onComplete(response.data); } catch (error) { - const message = `Failed to unfavorite ${data.name}: ${error}`; - Logger.logError(message, "GalleryUtils/unfavoriteItem"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GalleryUtils/unfavoriteItem", `Failed to unfavorite ${data.name}`); } } } @@ -268,9 +264,7 @@ export function deleteItem( NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Successfully removed ${name} from gallery`); onComplete(response.data); } catch (error) { - const message = `Failed to remove ${name} from gallery: ${error}`; - Logger.logError(message, "GalleryUtils/deleteItem"); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); + handleError(error, "GalleryUtils/deleteItem", `Failed to remove ${name} from gallery`); } NotificationConsoleUtils.clearInProgressMessageWithId(notificationId); diff --git a/src/Utils/NotebookConfigurationUtils.ts b/src/Utils/NotebookConfigurationUtils.ts index 815fa435e..20a10fc76 100644 --- a/src/Utils/NotebookConfigurationUtils.ts +++ b/src/Utils/NotebookConfigurationUtils.ts @@ -1,5 +1,6 @@ import * as DataModels from "../Contracts/DataModels"; import * as Logger from "../Common/Logger"; +import { getErrorMessage } from "../Common/ErrorHandlingUtils"; interface KernelConnectionMetadata { name: string; @@ -78,13 +79,13 @@ export class NotebookConfigurationUtils { if (!response.ok) { const responseMessage = await response.json(); Logger.logError( - JSON.stringify(responseMessage), + getErrorMessage(responseMessage), "NotebookConfigurationUtils/configureServiceEndpoints", response.status ); } } catch (error) { - Logger.logError(error, "NotebookConfigurationUtils/configureServiceEndpoints"); + Logger.logError(getErrorMessage(error), "NotebookConfigurationUtils/configureServiceEndpoints"); } } }