Skip to content

Conversation

@erdembayar
Copy link
Contributor

@erdembayar erdembayar commented Nov 10, 2020

Bug

Fixes: Nuget/Home#10142
Child of https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1167790.
Regression: No

  • Last working version:
  • How are we preventing it in future:

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.

  1. vs/nuget/powershellloaded: This telemetry is for reporting that Powershell just got loaded, and we have flag indicated what triggered powershell load.
    This one is important because we can detect if VS crash before we emit other PowerShell usage telemetries.

image

Property Desc
vs.nuget.trigger PMUI or PMC

image

  1. vs/nuget/solutionclose: This telemetry is for PMC/PMUI usage during VS solution session.

image

Property Desciption Value1 Value2
vs.nuget.powershellhost.firsttimeloadedfrompmc If PMC PowerShellHost get loaded then was it first time during this VS instance session? true = Yes false = No
vs.nuget.powershellhost.firsttimeloadedfrompmui If PMUI PowerShellHost get loaded then was it first time during this VS instance session? true = Yes false = No
vs.nuget.powershellhost.initps1loadedfrompmcfirst Which one was first from below 2 events? true = PMC false = PMUI
vs.nuget.powershellhost.initps1loadpmc Did PMC  execute init.ps1 during current VS solution session ? true = Yes false = No
vs.nuget.powershellhost.initps1loadpmui Did PMUI  execute init.ps1 during current VS solution session ? true = Yes false = No
vs.nuget.powershellhost.loadedfrompmc Did PMC PowerShellHost load during current VS solution session? true = Yes false = No
vs.nuget.powershellhost.loadedfrompmui Did PMUI PowerShellHost load during current VS solution session? true = Yes false = No
vs.nuget.powershellhost.nugetcommandused Did user execute any Nuget command (e.g. install-package)? true = Yes false = No
vs.nuget.powershellhost.pmcexecutecommandcount Number of commands executed on PMC    
vs.nuget.powershellhost.pmcwindowloadcount Number of times PMC window got user focus    
vs.nuget.powershellhost.pmuiexecutecommandcount Number of  powershell commands executed fromPMUI    
vs.nuget.powershellhost.solutionloaded If solution was loaded? PMC window can be used without solution. true = Yes false = No

image

  1. vs/nuget/instanceclose This telemetry is for VS instance close, so it has some aggregated data in it.
    For example below circled one shows PMC window last focused window, therefore it'll be automatically re-opened when we open VS next time.

image

Property Desciption Value1 Value2
vs.nuget.powershellhost.pmcexecutecommandcount Number of commands executed on PMC    
vs.nuget.powershellhost.pmcpowershellloadedsolutioncount Number of times PMC window got user focus    
vs.nuget.powershellhost.pmcwindowloadcount Number solution PMC powershell was loaded (May include PMC session without solution load).    
vs.nuget.powershellhost.pmuiexecutecommandcount If PMC window going to reopen true = Yes    false = No
vs.nuget.powershellhost.reopenatstart Number solution PMUI powershell was loaded.    
vs.nuget.powershellhost.solutioncount Number of actual solutions loaded

image

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.

@erdembayar erdembayar force-pushed the dev-eryondon-PMC-telemetry-event branch from 79a27ab to 099c7f0 Compare November 10, 2020 02:18
@erdembayar erdembayar closed this Nov 12, 2020
@erdembayar erdembayar reopened this Nov 12, 2020
@erdembayar erdembayar marked this pull request as ready for review November 12, 2020 18:59
@erdembayar erdembayar requested a review from a team as a code owner November 12, 2020 18:59
@erdembayar erdembayar force-pushed the dev-eryondon-PMC-telemetry-event branch 4 times, most recently from a90ff26 to c1feb67 Compare November 12, 2020 23:59
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
@erdembayar
Copy link
Contributor Author

@erdembayar

Can you please review the PR description.

@nkolev92

Ok. I updated PR description.

Copy link
Member

@zivkan zivkan left a 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.

Comment on lines 33 to 34
NuGetPowerShellUsageCollector _nuGetPowerShellUsageCollector = ServiceLocator.GetInstance<NuGetPowerShellUsageCollector>();
Assumes.NotNull(_nuGetPowerShellUsageCollector);
Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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

Copy link
Contributor Author

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.

Comment on lines 13 to 15
[Export(typeof(NuGetPowerShellUsageCollector))]
[PartCreationPolicy(CreationPolicy.Shared)]
public sealed class NuGetPowerShellUsageCollector : IDisposable
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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.

Comment on lines 85 to 89
// Telemetry service is not ready then delay for while.
if (TelemetryActivity.NuGetTelemetryService == null)
{
_powerShellLoadEvent = telemetryEvent;
}
Copy link
Member

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.

Copy link
Contributor Author

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 }
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Member

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?

Copy link
Contributor Author

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.

Comment on lines 307 to 312
_vsInstanceData._pmcLoadedSolutionCount++;
}

if (_vsSolutionData._loadedFromPMUI)
{
_vsInstanceData._pmuiLoadedSolutionCount++;
Copy link
Member

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).

Copy link
Contributor Author

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.

Comment on lines 40 to 41
public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose);
public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose);
Copy link
Member

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.

Copy link
Contributor Author

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
image

If I name it not this generic then I don't need this prefix.

Copy link
Contributor

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

Copy link
Contributor Author

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'.

Copy link
Contributor Author

@erdembayar erdembayar left a comment

Choose a reason for hiding this comment

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

@zivkan

I addressed PR comments. Please review again.

Comment on lines 33 to 34
NuGetPowerShellUsageCollector _nuGetPowerShellUsageCollector = ServiceLocator.GetInstance<NuGetPowerShellUsageCollector>();
Assumes.NotNull(_nuGetPowerShellUsageCollector);
Copy link
Contributor Author

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;
Copy link
Contributor Author

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.

Comment on lines 80 to 83
var telemetryEvent = new TelemetryEvent(NuGetPowerShellLoaded, new Dictionary<string, object>
{
{ NuGetPowershellPrefix + LoadedFromPMC, isPMC }
});
Copy link
Contributor Author

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.

Comment on lines 40 to 41
public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose);
public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose);
Copy link
Contributor Author

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
image

If I name it not this generic then I don't need this prefix.

Comment on lines 13 to 15
[Export(typeof(NuGetPowerShellUsageCollector))]
[PartCreationPolicy(CreationPolicy.Shared)]
public sealed class NuGetPowerShellUsageCollector : IDisposable
Copy link
Contributor Author

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.

Comment on lines 307 to 312
_vsInstanceData._pmcLoadedSolutionCount++;
}

if (_vsSolutionData._loadedFromPMUI)
{
_vsInstanceData._pmuiLoadedSolutionCount++;
Copy link
Contributor Author

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()
Copy link
Contributor Author

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.

Comment on lines 159 to 173
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;
Copy link
Contributor Author

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 }
Copy link
Contributor Author

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.

Comment on lines 126 to 141
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++;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. Addressed.

Copy link
Contributor

@dominoFire dominoFire left a 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

Comment on lines 40 to 41
public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose);
public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose);
Copy link
Contributor

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.
Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

@erdembayar erdembayar left a 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.

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.
Copy link
Member

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.

Comment on lines 40 to 43
// _vsSolutionData hold telemetry data for current VS solution session.
private SolutionData _vsSolutionData;
// _vsInstanceData hold telemetry for current VS instance session.
private readonly InstanceData _vsInstanceData;
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, removing.

public sealed class NuGetPowerShellUsageCollector : IDisposable
{
// PMC, PMUI powershell telemetry consts
public const string NuGetPMCExecuteCommandCount = nameof(NuGetPMCExecuteCommandCount);
Copy link
Member

@zivkan zivkan Jan 22, 2021

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.

Copy link
Contributor Author

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.

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

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.

Copy link
Member

Choose a reason for hiding this comment

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

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions#capitalization-rules-for-identifiers

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:

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.

Copy link
Contributor Author

@erdembayar erdembayar left a 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);
Copy link
Contributor Author

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.

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

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.
Copy link
Contributor Author

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.

Comment on lines 40 to 41
public const string NuGetVSSolutionClose = nameof(NuGetVSSolutionClose);
public const string NuGetVSInstanceClose = nameof(NuGetVSInstanceClose);
Copy link
Contributor Author

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'.

Comment on lines 40 to 43
// _vsSolutionData hold telemetry data for current VS solution session.
private SolutionData _vsSolutionData;
// _vsInstanceData hold telemetry for current VS instance session.
private readonly InstanceData _vsInstanceData;
Copy link
Contributor Author

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 }
Copy link
Contributor Author

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.

public sealed class NuGetPowerShellUsageCollector : IDisposable
{
// PMC, PMUI powershell telemetry consts
public const string NuGetPMCExecuteCommandCount = nameof(NuGetPMCExecuteCommandCount);
Copy link
Member

Choose a reason for hiding this comment

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

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions#capitalization-rules-for-identifiers

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:

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.

Copy link
Member

@zivkan zivkan left a 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.

Copy link
Contributor

@dominoFire dominoFire left a comment

Choose a reason for hiding this comment

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

Some styling comments.

…event called vs/nuget/solutionclose and vs instance close event called vs/nuget/instanceclose.
Copy link
Contributor Author

@erdembayar erdembayar left a 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.

@erdembayar erdembayar merged commit 7c710c0 into dev Jan 23, 2021
@erdembayar erdembayar deleted the dev-eryondon-PMC-telemetry-event branch January 23, 2021 01:18
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
_nuGetPowerShellUsageCollector = new NuGetPowerShellUsageCollector();
NuGet.Common.TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService();
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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.
image

Copy link
Member

@nkolev92 nkolev92 Jan 25, 2021

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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.

@nkolev92
Copy link
Member

@erdembayar

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.

@erdembayar
Copy link
Contributor Author

@erdembayar

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.

@nkolev92
Sorry, I saw your PR comments right after I merged. I created this follow up PR, please check. #3863

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implementation - Add new telemetries to track events related to PMC and Powershell usage.

5 participants