Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework showing of generic error message #795

Merged
merged 23 commits into from
Sep 10, 2021

Conversation

mattseddon
Copy link
Member

@mattseddon mattseddon commented Sep 8, 2021

Addresses a big portion of #482

The change here standardises the way that we handle errors with our user facing commands. We now have two different approaches based on whether or not the command relies on the DVC CLI.

Demo CLI based command:

Screen.Recording.2021-09-10.at.10.44.22.am.mov

Demo non-cli command (wired to throw):

Screen.Recording.2021-09-10.at.10.45.43.am.mov

Appreciate this is a big PR and will take some time to review. We had a lot of inconsistent try / catch logic sprinkled throughout the code. I've left lots of comments inline to try and help with the size.

@mattseddon mattseddon added the product PR that affects product label Sep 8, 2021
@mattseddon mattseddon self-assigned this Sep 8, 2021
@mattseddon mattseddon changed the base branch from master to add-rename-command September 8, 2021 09:19

if (stderr?.includes(Prompt.TRY_FORCE)) {
return offerToForce(stderr, internalCommands, commandId, ...args)
}

return showGenericError()
throw e
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] We now want to catch these errors in the same place to send an analytics error event

@@ -60,6 +61,7 @@ export const registerInstrumentedCommand = <T = string | undefined>(
})
return res
} catch (e: unknown) {
showGenericError()
sendTelemetryEventAndThrow(name, e as Error, stopWatch.getElapsedTime())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] We probably don't need to throw here anymore as we are putting up a modal to say that something has gone wrong, we might even be able to drop that to a toast if we add a button to show the output channel

Base automatically changed from add-rename-command to master September 8, 2021 22:46
@mattseddon mattseddon force-pushed the rework-default-notifications branch 2 times, most recently from bd8403e to 649a779 Compare September 8, 2021 22:58
@mattseddon mattseddon force-pushed the rework-default-notifications branch from 649a779 to 9b2ab84 Compare September 9, 2021 01:09
return res
} catch (e: unknown) {
showGenericError()
this.outputChannel.show()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] Want to rework this part now

return res
} catch (e: unknown) {
this.outputChannel.handleError(e as Error)
sendErrorTelemetryEvent(name, e as Error, stopWatch.getElapsedTime())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] The difference in these functions is how we handle the error. For cli based commands we just offer to show the output channel for everything else we append the error message to the channel and then offer to show that

return await this.runAndSendTelemetry<T>(name, func, arg)
} catch (e: unknown) {
reportCommandFailed(name)
throw e
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[C] Test this again, it might show two notifications

try {
window.showInformationMessage((await stdout) || 'Operation successful.')
} catch (e) {
reportErrorMessage(e)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] We now handle this in the same place as the other CLI errors. Made sense to rename the function at the same time.

}
export const reportOutput = async (stdout: Promise<string>) => {
const output = (await stdout) || 'Operation successful.'
window.showInformationMessage(output)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] We only need to await the stdout coming through to see if the function throws, we can then send this notification into the void instead of waiting for a response before returning.

try {
return await this.runAndSendTelemetry<T>(name, func, arg)
} catch (e: unknown) {
this.outputChannel.offerToShowError()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] This is the difference between "CLI" and "non-CLI" commands, if the CLI fails then we will offer to show the output channel to the user, if a command that we have total control over fails then it will fail in the normal VS code way.

@@ -46,20 +41,3 @@ export enum RegisteredCommands {
TRACKED_EXPLORER_COPY_FILE_PATH = 'dvc.copyFilePath',
TRACKED_EXPLORER_COPY_REL_FILE_PATH = 'dvc.copyRelativeFilePath'
}

export const registerInstrumentedCommand = <T = string | undefined>(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] This has been replaced by an InternalCommands method.

import { StopWatch } from '../util/time'

export enum RegisteredCommands {
export enum RegisteredCliCommands {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] The change in this file is to split commands between those that heavily rely on the CLI (generally are just pass through) and those that don't.

@@ -140,7 +140,7 @@ export class Experiments {
return
}

report(this.internalCommands.executeCommand(commandId, cwd))
return reportOutput(this.internalCommands.executeCommand(commandId, cwd))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] We are now processing this differently (hence the need for the return) see here for an explanation.

@@ -5,6 +5,7 @@ import { Operator } from '.'
import { ExperimentsFilterByTree } from './tree'
import { Experiments } from '../..'
import { joinParamOrMetricPath } from '../../paramsAndMetrics/paths'
import { InternalCommands } from '../../../commands/internal'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] Changes in here are a constructor signature change. I had to add InternalCommands into all of the trees to register commands. I did this instead of exposing through the experiments class as that means that we will have the option to break up InternalCommands in the future.

@@ -39,16 +39,3 @@ describe('getWarningResponse', () => {
expect(mockedShowWarningMessage).toBeCalledTimes(1)
})
})

describe('showGenericError', () => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] This was replaced by a new function inside of the output channel class (we want everything to go through there now).

@@ -49,10 +54,6 @@ export class InternalCommands {
)

this.registerCommand(AvailableCommands.GET_THEME, () => config.getTheme())

this.registerCommand(AvailableCommands.SHOW_OUTPUT_CHANNEL, () =>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[F] This was just a placeholder command.

@mattseddon mattseddon marked this pull request as ready for review September 10, 2021 01:04
@codeclimate
Copy link

codeclimate bot commented Sep 10, 2021

Code Climate has analyzed commit 0fe2f7b and detected 0 issues on this pull request.

The test coverage on the diff in this pull request is 93.2% (85% is the threshold).

This pull request will bring the total coverage in the repository to 96.0% (0.0% change).

View more on Code Climate.

Copy link
Contributor

@rogermparent rogermparent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks fine to me! Took a bit of time to review, but mostly just renames and repeated minor refactors that could be scrolled by- the comments were really helpful on this one!

@mattseddon mattseddon merged commit 4c2c28b into master Sep 10, 2021
@mattseddon mattseddon deleted the rework-default-notifications branch September 10, 2021 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
product PR that affects product
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants