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

Reduce status bar spam, log only minimal message to the status bar #4366

Merged
merged 6 commits into from
Dec 10, 2021

Conversation

nkolev92
Copy link
Member

@nkolev92 nkolev92 commented Dec 9, 2021

Bug

Fixes: NuGet/Home#4376
Fixes: NuGet/Home#6047

Regression? Last working version:

Description

NuGet has generally relevant logs at normal verbosity, but the logs on the status bar are not super thought through.
This PR changes that.

Note These are not are the final changes in this area. There are other components/APIs we can use for reporting progress, but that's a different change tracked in NuGet/Home#9396.

All the logs and tests below were performed on a solution with 1 PackageReference and 1 packages.config project each.

Here's the before on what gets logged to the Output Window on Normal Verbosity.

Restoring NuGet packages...
Restoring packages for C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj...
  GET https://api.nuget.org/v3-flatcontainer/nuget.common/index.json
  OK https://api.nuget.org/v3-flatcontainer/nuget.common/index.json 365ms
  GET https://api.nuget.org/v3-flatcontainer/nuget.common/6.0.0/nuget.common.6.0.0.nupkg
  OK https://api.nuget.org/v3-flatcontainer/nuget.common/6.0.0/nuget.common.6.0.0.nupkg 95ms
  GET https://api.nuget.org/v3-flatcontainer/nuget.frameworks/index.json
  OK https://api.nuget.org/v3-flatcontainer/nuget.frameworks/index.json 171ms
  GET https://api.nuget.org/v3-flatcontainer/nuget.frameworks/6.0.0/nuget.frameworks.6.0.0.nupkg
  OK https://api.nuget.org/v3-flatcontainer/nuget.frameworks/6.0.0/nuget.frameworks.6.0.0.nupkg 57ms
Installed NuGet.Frameworks 6.0.0 from https://api.nuget.org/v3/index.json with content hash pEWTGa8sGEbSBE7VtKBlWZafG5tWNCGPzyNL91zneWoxZubNEWK1MN5QPN3fk+cV5CaySePT5reYjCAqELn5DA==.
Installed NuGet.Common 6.0.0 from https://api.nuget.org/v3/index.json with content hash NYK9JJd60jpv+VAGuCRnnDftF9osOCCgpkyG48cDK3eTGF0P19ttROJMVULQvJw+lUp31lk9X3rDEMqADj5n3w==.
Committing restore...
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.props.
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.targets.
Writing assets file to disk. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 1.41 sec).
NuGet package restore finished.
Time Elapsed: 00:00:02.8708809
========== Finished ==========

Here's the after.

Restoring NuGet packages...
Restoring packages for C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj...
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.common/index.json
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.common/6.0.0/nuget.common.6.0.0.nupkg
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.frameworks/index.json
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.frameworks/6.0.0/nuget.frameworks.6.0.0.nupkg
Installed NuGet.Frameworks 6.0.0 from https://api.nuget.org/v3/index.json with content hash pEWTGa8sGEbSBE7VtKBlWZafG5tWNCGPzyNL91zneWoxZubNEWK1MN5QPN3fk+cV5CaySePT5reYjCAqELn5DA==.
Installed NuGet.Common 6.0.0 from https://api.nuget.org/v3/index.json with content hash NYK9JJd60jpv+VAGuCRnnDftF9osOCCgpkyG48cDK3eTGF0P19ttROJMVULQvJw+lUp31lk9X3rDEMqADj5n3w==.
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.props.
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.targets.
Writing assets file to disk. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 547 ms).
NuGet package restore finished.
Time Elapsed: 00:00:01.7031949
========== Finished ==========

Here's my reasoning for why the after output is as is.

  • 1st line indicates that a restore is happening at minimal verbosity. I'd argue it's necessary.
  • Details about starting restore of the project are logged at Normal verbosity. This is standard behavior for operations such as restore build. All of them indicate the start and finish of the operation.
  • The CACHE messages were there to indicate the remote calls NuGet makes/attempts to make. They are useful for auditing.
  • Same thing applies about the individual package installation. This is a recent change.
  • Generating of the msbuild files and assets file is arguably the least valuable information here, but given that our logging is the same in VS and commandline (and I'd argue it should remain the same for sanity), they are relevant for auditing in commandline builds.
  • Finally the details about the project being restored and the time it took are relevant and important. These are logged at minimal verbosity.

Here's the before and after for the Status Bar when a clean restore happens.

Before:

Restoring NuGet packages...
Restored NuGet package CsvParser.0.5.2.
Restoring NuGet packages...
Restoring packages for C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj...
Installed NuGet.Frameworks 6.0.0 from https://api.nuget.org/v3/index.json with content hash pEWTGa8sGEbSBE7VtKBlWZafG5tWNCGPzyNL91zneWoxZubNEWK1MN5QPN3fk+cV5CaySePT5reYjCAqELn5DA==.
Installed NuGet.Common 6.0.0 from https://api.nuget.org/v3/index.json with content hash NYK9JJd60jpv+VAGuCRnnDftF9osOCCgpkyG48cDK3eTGF0P19ttROJMVULQvJw+lUp31lk9X3rDEMqADj5n3w==.
Committing restore...
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.props.
Generating MSBuild file C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\PackageReferenceProject.csproj.nuget.g.targets.
Writing assets file to disk. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json

After:

Restoring NuGet packages...
Restored NuGet package CsvParser.0.5.2.
Restoring NuGet packages...
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 547 ms).

