-
Notifications
You must be signed in to change notification settings - Fork 736
Understand PMC and Powershell usages #3755
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
Conversation
79a27ab to
099c7f0
Compare
a90ff26 to
c1feb67
Compare
Add telemetry for if PMC opened by default without user gesture. Add telemetry for how many times powershell commands executed.
…r PM UI and PM PMC. So make change to accommodiate this concern.
…itial run of install new package with init.ps1. It's bit complicated.
…t for emitting telemetry in PowerShellHost.cs
Ok. I updated PR description. |
zivkan
left a comment
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.
github tells me that new commits were pushed. Publishing my comments now before I refresh to check what changed.
src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs
Outdated
Show resolved
Hide resolved
| NuGetPowerShellUsageCollector _nuGetPowerShellUsageCollector = ServiceLocator.GetInstance<NuGetPowerShellUsageCollector>(); | ||
| Assumes.NotNull(_nuGetPowerShellUsageCollector); |
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 variable isn't being used anywhere
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.
Thank you for review. Removed. This funky thing used for event subscription to work.
| SolutionManager.Value.NuGetProjectContext = ProjectContext.Value; | ||
| } | ||
|
|
||
| NuGetPowerShellUsageCollector nuGetPowerShellUsageCollectorInstance = NuGetPowerShellUsageCollector.Value; |
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 variable isn't being used anywhere
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.
Ok. Removed. This funky thing used for event subscription to work.
| [Export(typeof(NuGetPowerShellUsageCollector))] | ||
| [PartCreationPolicy(CreationPolicy.Shared)] | ||
| public sealed class NuGetPowerShellUsageCollector : IDisposable |
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.
The only places this class is MEF imported, no methods or properties are being called. Therefore, it seems there's no point to make it MEF exported. However, I guess it's because you want this class to be a singleton. Given this class needs to subscrube to the events from the beginning of the NuGet package (extension) being loaded by Visual Studio, and stay alive until VS shuts down, I suggest stop exporting as MEF, and instead just new ..() in NuGetPackage.cs's InitializeAsync method, saving it as a class field, so it doesn't get garbage disposed (although if it subscribes to events, it will have references and not be eligible for GC). Just need to make sure solution events are subscribed to. If you register through NuGet's solution manager, rather than VS's "native" interfaces, then that would need to be "hooked up" correctly.
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.
Ok. Taken your suggestion and moved to NugetPackage.cs>> InitializeAsync method. Please check if I implemented correctly.
| NuGetPowerShellUsage.VSInstanceCloseEvent -= NuGetPowerShellUsage_VSInstanseCloseHandler; | ||
| } | ||
|
|
||
| internal class NuGetPowershellVSSolutionCloseEvent |
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 class class doesn't represent an event, so I don't think this is a good name. Perhaps SolutionData, SolutionMetrics, something like that.
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.
Thank you for better name. Implemented.
| // Telemetry service is not ready then delay for while. | ||
| if (TelemetryActivity.NuGetTelemetryService == null) | ||
| { | ||
| _powerShellLoadEvent = telemetryEvent; | ||
| } |
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.
Initiaizing the telemetry service should be moved out of VsSolutionManager into NuGetPackage.InitializeAsync, so this situation shouldn't be possible.
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.
Thank you for review. I implemented your suggestion.
| { | ||
| var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object> | ||
| { | ||
| { NuGetPowershellPrefix + LoadedFromPMC, isPMC } |
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.
Rather than a boolean, would it be better to have a vs.nuget.powershellloadreason that has values like pmc or pmui?
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 would prefer leave it as it's now. Because next lines I have to make comparison to "pmc" or "pmui" which gets ugly.
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 suggesting replacing the isPMC variable/parameter everywhere, just the reported telemetry:
var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object>()
{
{ NuGetPowershellPrefix + "Trigger", isPMC ? "PMC" : "PMUI" }
};Consider the point of view from someone querying the data. They see vs.nuget.nugetpowershellprefix.loadedfrompmc == false, but if they don't NuGet very well, they might wonder where did it load from then?
This made me notice, do you really want to use NuGetPowershellPrefix for this? This has a different event name vs.nuget.nugetpowershellloaded, so duplicating nugetpowershell in the property name is redundant.
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.
Ok.
Implemented your suggestion. Also I'm removing prefix concept. It's remnant from universal 1 telemetry which contains different types of properties from several types of activities.
| _vsSolutionData._loadedFromPMUI = pmuiPowershellLoad; | ||
| } | ||
|
|
||
| private void IncrementUpdateVSInstanceData() |
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.
just thinking out loud, I don't know if this is a good idea or not: Would it be better to increment both the solution and instance counters in the event handler, so it's not necessary to "fixup" the instance data on solution open/close?
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.
Ok. Removed this logic. Update InstanceData values when I update solution data same time.
| _vsInstanceData._pmcLoadedSolutionCount++; | ||
| } | ||
|
|
||
| if (_vsSolutionData._loadedFromPMUI) | ||
| { | ||
| _vsInstanceData._pmuiLoadedSolutionCount++; |
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 method (IncrementUpdateVSInstanceData) is being called on both solution open and solution close. Therefore, this "solution count" will be wrong (hopefully always exactly double the real value).
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.
Ok. Removed this logic. Update InstanceData values when I update solution data same time.
| public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose); | ||
| public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose); |
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.
These two properties are being used as the telemetry event name. This class has a specific name, but the telemetry event name is very generic. @dominoFire do you have an opinion on what is better to query? A single telemetry event with many, unrelated properties, or use the event name to partition different "families" of data, even when they are emit at the same time (solution close, VS close)?
We can refactor this class later to make it easier to re-use a generic event name later, but it will break all data queries if we change the event name, so that's more important to get right now.
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.
@zivkan
Your concern is valid. I can change name now. Also I added this prefix to prevent any future property conflict

If I name it not this generic then I don't need this prefix.
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 consider it's better to have one event:
- Triggered when it's appropriate to make ordering assumptions, but, don't rely on timing data since each client/user/machine has their relative clocks
- Has all needed properties, to avoid further table joins
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.
In spec already agreed we're going to have separate vssolution emit and vsinstance telemetry.
Also if we wait for VS close for 1 batched telemetry event then in case of PMC cause VS to fail, we'll loose all the history leading to this event.
For example: Maybe user used 1 solution with PMC powershell without problem then next another solution with PMUI powershell which cause VS to fail. We need usage history and currently we're sending aggregate data to reduce traffic.
I removed almost all nuget prefixes from properties and rename my events powershellloaded, powershellvssolutionclose, `powershellvsinstanceclose'.
erdembayar
left a comment
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 addressed PR comments. Please review again.
| NuGetPowerShellUsageCollector _nuGetPowerShellUsageCollector = ServiceLocator.GetInstance<NuGetPowerShellUsageCollector>(); | ||
| Assumes.NotNull(_nuGetPowerShellUsageCollector); |
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.
Thank you for review. Removed. This funky thing used for event subscription to work.
| SolutionManager.Value.NuGetProjectContext = ProjectContext.Value; | ||
| } | ||
|
|
||
| NuGetPowerShellUsageCollector nuGetPowerShellUsageCollectorInstance = NuGetPowerShellUsageCollector.Value; |
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.
Ok. Removed. This funky thing used for event subscription to work.
| var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object> | ||
| { | ||
| { NuGetPowershellPrefix + LoadedFromPMC, isPMC } | ||
| }); |
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 thought about doing it from PMC itself, but we still need it here to check if it's first time load or not logic. So I prefer to leave it here.
| public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose); | ||
| public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose); |
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.
@zivkan
Your concern is valid. I can change name now. Also I added this prefix to prevent any future property conflict

If I name it not this generic then I don't need this prefix.
| [Export(typeof(NuGetPowerShellUsageCollector))] | ||
| [PartCreationPolicy(CreationPolicy.Shared)] | ||
| public sealed class NuGetPowerShellUsageCollector : IDisposable |
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.
Ok. Taken your suggestion and moved to NugetPackage.cs>> InitializeAsync method. Please check if I implemented correctly.
| _vsInstanceData._pmcLoadedSolutionCount++; | ||
| } | ||
|
|
||
| if (_vsSolutionData._loadedFromPMUI) | ||
| { | ||
| _vsInstanceData._pmuiLoadedSolutionCount++; |
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.
Ok. Removed this logic. Update InstanceData values when I update solution data same time.
| _vsSolutionData._loadedFromPMUI = pmuiPowershellLoad; | ||
| } | ||
|
|
||
| private void IncrementUpdateVSInstanceData() |
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.
Ok. Removed this logic. Update InstanceData values when I update solution data same time.
| switch (command) | ||
| { | ||
| case "GET-HELP": | ||
| case "FIND-PACKAGE": | ||
| case "GET-PACKAGE": | ||
| case "INSTALL-PACKAGE": | ||
| case "UNINSTALL-PACKAGE": | ||
| case "UPDATE-PACKAGE": | ||
| case "SYNC-PACKAGE": | ||
| case "ADD-BINDINGREDIRECT": | ||
| case "GET-PROJECT": | ||
| case "REGISTER-TABEXPANSION": | ||
| // Nuget Command executed | ||
| vsSolutionData._nuGetCommandUsed = true; | ||
| break; |
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.
Ok. Created new NuGetCmdletExecutedEvent and raising it from NuGetPowerShellBaseCommand.cs.
| { | ||
| var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object> | ||
| { | ||
| { NuGetPowershellPrefix + LoadedFromPMC, isPMC } |
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 would prefer leave it as it's now. Because next lines I have to make comparison to "pmc" or "pmui" which gets ugly.
| if (isPMC) | ||
| { | ||
| { | ||
| // Please note: Direct PMC and PMUI don't share same code path for installing packages with *.ps1 files | ||
| // For PMC all installation done in one pass so no double counting. | ||
| vsSolutionData._nuGetPMCExecuteCommandCount++; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // Please note: Direct PMC and PMUI don't share same code path for installing packages with *.ps1 files | ||
| // This one is called for both init.ps1 and install.ps1 seperately. | ||
| // For MSBuildNuGetProject projects install.ps1 can even further increase duplicate counting: See MSBuildNuGetProject.cs#L377 - L396 | ||
| // Also this concern valid for dependent packages with *.ps1 files. | ||
| vsSolutionData._nuGetPMUIExecuteCommandCount++; | ||
| } |
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.
Ok. Addressed.
dominoFire
left a comment
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.
Some comments. Looks good
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
| public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose); | ||
| public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose); |
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 consider it's better to have one event:
- Triggered when it's appropriate to make ordering assumptions, but, don't rely on timing data since each client/user/machine has their relative clocks
- Has all needed properties, to avoid further table joins
| public const string ReOpenAtStart = nameof(ReOpenAtStart); | ||
|
|
||
| // Const name for emitting when VS solution close or VS instance close. | ||
| public const string NuGetPowershellPrefix = "NuGetPowershellPrefix."; // Using prefix prevent accidental same name property collission from different type telemetry. |
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 would try to reduce how many times 'nuget' appears in event and property names.
public const string PackageCommands = "PackageCommands."; // Using prefix prevent accidental same name property collission from different type telemetry.
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.
The word "prefix" in the property names doesn't add anything to the name either.
I'm not sure if PackageCommands. is the suggestion, or just a generic example, but this telemetry is not about packages, or really about commnads. It's more about NuGet's powershell host usage, so I think vs.nuget.powershellhost. would be a good prefix.
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 think now no need anymore. I'm getting rid of prefix then all together. It's remnant from universal vssolution/vsinstance emitter idea.
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.
From this comment thread, Fernando suggested keeping the generic "vs.nuget.solutionclose" and "vs.nuget.instanceclose" event names, so we can reuse it for other data in the future where we want to report at solution/instance close.
erdembayar
left a comment
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.
@dominoFire
Thank you for your review. Implemented all your suggestion except batching all telemetry only 1 event emit.
In spec already agreed we're going to have separate vssolution emit and vsinstance telemetry.
Also if we wait for VS close for 1 batched telemetry event then in case of PMC cause VS to fail, we'll loose all the history leading to this event.
For example: Maybe user used 1 solution with PMC powershell without problem then next another solution with PMUI powershell which cause VS to fail. We need usage history and currently we're sending aggregate data to reduce traffic.
I removed almost all nuget prefixes from properties and rename my events powershellloaded, powershellvssolutionclose, `powershellvsinstanceclose'.
Please check again.
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs
Outdated
Show resolved
Hide resolved
| public const string ReOpenAtStart = nameof(ReOpenAtStart); | ||
|
|
||
| // Const name for emitting when VS solution close or VS instance close. | ||
| public const string NuGetPowershellPrefix = "NuGetPowershellPrefix."; // Using prefix prevent accidental same name property collission from different type telemetry. |
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.
The word "prefix" in the property names doesn't add anything to the name either.
I'm not sure if PackageCommands. is the suggestion, or just a generic example, but this telemetry is not about packages, or really about commnads. It's more about NuGet's powershell host usage, so I think vs.nuget.powershellhost. would be a good prefix.
| // _vsSolutionData hold telemetry data for current VS solution session. | ||
| private SolutionData _vsSolutionData; | ||
| // _vsInstanceData hold telemetry for current VS instance session. | ||
| private readonly InstanceData _vsInstanceData; |
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'm not sure what other people think, but I think the variable names are clear enough, so the comments don't add value.
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.
Sure, removing.
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
| public sealed class NuGetPowerShellUsageCollector : IDisposable | ||
| { | ||
| // PMC, PMUI powershell telemetry consts | ||
| public const string NuGetPMCExecuteCommandCount = nameof(NuGetPMCExecuteCommandCount); |
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.
As mentioned in another comment, initializations should only have the first letter capitalized, the rest lower case, like Sql, Xml, Json. I see many, many instances of all upper PMC and PMUI in this file. Please check the whole PR.
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.
Not sure why only the first letter capitalized?
I checked previous examples how it's implemented. All of them using Pascal case like mine.
NuGet.Client/src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectBuildProperties.cs
Lines 12 to 17 in a8521b9
| public const string MSBuildProjectExtensionsPath = nameof(MSBuildProjectExtensionsPath); | |
| public const string PackageTargetFallback = nameof(PackageTargetFallback); | |
| public const string AssetTargetFallback = nameof(AssetTargetFallback); | |
| public const string PackageVersion = nameof(PackageVersion); | |
| public const string RestoreProjectStyle = nameof(RestoreProjectStyle); | |
| public const string RuntimeIdentifier = nameof(RuntimeIdentifier); |
NuGet.Client/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Lines 38 to 40 in a8521b9
| private static readonly string AggregateSourceName = Resources.AggregateSourceName; | |
| private static readonly TimeSpan ExecuteInitScriptsRetryDelay = TimeSpan.FromMilliseconds(400); | |
| private static readonly int MaxTasks = 16; |
I feel current form makes easy to read, in my previous company they enforced it so it became habit. If only the first letter capitalized is better practice then I can change to that one.
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.
The PascalCasing convention, used for all identifiers except parameter names, capitalizes the first character of each word (including acronyms over two letters in length), as shown in the following examples:
PropertyDescriptor HtmlTag
A special case is made for two-letter acronyms in which both letters are capitalized, as shown in the following identifier:
IOStream
This is why we have APIs like:
SqlClient, notSQLClientXmlDocument, notXMLDocumentJsonSerializer, notJSONSerializer.
So, NuGetPMCExecuteCommandCount should be NuGetPmcExecuteCommandCount. There are many examples of this naming convention not being followed in this PR for both Pmc and Pmui. When writing human text, we continue to capitalize the full "word", so I'd still talk about PMC, but code using it as part of a variable name should use Pmc.
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
erdembayar
left a comment
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.
@zivkan
Thank you for your review. I addressed all your comments. There 2-3 things I commented my point of view.
Please check.
| public sealed class NuGetPowerShellUsageCollector : IDisposable | ||
| { | ||
| // PMC, PMUI powershell telemetry consts | ||
| public const string NuGetPMCExecuteCommandCount = nameof(NuGetPMCExecuteCommandCount); |
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.
Not sure why only the first letter capitalized?
I checked previous examples how it's implemented. All of them using Pascal case like mine.
NuGet.Client/src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectBuildProperties.cs
Lines 12 to 17 in a8521b9
| public const string MSBuildProjectExtensionsPath = nameof(MSBuildProjectExtensionsPath); | |
| public const string PackageTargetFallback = nameof(PackageTargetFallback); | |
| public const string AssetTargetFallback = nameof(AssetTargetFallback); | |
| public const string PackageVersion = nameof(PackageVersion); | |
| public const string RestoreProjectStyle = nameof(RestoreProjectStyle); | |
| public const string RuntimeIdentifier = nameof(RuntimeIdentifier); |
NuGet.Client/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Lines 38 to 40 in a8521b9
| private static readonly string AggregateSourceName = Resources.AggregateSourceName; | |
| private static readonly TimeSpan ExecuteInitScriptsRetryDelay = TimeSpan.FromMilliseconds(400); | |
| private static readonly int MaxTasks = 16; |
I feel current form makes easy to read, in my previous company they enforced it so it became habit. If only the first letter capitalized is better practice then I can change to that one.
| public const string ReOpenAtStart = nameof(ReOpenAtStart); | ||
|
|
||
| // Const name for emitting when VS solution close or VS instance close. | ||
| public const string NuGetPowershellPrefix = "NuGetPowershellPrefix."; // Using prefix prevent accidental same name property collission from different type telemetry. |
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 think now no need anymore. I'm getting rid of prefix then all together. It's remnant from universal vssolution/vsinstance emitter idea.
| public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose); | ||
| public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose); |
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.
In spec already agreed we're going to have separate vssolution emit and vsinstance telemetry.
Also if we wait for VS close for 1 batched telemetry event then in case of PMC cause VS to fail, we'll loose all the history leading to this event.
For example: Maybe user used 1 solution with PMC powershell without problem then next another solution with PMUI powershell which cause VS to fail. We need usage history and currently we're sending aggregate data to reduce traffic.
I removed almost all nuget prefixes from properties and rename my events powershellloaded, powershellvssolutionclose, `powershellvsinstanceclose'.
| // _vsSolutionData hold telemetry data for current VS solution session. | ||
| private SolutionData _vsSolutionData; | ||
| // _vsInstanceData hold telemetry for current VS instance session. | ||
| private readonly InstanceData _vsInstanceData; |
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.
Sure, removing.
| { | ||
| var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object> | ||
| { | ||
| { NuGetPowershellPrefix + LoadedFromPMC, isPMC } |
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.
Ok.
Implemented your suggestion. Also I'm removing prefix concept. It's remnant from universal 1 telemetry which contains different types of properties from several types of activities.
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
| public sealed class NuGetPowerShellUsageCollector : IDisposable | ||
| { | ||
| // PMC, PMUI powershell telemetry consts | ||
| public const string NuGetPMCExecuteCommandCount = nameof(NuGetPMCExecuteCommandCount); |
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.
The PascalCasing convention, used for all identifiers except parameter names, capitalizes the first character of each word (including acronyms over two letters in length), as shown in the following examples:
PropertyDescriptor HtmlTag
A special case is made for two-letter acronyms in which both letters are capitalized, as shown in the following identifier:
IOStream
This is why we have APIs like:
SqlClient, notSQLClientXmlDocument, notXMLDocumentJsonSerializer, notJSONSerializer.
So, NuGetPMCExecuteCommandCount should be NuGetPmcExecuteCommandCount. There are many examples of this naming convention not being followed in this PR for both Pmc and Pmui. When writing human text, we continue to capitalize the full "word", so I'd still talk about PMC, but code using it as part of a variable name should use Pmc.
zivkan
left a comment
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.
Once we sort out the "generic solution/instance close with appropriate property name prefix" vs "specific telemetry events without any property name prefix" decision/implementation, I think this will be good enough to go.
dominoFire
left a comment
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.
Some styling comments.
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
…event called vs/nuget/solutionclose and vs instance close event called vs/nuget/instanceclose.
erdembayar
left a comment
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.
@zivkan
Thank you for your review. I addressed all latest comments. Please review again.
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs
Outdated
Show resolved
Hide resolved
| protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress) | ||
| { | ||
| _nuGetPowerShellUsageCollector = new NuGetPowerShellUsageCollector(); | ||
| NuGet.Common.TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService(); |
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.
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.
@nkolev92
Reason I did it was if I import Nuget.Common then just 8-9 lines down on AsyncLazy<IVsMonitorSelection> needed exact same thing it needs fully qualified name. So instead of touching existing code for same change I tried to contain my changes.

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 can always do a using like this one: https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.VisualStudio.Common/OutputConsoleLogger.cs#L14
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.
Addressed in new PR#3863.
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs
Show resolved
Hide resolved
|
Please consider waiting on reviewers that have been engaged throughout the whole PR process. I left some feedback that you should consider addressing in a follow up PR. |
Bug
Fixes: Nuget/Home#10142
Child of https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1167790.
Regression: No
Fix
Details:
Recently decided we not to act on decrease PMC usage issue. We suspect it's highly unlikely problem to happen. To better understand this problem we add those 3 types of telemetries.
Design at Nuget/Client.Engineering#582
@nkolev92 @zivkan @dominoFire please review.
If you might find choice names of telemetry properties could be not good then please comment so I can rename them.
This one is important because we can detect if VS crash before we emit other PowerShell usage telemetries.
For example below circled one shows PMC window last focused window, therefore it'll be automatically re-opened when we open VS next time.
Testing/Validation
Tests Added: No
Reason for not adding tests: It's just telemetry, I may add later once current PR gets 1 approval.
Validation: Lots of manual validation.