Add telemetry to the console host to report platform and version#3620
Add telemetry to the console host to report platform and version#3620daxian-dbw merged 5 commits intoPowerShell:masterfrom
Conversation
There was a problem hiding this comment.
$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.
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.
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.
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.
also rename to _developerMode
There was a problem hiding this comment.
There was a problem hiding this comment.
convention has been to use leading underscore _telemetryClient
There was a problem hiding this comment.
shouldn't this be ConsoleHostStartup?
There was a problem hiding this comment.
There was a problem hiding this comment.
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.
Please see my review comments
There was a problem hiding this comment.
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.
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.
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.
@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.
To get PSHOME, we normally use this code:
var psHome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID);There was a problem hiding this comment.
There was a problem hiding this comment.
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.
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
|
@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.
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.
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.
I think it's better to be private because it's more like an implementation detail.
There was a problem hiding this comment.
| /// </summary> | ||
| public static string TelemetrySemaphoreFilePath = Path.Combine( | ||
| Utils.GetApplicationBase(Utils.DefaultPowerShellShellID), | ||
| TelemetrySemaphoreFilename); |
There was a problem hiding this comment.
This also seems to be an implementation detail that shouldn't be exposed.
There was a problem hiding this comment.
| /// <summary> | ||
| /// send up telemetry for startup | ||
| /// </summary> | ||
| public class ApplicationInsightsTelemetry |
There was a problem hiding this comment.
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.
| if (Utils.NativeFileExists(TelemetrySemaphoreFilePath)) | ||
| { | ||
| TelemetryConfiguration.Active.InstrumentationKey = _psCoreTelemetryKey; | ||
| TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = _developerMode; |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
There was a problem hiding this comment.
Sounds good. In that case, the class ApplicationInsightsTelemetry should also be made internal.
There was a problem hiding this comment.
I think this also needs to be under try/catch since TelemetrySempahoreFilePath static assignment will occur on first use.
…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.