Skip to content

Commit fe2cc6a

Browse files
JamesWTruheradityapatwardhan
authored andcommitted
Additional Telemetry - Implementation of RFC0036 (PowerShell#10336)
1 parent c8e72d1 commit fe2cc6a

17 files changed

Lines changed: 610 additions & 124 deletions

File tree

build.psm1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ function Start-PSPester {
10121012
# All concatenated commands/arguments are suffixed with the delimiter (space)
10131013

10141014
# Disable telemetry for all startups of pwsh in tests
1015-
$command = "`$env:POWERSHELL_TELEMETRY_OPTOUT = 1;"
1015+
$command = "`$env:POWERSHELL_TELEMETRY_OPTOUT = 'yes';"
10161016
if ($Terse)
10171017
{
10181018
$command += "`$ProgressPreference = 'silentlyContinue'; "
@@ -1153,7 +1153,7 @@ function Start-PSPester {
11531153
try {
11541154
$originalModulePath = $env:PSModulePath
11551155
$originalTelemetry = $env:POWERSHELL_TELEMETRY_OPTOUT
1156-
$env:POWERSHELL_TELEMETRY_OPTOUT = 1
1156+
$env:POWERSHELL_TELEMETRY_OPTOUT = 'yes'
11571157
if ($Unelevate)
11581158
{
11591159
Start-UnelevatedProcess -process $powershell -arguments ($PSFlags + "-c $Command")

src/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
<ItemGroup>
1010
<ProjectReference Include="..\System.Management.Automation\System.Management.Automation.csproj" />
11-
<!-- the following package(s) are from https://github.com/microsoft/applicationinsights-??? -->
12-
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.10.0" />
1311
</ItemGroup>
1412

1513
<PropertyGroup>

src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using System.Text;
2525
using System.Threading;
2626
using System.Threading.Tasks;
27+
using Microsoft.PowerShell.Telemetry;
2728

2829
using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle;
2930
using Dbg = System.Management.Automation.Diagnostics;
@@ -123,12 +124,8 @@ internal static int Start(
123124

124125
try
125126
{
126-
string profileDir;
127-
#if UNIX
128-
profileDir = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE);
129-
#else
130-
profileDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerShell";
131-
127+
string profileDir = Platform.CacheDirectory;
128+
#if ! UNIX
132129
if (!Directory.Exists(profileDir))
133130
{
134131
Directory.CreateDirectory(profileDir);
@@ -200,25 +197,29 @@ internal static int Start(
200197
// First check for and handle PowerShell running in a server mode.
201198
if (s_cpp.ServerMode)
202199
{
200+
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("ServerMode");
203201
ProfileOptimization.StartProfile("StartupProfileData-ServerMode");
204202
System.Management.Automation.Remoting.Server.OutOfProcessMediator.Run(s_cpp.InitialCommand);
205203
exitCode = 0;
206204
}
207205
else if (s_cpp.NamedPipeServerMode)
208206
{
207+
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("NamedPipe");
209208
ProfileOptimization.StartProfile("StartupProfileData-NamedPipeServerMode");
210209
System.Management.Automation.Remoting.RemoteSessionNamedPipeServer.RunServerMode(
211210
s_cpp.ConfigurationName);
212211
exitCode = 0;
213212
}
214213
else if (s_cpp.SSHServerMode)
215214
{
215+
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("SSHServer");
216216
ProfileOptimization.StartProfile("StartupProfileData-SSHServerMode");
217217
System.Management.Automation.Remoting.Server.SSHProcessMediator.Run(s_cpp.InitialCommand);
218218
exitCode = 0;
219219
}
220220
else if (s_cpp.SocketServerMode)
221221
{
222+
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("SocketServerMode");
222223
ProfileOptimization.StartProfile("StartupProfileData-SocketServerMode");
223224
System.Management.Automation.Remoting.Server.HyperVSocketMediator.Run(s_cpp.InitialCommand,
224225
s_cpp.ConfigurationName);
@@ -242,7 +243,7 @@ internal static int Start(
242243
PSHost.IsStdOutputRedirected = Console.IsOutputRedirected;
243244

244245
// Send startup telemetry for ConsoleHost startup
245-
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry();
246+
ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry("Normal");
246247

247248
exitCode = s_theConsoleHost.Run(s_cpp, false);
248249
}

src/Microsoft.PowerShell.ConsoleHost/host/msh/Telemetry.cs

Lines changed: 0 additions & 102 deletions
This file was deleted.

src/System.Management.Automation/CoreCLR/CorePsPlatform.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,21 @@ public static bool IsWindowsDesktop
140140
}
141141
}
142142

143+
/// <summary>
144+
/// Gets the location for the various caches.
145+
/// </summary>
146+
internal static string CacheDirectory
147+
{
148+
get
149+
{
150+
#if UNIX
151+
return Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE);
152+
#else
153+
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerShell";
154+
#endif
155+
}
156+
}
157+
143158
#if !UNIX
144159
private static bool? _isNanoServer = null;
145160
private static bool? _isIoT = null;

src/System.Management.Automation/System.Management.Automation.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<ItemGroup>
1414
<!-- the following package(s) are from https://github.com/JamesNK/Newtonsoft.Json -->
1515
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
16+
<!-- the Application Insights package -->
17+
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.10.0" />
1618
<!-- the following package(s) are from https://github.com/dotnet/corefx -->
1719
<PackageReference Include="Microsoft.Win32.Registry.AccessControl" Version="4.6.0-preview8.19405.3" />
1820
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.6.0-preview8.19405.3" />

src/System.Management.Automation/engine/CommandCompletion/CommandCompletion.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,12 @@ private static CommandCompletion CallScriptWithAstParameterSet(Ast ast, Token[]
515515
// This is the start of the real implementation of autocomplete/intellisense/tab completion
516516
private static CommandCompletion CompleteInputImpl(Ast ast, Token[] tokens, IScriptPosition positionOfCursor, Hashtable options)
517517
{
518+
#if LEGACYTELEMETRY
519+
// We could start collecting telemetry at a later date.
520+
// We will leave the #if to remind us that we did this once.
518521
var sw = new Stopwatch();
519522
sw.Start();
520-
523+
#endif
521524
using (var powershell = PowerShell.Create(RunspaceMode.CurrentRunspace))
522525
{
523526
var context = LocalPipeline.GetExecutionContextFromTLS();
@@ -590,8 +593,10 @@ private static CommandCompletion CompleteInputImpl(Ast ast, Token[] tokens, IScr
590593
}
591594

592595
var completionResults = results ?? EmptyCompletionResult;
593-
sw.Stop();
596+
594597
#if LEGACYTELEMETRY
598+
// no telemetry here. We don't capture tab completion performance.
599+
sw.Stop();
595600
TelemetryAPI.ReportTabCompletionTelemetry(sw.ElapsedMilliseconds, completionResults.Count,
596601
completionResults.Count > 0 ? completionResults[0].ResultType : CompletionResultType.Text);
597602
#endif

src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Management.Automation.Internal;
1010
using System.Management.Automation.Tracing;
1111
using System.Runtime.CompilerServices;
12+
using Microsoft.PowerShell.Telemetry;
1213

1314
namespace System.Management.Automation
1415
{
@@ -150,13 +151,15 @@ private static ReadOnlyBag<string> ProcessEnabledFeatures(string[] enabledFeatur
150151
if (IsModuleFeatureName(name))
151152
{
152153
list.Add(name);
154+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ExperimentalModuleFeatureActivation, name);
153155
}
154156
else if (IsEngineFeatureName(name))
155157
{
156158
if (EngineExperimentalFeatureMap.TryGetValue(name, out ExperimentalFeature feature))
157159
{
158160
feature.Enabled = true;
159161
list.Add(name);
162+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ExperimentalEngineFeatureActivation, name);
160163
}
161164
else
162165
{

src/System.Management.Automation/engine/GetCommandCommand.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,9 @@ public PSTypeName[] ParameterType
369369
/// </summary>
370370
protected override void BeginProcessing()
371371
{
372+
#if LEGACYTELEMETRY
372373
_timer.Start();
373-
374+
#endif
374375
base.BeginProcessing();
375376

376377
if (ShowCommandInfo.IsPresent && Syntax.IsPresent)
@@ -552,9 +553,11 @@ private void OutputResultsHelper(IEnumerable<CommandInfo> results)
552553
}
553554
}
554555

556+
#if LEGACYTELEMETRY
555557
_timer.Stop();
556558

557-
#if LEGACYTELEMETRY
559+
// No telemetry here - capturing the name of a command which we are not familiar with
560+
// may be confidential customer information
558561
// We want telementry on commands people look for but don't exist - this should give us an idea
559562
// what sort of commands people expect but either don't exist, or maybe should be installed by default.
560563
// The StartsWith is to avoid logging telemetry when suggestion mode checks the
@@ -1443,8 +1446,9 @@ private bool IsCommandInResult(CommandInfo command)
14431446
private Collection<WildcardPattern> _nounPatterns;
14441447
private Collection<WildcardPattern> _modulePatterns;
14451448

1449+
#if LEGACYTELEMETRY
14461450
private Stopwatch _timer = new Stopwatch();
1447-
1451+
#endif
14481452
#endregion
14491453

14501454
#region ShowCommandInfo support

src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@
1010
using System.Linq;
1111
using System.Management.Automation;
1212
using System.Management.Automation.Internal;
13+
using System.Management.Automation.Language;
1314
using System.Management.Automation.Runspaces;
1415
using System.Reflection;
1516
using System.Security;
1617
using System.Threading;
1718

1819
using Microsoft.Management.Infrastructure;
1920
using Microsoft.PowerShell.Cmdletization;
21+
using Microsoft.PowerShell.Telemetry;
2022

2123
using Dbg = System.Management.Automation.Diagnostics;
22-
23-
using System.Management.Automation.Language;
2424
using Parser = System.Management.Automation.Language.Parser;
2525
using ScriptBlock = System.Management.Automation.ScriptBlock;
2626
using Token = System.Management.Automation.Language.Token;
27+
2728
#if LEGACYTELEMETRY
2829
using Microsoft.PowerShell.Telemetry.Internal;
2930
#endif
@@ -825,6 +826,12 @@ private IList<PSModuleInfo> ImportModule_RemotelyViaPsrpSession(
825826
}
826827
}
827828

829+
// Send telemetry on the imported modules
830+
foreach (PSModuleInfo moduleInfo in remotelyImportedModules)
831+
{
832+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, moduleInfo.Name);
833+
}
834+
828835
return remotelyImportedModules;
829836
}
830837

@@ -1251,6 +1258,7 @@ private void ImportModule_RemotelyViaCimSession(
12511258
foreach (RemoteDiscoveryHelper.CimModule remoteCimModule in remotePsCimModules)
12521259
{
12531260
ImportModule_RemotelyViaCimModuleData(importModuleOptions, remoteCimModule, cimSession);
1261+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, remoteCimModule.ModuleName);
12541262
}
12551263
}
12561264

@@ -1743,6 +1751,7 @@ protected override void ProcessRecord()
17431751
// of doing Get-Module -list
17441752
foreach (PSModuleInfo module in ModuleInfo)
17451753
{
1754+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, module.Name);
17461755
RemoteDiscoveryHelper.DispatchModuleInfoProcessing(
17471756
module,
17481757
localAction: delegate ()
@@ -1772,6 +1781,7 @@ protected override void ProcessRecord()
17721781
{
17731782
foreach (Assembly suppliedAssembly in Assembly)
17741783
{
1784+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, suppliedAssembly.GetName().Name);
17751785
ImportModule_ViaAssembly(importModuleOptions, suppliedAssembly);
17761786
}
17771787
}
@@ -1785,6 +1795,8 @@ protected override void ProcessRecord()
17851795
{
17861796
SetModuleBaseForEngineModules(foundModule.Name, this.Context);
17871797

1798+
// Telemetry here - report module load
1799+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, foundModule.Name);
17881800
#if LEGACYTELEMETRY
17891801
TelemetryAPI.ReportModuleLoad(foundModule);
17901802
#endif
@@ -1809,6 +1821,7 @@ protected override void ProcessRecord()
18091821
BaseGuid = modulespec.Guid;
18101822

18111823
PSModuleInfo foundModule = ImportModule_LocallyViaName(importModuleOptions, modulespec.Name);
1824+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, modulespec.Name);
18121825
if (foundModule != null)
18131826
{
18141827
SetModuleBaseForEngineModules(foundModule.Name, this.Context);
@@ -1818,6 +1831,10 @@ protected override void ProcessRecord()
18181831
else if (this.ParameterSetName.Equals(ParameterSet_FQName_ViaPsrpSession, StringComparison.OrdinalIgnoreCase))
18191832
{
18201833
ImportModule_RemotelyViaPsrpSession(importModuleOptions, null, FullyQualifiedName, this.PSSession);
1834+
foreach (ModuleSpecification modulespec in FullyQualifiedName)
1835+
{
1836+
ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ModuleLoad, modulespec.Name);
1837+
}
18211838
}
18221839
else
18231840
{

0 commit comments

Comments
 (0)