diff --git a/.gitignore b/.gitignore index 61dd6cb62f..bbf7d99f70 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,9 @@ dotnet-uninstall-debian-packages.sh # ignore the version file as it is generated at build time powershell.version +# ignore the telemetry semaphore file +DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY + # default location for produced nuget packages /nuget-artifacts diff --git a/build.psm1 b/build.psm1 index f3aed3395a..849c11a0e2 100644 --- a/build.psm1 +++ b/build.psm1 @@ -160,6 +160,9 @@ function Start-PSBuild { # save Git description to file for PowerShell to include in PSVersionTable git --git-dir="$PSScriptRoot/.git" describe --dirty --abbrev=60 > "$psscriptroot/powershell.version" + # create the telemetry flag file + $null = new-item -force -type file "$psscriptroot/DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY" + # simplify ParameterSetNames if ($PSCmdlet.ParameterSetName -eq 'FullCLR') { $FullCLR = $true diff --git a/src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj b/src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj index 9e0922018e..34eb0d2a32 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj +++ b/src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj @@ -25,6 +25,7 @@ + diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index 85702a4057..e1ab4f607d 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -257,6 +257,9 @@ namespace Microsoft.PowerShell s_theConsoleHost.UI.WriteWarningLine(preStartWarning); } + // Send startup telemetry for ConsoleHost startup + ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry(); + ClrFacade.StartProfileOptimization( s_theConsoleHost.LoadPSReadline() ? "StartupProfileData-Interactive" diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/Telemetry.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Telemetry.cs new file mode 100644 index 0000000000..bf70135a5b --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/Telemetry.cs @@ -0,0 +1,79 @@ +using System; +using Microsoft.ApplicationInsights; +using Microsoft.ApplicationInsights.DataContracts; +using Microsoft.ApplicationInsights.Extensibility; +using System.Management.Automation; +using System.Security.Cryptography; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.IO; + +namespace Microsoft.PowerShell +{ + /// + /// send up telemetry for startup + /// + internal static class ApplicationInsightsTelemetry + { + // The semaphore file which indicates whether telemetry should be sent + // This is temporary code waiting on the acceptance and implementation of the configuration spec + // The name of the file by when present in $PSHOME will enable telemetry. + // If this file is not present, no telemetry will be sent. + private const string TelemetrySemaphoreFilename = "DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY"; + + // The path to the semaphore file which enables telemetry + private static string TelemetrySemaphoreFilePath = Path.Combine( + Utils.GetApplicationBase(Utils.DefaultPowerShellShellID), + TelemetrySemaphoreFilename); + + // Telemetry client to be reused when we start sending more telemetry + private static TelemetryClient _telemetryClient = null; + + // Set this to true to reduce the latency of sending the telemetry + private static bool _developerMode = false; + + // PSCoreInsight2 telemetry key + private const string _psCoreTelemetryKey = "ee4b2115-d347-47b0-adb6-b19c2c763808"; + + static ApplicationInsightsTelemetry() + { + TelemetryConfiguration.Active.InstrumentationKey = _psCoreTelemetryKey; + TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = _developerMode; + } + + /// + /// Send the telemetry + /// + private static void SendTelemetry(string eventName, Dictionarypayload) + { + try + { + // if the semaphore file exists, try to send telemetry + if (Utils.NativeFileExists(TelemetrySemaphoreFilePath)) + { + if ( _telemetryClient == null ) + { + _telemetryClient = new TelemetryClient(); + } + _telemetryClient.TrackEvent(eventName, payload, null); + } + } + catch (Exception) + { + ; // Do nothing, telemetry can't be sent + } + } + + /// + /// Create the startup payload and send it up + /// + internal static void SendPSCoreStartupTelemetry() + { + var properties = new Dictionary(); + properties.Add("GitCommitID", PSVersionInfo.GitCommitId); + properties.Add("OSDescription", RuntimeInformation.OSDescription); + SendTelemetry("ConsoleHostStartup", properties); + } + } +} diff --git a/src/powershell-unix/powershell-unix.csproj b/src/powershell-unix/powershell-unix.csproj index 035bc332d2..60d501223e 100644 --- a/src/powershell-unix/powershell-unix.csproj +++ b/src/powershell-unix/powershell-unix.csproj @@ -19,7 +19,7 @@ PreserveNewest PreserveNewest - + PreserveNewest PreserveNewest diff --git a/src/powershell-win-core/powershell-win-core.csproj b/src/powershell-win-core/powershell-win-core.csproj index 71f16d5140..d17eb0f47a 100644 --- a/src/powershell-win-core/powershell-win-core.csproj +++ b/src/powershell-win-core/powershell-win-core.csproj @@ -23,7 +23,7 @@ PreserveNewest PreserveNewest - + PreserveNewest PreserveNewest