Note that the above version has a lot of fluff.
Details about starting/ending restore and the individual packages installed + some fluff messages such as Committing restore are absolutely irrelevant for the status bar.

The new version does contain 2 Restoring NuGet packages... lines, but that's a larger refactoring that if people feel is super relevant I can create an issue for.

Finally here are the changes for the first no-op restores.

Output Window - Before:

Restoring NuGet packages...
Committing restore...
Assets file has not changed. Skipping assets file writing. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 66 ms).
NuGet package restore finished.
Time Elapsed: 00:00:00.4727655
========== Finished ==========

Output Window - After;

Restoring NuGet packages...
Assets file has not changed. Skipping assets file writing. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 60 ms).
NuGet package restore finished.
Time Elapsed: 00:00:00.4651742
========== Finished ==========

Note that details about the assets file not changing has been deemed relevant in the past. We can rethink that/change it, but I'm solving one problem at a time :)

Status bar - Before

Restoring NuGet packages...
Committing restore...
Assets file has not changed. Skipping assets file writing. Path: C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\obj\project.assets.json
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 66 ms).

Status bar - After

Restoring NuGet packages...

Now the last part is a bit controversial.
No actual restore happened, and there's no indication of that in the status bar. The trikc is that once you're done with a status bar, it switches to Ready which is indicative of operation completion. So I propose not to complicate things by adding an extra message there.

Finally:

Note that every 2nd no-op logs nothing to the Status bar, and that's true before and after my change.

PR Checklist

  • PR has a meaningful title

  • PR has a linked issue.

  • Described changes

  • Tests

    • Automated tests added
    • OR
    • Test exception - There's no means of testing this.
    • OR
    • N/A
  • Documentation

    • Documentation PR or issue filled
    • OR
    • N/A

@nkolev92 nkolev92 marked this pull request as ready for review December 9, 2021 22:45
@nkolev92 nkolev92 requested a review from a team as a code owner December 9, 2021 22:45
@nkolev92
Copy link
Member Author

nkolev92 commented Dec 9, 2021

@JonDouglas

I'd appreciate a review here.

@@ -24,6 +24,8 @@ internal sealed class NuGetFileLogger : IDisposable

public bool IsEnabled { get; }

public bool ShouldFormatWithTime { get; }
Copy link
Member Author

Choose a reason for hiding this comment

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

Note that this logger is a testing utility that's only built under debug, so changes here don't affect the product.

@@ -468,71 +468,6 @@ private static LogLevel GetLogLevel(MSBuildVerbosityLevel level)
}
}

internal class WaitDialogProgress : RestoreOperationProgressUI
Copy link
Member Author

Choose a reason for hiding this comment

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

Unused class, just kept creating extra refs to some methods.

