Refactor error handling part 2 (#313)

This commit is contained in:
victor-meng
2020-11-03 13:40:44 -08:00
committed by GitHub
parent a009a8ba5f
commit 5f1f7a8266
58 changed files with 229 additions and 336 deletions

View File

@@ -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<ArcadiaMenuPickerProps, A
selectedSparkPool: item.text
});
} catch (error) {
Logger.logError(error, "ArcadiaMenuPicker/_onSparkPoolClicked");
Logger.logError(getErrorMessage(error), "ArcadiaMenuPicker/_onSparkPoolClicked");
throw error;
}
};

View File

@@ -4,12 +4,10 @@
import * as React from "react";
import * as DataModels from "../../../Contracts/DataModels";
import * as Logger from "../../../Common/Logger";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
import { StringUtils } from "../../../Utils/StringUtils";
import { userContext } from "../../../UserContext";
import { TerminalQueryParams } from "../../../Common/Constants";
import { handleError } from "../../../Common/ErrorHandlingUtils";
export interface NotebookTerminalComponentProps {
notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo;
@@ -71,9 +69,10 @@ export class NotebookTerminalComponent extends React.Component<NotebookTerminalC
params: Map<string, string>
): 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 "";
}

View File

@@ -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<CodeOfConductCompone
this.props.onAcceptCodeOfConduct(response.data);
} catch (error) {
const message = `Failed to accept code of conduct: ${error}`;
Logger.logError(message, "CodeOfConductComponent/acceptCodeOfConduct");
logConsoleError(message);
handleError(error, "CodeOfConductComponent/acceptCodeOfConduct", "Failed to accept code of conduct");
}
}

View File

@@ -16,11 +16,8 @@ import {
Text
} from "office-ui-fabric-react";
import * as React from "react";
import * as Logger from "../../../Common/Logger";
import { IGalleryItem, JunoClient, IJunoResponse, IPublicGalleryData } from "../../../Juno/JunoClient";
import * as GalleryUtils from "../../../Utils/GalleryUtils";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComponent";
import { GalleryCardComponent, GalleryCardComponentProps } from "./Cards/GalleryCardComponent";
import "./GalleryViewerComponent.less";
@@ -28,6 +25,7 @@ import { HttpStatusCodes } from "../../../Common/Constants";
import Explorer from "../../Explorer";
import { CodeOfConductComponent } from "./CodeOfConductComponent";
import { InfoComponent } from "./InfoComponent/InfoComponent";
import { handleError } from "../../../Common/ErrorHandlingUtils";
export interface GalleryViewerComponentProps {
container?: Explorer;
@@ -354,9 +352,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
this.sampleNotebooks = response.data;
} catch (error) {
const message = `Failed to load sample notebooks: ${error}`;
Logger.logError(message, "GalleryViewerComponent/loadSampleNotebooks");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
handleError(error, "GalleryViewerComponent/loadSampleNotebooks", "Failed to load sample notebooks");
}
}
@@ -382,9 +378,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
throw new Error(`Received HTTP ${response.status} when loading public notebooks`);
}
} catch (error) {
const message = `Failed to load public notebooks: ${error}`;
Logger.logError(message, "GalleryViewerComponent/loadPublicNotebooks");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
handleError(error, "GalleryViewerComponent/loadPublicNotebooks", "Failed to load public notebooks");
}
}
@@ -404,9 +398,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
this.favoriteNotebooks = response.data;
} catch (error) {
const message = `Failed to load favorite notebooks: ${error}`;
Logger.logError(message, "GalleryViewerComponent/loadFavoriteNotebooks");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
handleError(error, "GalleryViewerComponent/loadFavoriteNotebooks", "Failed to load favorite notebooks");
}
}
@@ -432,9 +424,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
this.publishedNotebooks = response.data;
} catch (error) {
const message = `Failed to load published notebooks: ${error}`;
Logger.logError(message, "GalleryViewerComponent/loadPublishedNotebooks");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
handleError(error, "GalleryViewerComponent/loadPublishedNotebooks", "Failed to load published notebooks");
}
}

View File

@@ -21,6 +21,7 @@ import Explorer from "../../Explorer";
import { NotebookV4 } from "@nteract/commutable/lib/v4";
import { SessionStorageUtility } from "../../../Shared/StorageUtility";
import { DialogHost } from "../../../Utils/GalleryUtils";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
export interface NotebookViewerComponentProps {
container?: Explorer;
@@ -100,9 +101,7 @@ export class NotebookViewerComponent extends React.Component<NotebookViewerCompo
}
} catch (error) {
this.setState({ showProgressBar: false });
const message = `Failed to load notebook content: ${error}`;
Logger.logError(message, "NotebookViewerComponent/loadNotebookContent");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
handleError(error, "NotebookViewerComponent/loadNotebookContent", "Failed to load notebook content");
}
}

View File

@@ -46,7 +46,7 @@ export class IndexingPolicyRefreshComponent extends React.Component<
try {
await this.props.refreshIndexTransformationProgress();
} catch (error) {
handleError(error, "Refreshing index transformation progress failed.", "RefreshIndexTransformationProgress");
handleError(error, "RefreshIndexTransformationProgress", "Refreshing index transformation progress failed");
} finally {
this.setState({ isRefreshing: false });
}

View File

@@ -1533,7 +1533,7 @@ export default class Explorer {
resolve(token);
},
(error: any) => {
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<NotebookContentItem> {
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<NotebookContentItem> {
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<NotebookContentItem> {
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<string> {
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<void> {
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<void> {
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<void> {
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;
}
}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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");
}
}

View File

@@ -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<number>;
@@ -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();
};

View File

@@ -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)
});
}
}
}