-
Notifications
You must be signed in to change notification settings - Fork 697
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
Make RestoreCommand handle unexpected exceptions. #5997
base: dev
Are you sure you want to change the base?
Conversation
Comment from closed PR: #5878 (review)
|
Currently, the idea is to catch all exceptions in Regarding the error code, I agree that we should have a general error code for this scenario. However, if the exception thrown has an error code with it, we should use the exceptions error code. |
That makes sense to me.
One thing that might be tricky is that in the current implementation when we catch FatalProtocolException we don't really log the message, we assume it's already been logged. |
Erro code:
Double logging
|
|
||
if (unwrappedLogMessage != null) | ||
{ | ||
assetsFile.LogMessages.Add(new AssetsLogMessage(LogLevel.Error, unwrappedLogMessage.Code, unwrappedLogMessage.Message, null)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your CLI restore example shows that MSBuild is attributing the exception to NuGet.targets, and not the csproj file. There's a property on AssetsLogMessage
so NuGet tells MSBuild which project file the error is related to, which should be filled in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just updated the CLI example in the description section. The screenshot I had was an old one - before I started adding the error to an assets file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about building the assets file after you log the message to the logger.
Currently this adds another place where we can create a discrepancy.
The pattern currently is:
- You log warnings to the "collector" logger.
- When you create the assets file, the "collector" logger creates assets file warnings.
- It'd also be ideal if the failed restore result is created into fewer places. Same reason as above, fewer chances of a discrepancy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need the assets file, as it’s responsible for capturing all log messages. is the suggestion to do _logger.Log(error)
instead? or to do _logger.log(error)
and then follow it up with asset.LogMessage(error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, don't add messages to the assets file.
There's a collector logger that ensures that all warnings/errors will be part of the built assets file.
Compare that to how we log errors like NU1008, or warnings like NU1603. You call the logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the collector logger write the assets file? This try-catch block is shallow in the call stack, and I wouldn't be surprised if an exception that bubbles all the way up here will not be written to the assets file by the collector logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't able to find out if the collector logger writes to the asset file. From my understanding, we do the writing into the assets file in RestoreCommand.ExecuteAsync
var logsEnumerable = _logger.Errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do all the logic restore ever would and you just write to the logger and that's it.
The try catch should end before we do the transformation at line 457.
Similarly, don't create a new RestoreResult and keep it in one place. That reduces the changes we end up with restore results that don't end up getting everything and either the output is broken or the result is misinterpreted.
Can we please add a test for this change that documents the desired behavior? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would have saved me half a day of debugging, if it was merged about a month ago 😁
|
||
if (unwrappedLogMessage != null) | ||
{ | ||
assetsFile.LogMessages.Add(new AssetsLogMessage(LogLevel.Error, unwrappedLogMessage.Code, unwrappedLogMessage.Message, null)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, don't add messages to the assets file.
There's a collector logger that ensures that all warnings/errors will be part of the built assets file.
Compare that to how we log errors like NU1008, or warnings like NU1603. You call the logger.
|
||
// Assert | ||
Assert.Contains("The 'packageB 1.0.0' package requires NuGet client version '9.0.0' or above, but the current NuGet version is", ex.Message); | ||
Assert.Contains("The 'packageB 1.0.0' package requires NuGet client version '9.0.0' or above, but the current NuGet version is", result.LogMessages.First().Message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none of the tests modified in this PR validate that the assets file contains the log message. I'd expect the in-memory results to contain the log because the logger has scope longer than RestoreCommand
. However, RestoreCommand
needs to write the assets file, including the logger's messages, and if there's an unhandled exception, there's a decent chance that isn't happening.
f28e29f
to
527555b
Compare
Bug
Fixes: NuGet/Home#13188
Description
recreates #5878
For the screenshots below, the following synthetic projects were used:
- bad.csproj : A project that throws an exception upon restore.
- good.csproj: A project that restores successfully.
- multiprojectWithOneErrors.csproj: A project
Currently, restoring this solution will result in an exception that interrupts the restore from restoring projects that did not cause the exception.
After this change, exception are caught allowing restore to complete for other projects as following:
VS side
After the change, here's how the errors will be displayed on VS:
PR Checklist