@@ -259,7 +259,7 @@ public static async Task<RestoreSummary> CommitAsync(RestoreResultPair restoreRe
var log = summaryRequest.Request.Log;

// Commit the result
log.LogInformation(Strings.Log_Committing);
log.LogVerbose(Strings.Log_Committing);
Copy link
Member Author

Choose a reason for hiding this comment

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

I seriously considered removing this.

It literally just says "Comitting restore" which is not extremely helpful but it is a progress indicator.

For now, I just moved it verbose, but we can totally change it if others strongly lean one way or another.

// Do not show errors, warnings, verbose or debug messages on the progress dialog
// Avoid showing indented messages, these are typically not useful for the progress dialog since
// they are missing the context of the parent text above it
return RestoreOperationProgressUI.Current != null
&& GetMSBuildLevel(logMessage.Level) == MSBuildVerbosityLevel.Normal
&& GetMSBuildLevel(logMessage.Level) == MSBuildVerbosityLevel.Minimal
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the "big" change.

@jeffkl
Copy link
Contributor

jeffkl commented Dec 9, 2021

I like the cleaner output


static bool IsStringIndented(ILogMessage logMessage)
{
return logMessage.Message.Length > 0 && char.IsWhiteSpace(logMessage.Message[0]);
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Waaaaay better!

@JonDouglas
Copy link
Contributor

Here's all my feedback in a huge comment.

  CACHE https://api.nuget.org/v3-flatcontainer/nuget.common/index.json
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.common/6.0.0/nuget.common.6.0.0.nupkg
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.frameworks/index.json
  CACHE https://api.nuget.org/v3-flatcontainer/nuget.frameworks/6.0.0/nuget.frameworks.6.0.0.nupkg

In my opinion, if these are already downloaded, there's little need to even show these or say "Already Downloaded"? If they aren't downloaded, then saying "Downloading <...>". (Also do we care about index.json here? Ultimately we just care about downloading the package based on the index).

So my thoughts would be:

Restoring...
    Downloading / Already Downloaded...
    Installing...
Restored...

For the following:

Installed NuGet.Frameworks 6.0.0 from https://api.nuget.org/v3/index.json with content hash pEWTGa8sGEbSBE7VtKBlWZafG5tWNCGPzyNL91zneWoxZubNEWK1MN5QPN3fk+cV5CaySePT5reYjCAqELn5DA==.
Installed NuGet.Common 6.0.0 from https://api.nuget.org/v3/index.json with content hash NYK9JJd60jpv+VAGuCRnnDftF9osOCCgpkyG48cDK3eTGF0P19ttROJMVULQvJw+lUp31lk9X3rDEMqADj5n3w==.

Wonderful! I know these were downloaded & successfully installed. Is the path where it's installed useful here? (i.e. Installed NuGet.Common 6.0.0 (PATH) from ...)

Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 1.41 sec).
NuGet package restore finished.

If the line above says Restored, why do we need the last line? Keeping it is fine, but maybe it also needs spaces to help the user understand the scope of the output such as:

Restoring NuGet packages...
    [...]
Restored NuGet packages...

Also this comment is interesting:

The new version does contain 2 Restoring NuGet packages... lines, but that's a larger refactoring that if people feel is super relevant I can create an issue for.

From just looking at the output, this always has confused me. Why is restore doing multiple restores & logging such?

Restoring NuGet packages...
Restored NuGet package CsvParser.0.5.2.
Restoring NuGet packages...
Restored C:\Code\Temp\RestoreStatusMessages\PackageReferenceProject\PackageReferenceProject.csproj (in 547 ms).

This output does not make sense to me. I would expect a similar structure to the examples I have above about scope.

Lastly there's mention about Committing restore.... I agree about it being fluff & largely unsure of it's purpose. If we put a message saying Restoring NuGet packages... aren't we committing to that already or will give the user output saying why we are skipping it (no-op) for example? i.e. NuGet packages are already installed and up-to-date.

Bonus thought: Can we indent sections as they pertain to the current task they are doing for readability? For example:

Restoring...
    Downloading / Already Downloaded...
        [...]
    Installing...
        Installed package w/ content hash
        MSBuild stuff
        Writing Assets
Restored...

My two cents! This is a great PR as it stands & simplifies many things. Great job Nikolche!

Copy link
Contributor

@JonDouglas JonDouglas left a comment

Choose a reason for hiding this comment

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

Great job! Added comments to consider, but take em with a grain of salt 🧂

@nkolev92
Copy link
Member Author

Thanks for the long comment @JonDouglas! Super helpful! I've created some follow ups based on your feedback, some of which I might try to get done in customer sprint if I have time.

In my opinion, if these are already downloaded, there's little need to even show these or say "Already Downloaded"? If they aren't downloaded, then saying "Downloading <...>". (Also do we care about index.json here? Ultimately we just care about downloading the package based on the index).

The way it was designed originally, it's all http details that are included.
I'd be hesitant to change that without understanding whether we might break someone or something by tweaking it.

Wonderful! I know these were downloaded & successfully installed. Is the path where it's installed useful here? (i.e. Installed NuGet.Common 6.0.0 (PATH) from ...)

Good point. I've created NuGet/Home#11447.
I'll look for relevant issues filled and seek feedback, but I think this could be valuable!

If the line above says Restored, why do we need the last line? Keeping it is fine, but maybe it also needs spaces to help the user understand the scope of the output such as:

Restore in Visual Studio is always a solution restore.
You would get multiple of the Restored messages in one log. For now, I think we should keep the finish message.

From just looking at the output, this always has confused me. Why is restore doing multiple restores & logging such?

It's kind of funny how you diagnosed the problem from the output :D
Yes, it's 2 separate restores. packages.config and PackageReference restores are both run independently. One is project based, the other one is package based. As of now, I don't have a recommendation to change it, as while mixed projects are a thing, they're not the most common scenario so improving it seems like a low return of investment.

Lastly there's mention about Committing restore.... I agree about it being fluff & largely unsure of it's purpose. If we put a message saying Restoring NuGet packages... aren't we committing to that already or will give the user output saying why we are skipping it (no-op) for example? i.e. NuGet packages are already installed and up-to-date.

We're using that message as a progress indicator, telling you restore started in VS.
Note that on build restore logs in the build output not in a package manager output.

Today here's what we do:

MInimal verbosity - Indication of start
Minimal verbosity - Project Restored (we did something)
Normal verbosity - Project no-oped, details about files not changing.
Minimal verbosity - Restore completed.

Note that there may be many project messages in between.

Bonus thought: Can we indent sections as they pertain to the current task they are doing for readability? For example:

Unfortunately that one is pretty hard. A package installation may happen for multiple projects at once, and that is not tracked today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants