-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Add telemetry to the console host to report platform and version #3620
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
Add telemetry to the console host to report platform and version #3620
Conversation
build.psm1
Outdated
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.
$psscriptroot [](start = 40, length = 13)
This will create the file in the directory where Start-PSBuild is being run. But don't we want this location to be the output publish path? #Closed
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 placement of the file in the actual publish directory is managed by putting it in the *.csproj files (same as powershell.version is done), but the file has to exist. #Closed
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 path shouldn't change per session so it seems they can also be static variables initialized on first use (for cases other then start up telemetry reporting). You could use a static constructor or static assignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should set this to false now. if you need to test it, change it in your branch
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.
also rename to _developerMode
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.
convention has been to use leading underscore _telemetryClient
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.
fixed
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.
shouldn't this be ConsoleHostStartup?
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.
if ( File.Exists(telemetrySemaphoreFilePath ) ) [](start = 12, length = 47)
Some of these method calls can throw (Access Denied, ArgumentException) so I think we need to wrap this in a try/catch to allow PowerShell to continue to run on telemetry send fail.
|
🕐 |
PaulHigin
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.
Please see my review comments
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.
Can you measure the impact on startup?
I see that ApplicationInsights claims calls are non-blocking and telemetry is batched and sent on another thread, so there may be little or no impact.
I have a feeling we'll want to cross-gen the ApplicationInsights assembly though - JIT time is often noticeable.
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 did some checking earlier (it was about 30ms), but will validate again since the code has changed to using a semaphore file. I will include that in the comments of the next push
In reply to: 112802910 [](ancestors = 112802910)
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.
30ms is still quite a bit - it would be ~10% of total startup if we were matching performance of Windows PowerShell.
It would be good to know how much of that time is in JIT, see #3638 for some relative comparisons for time spent in JIT on other assemblies.
If the time is mostly in JIT (say > 95% of the time), then these changes are fine, and we can address cross-gen in the issue I've opened. If the time is not JIT time, then I think it should move to the background - for an example of where we do something similar in the console, see https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs#L52
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.
@lzybkr initially I was also calculating a checksum of the SMA assembly which was removed, and now there's less than 2ms increase when sending telemetry. (see comments below).
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.
To get PSHOME, we normally use this code:
var psHome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID);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.
We have a fast version of File.Exists that we should probably use here for faster startup - it's Utils.NativeFileExists.
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.
add application insights reference Create telemetry class We will upload GitCommitId and OSVersion information This is just applicable to the console host, if we want to make it more general, we can refactor at that time
We need a way to allow the user to opt out of telemetry and with the config RFC still in flight, we don't have a centralized way to do that. This implements a semaphore file which when present will produce telemetry sends from the console host when it starts up. In order to disable telemetry, simply delete the file. Setup will need to be changed to handle this.
Also, protect the telemetry sending from exception. A failure to create the telemetry client should not be fatal to the shell starting.
a8c84d4 to
0b2bd5e
Compare
SteveL-MSFT
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.
LGTM
|
@lzybkr from a performance perspective, the cost is quite low. I did the following test with the semaphore file present and then not present: |
…tance have git ignore the telemetry semaphore file
0b2bd5e to
101a757
Compare
| /// The name of the file by when present in $PSHOME will enable telemetry. | ||
| /// If this file is not present, no telemetry will be sent. | ||
| /// </summary> | ||
| public const string TelemetrySemaphoreFilename = "DELETE_ME_TO_DISABLE_CONSOLEHOST_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.
Does this need to be public? It's recommended to not have a public const field because this will make changing this const value a breaking change to other assemblies that reference ConsoleHost.dll and use this const field.
More specifically, if another assembly uses it, this string will be embedded in that assembly instead of actually referencing ConsoleHost.dll and retrieving the value at runtime. So in future, say we have to change this string value, the existing assemblies that depend on this public const field will continue to use the old values even after it's changed in ConsoleHost.dll.
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.
it doesn't need to be public. Do you think the TelemetrySemaphoreFilePath should also be private?
In reply to: 113082894 [](ancestors = 113082894)
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 it's better to be private because it's more like an implementation detail.
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.
| /// </summary> | ||
| public static string TelemetrySemaphoreFilePath = Path.Combine( | ||
| Utils.GetApplicationBase(Utils.DefaultPowerShellShellID), | ||
| TelemetrySemaphoreFilename); |
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 also seems to be an implementation detail that shouldn't be exposed.
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.
| /// <summary> | ||
| /// send up telemetry for startup | ||
| /// </summary> | ||
| public class ApplicationInsightsTelemetry |
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.
It seems this could be declared as a static class, as it's not supposed to be instantiated.
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.
| if (Utils.NativeFileExists(TelemetrySemaphoreFilePath)) | ||
| { | ||
| TelemetryConfiguration.Active.InstrumentationKey = _psCoreTelemetryKey; | ||
| TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = _developerMode; |
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.
Is this configuration a one-time thing, or do we have to do this configuration every time calling SendTelemetry? If it's a one-time thing, we probably can put it in the static constructor of this class.
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.
right now, it's a one-time thing. I'll create a static constructor and move this inside
In reply to: 113083840 [](ancestors = 113083840)
| { | ||
| var properties = new Dictionary<string, string>(); | ||
| properties.Add("GitCommitID", PSVersionInfo.GitCommitId); | ||
| properties.Add("OSVersionInfo", Environment.OSVersion.VersionString); |
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.
Environment.OSVersion.VersionString doesn't give much useful information on different distro of Linux, for example, it show Unix 4.8.0.41 on Ubuntu 16.04. How about use [System.Runtime.InteropServices.RuntimeInformation]::OSDescription?
PS /> [System.Runtime.InteropServices.RuntimeInformation]::OSDescription
Linux 4.8.0-41-generic #44~16.04.1-Ubuntu SMP Fri Mar 3 17:11:16 UTC 2017
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.
Yes, it should be OSDescription, but I'm waiting for this to be available as part of PSVersionInfo, this is ok for now I think.
In reply to: 113084599 [](ancestors = 113084599)
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'd suggest changing to OSDescription now and using PSVersionTable is a change we can make later
| /// <summary> | ||
| /// Create the startup payload and send it up | ||
| /// </summary> | ||
| public static void SendPSCoreStartupTelemetry() |
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.
Do we want to expose this API? By looking at the name, it's for a very specific scenario -- sending telemetry at PS startup time, and thus doesn't seem to be needed to be public.
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.
Sounds good. In that case, the class ApplicationInsightsTelemetry should also be made internal.
PaulHigin
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.
LGTM
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 this also needs to be under try/catch since TelemetrySempahoreFilePath static assignment will occur on first use.
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.
And it can throw.
…sion create static constructor and initialize active telemetry in it change members to private rather than public
|
Minor comment: Some of the using directives seem not necessary, and it's better to have them cleaned up. |
Produce simple telemetry via Application Insights for the PowerShell Core console host.
This is limited to the console host and is not meant as generalized telemetry code for PowerShell Core. It will capture the GitCommitID and Platform Information when the console host starts. It enables opting out of sending telemetry. This does not include the changes required in setup to opt out of telemetry, which will be in a later PR.