Skip to content

Commit a7d7526

Browse files
Add telemetry to check for specific tags when importing a module (#20371) (#20540)
1 parent dd56ad6 commit a7d7526

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

Diff for: src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ private PSModuleInfo ImportModule_LocallyViaName_WithTelemetry(ImportModuleOptio
619619
// avoid double reporting for WinCompat modules that go through CommandDiscovery\AutoloadSpecifiedModule
620620
if (!foundModule.IsWindowsPowerShellCompatModule)
621621
{
622-
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, foundModule.Name, foundModule.Version?.ToString());
622+
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, foundModule);
623623
#if LEGACYTELEMETRY
624624
TelemetryAPI.ReportModuleLoad(foundModule);
625625
#endif
@@ -893,7 +893,7 @@ private PSModuleInfo ImportModule_LocallyViaFQName(ImportModuleOptions importMod
893893

894894
if (foundModule != null)
895895
{
896-
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, foundModule.Name, foundModule.Version?.ToString());
896+
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, foundModule);
897897
SetModuleBaseForEngineModules(foundModule.Name, this.Context);
898898
}
899899

@@ -935,7 +935,7 @@ private IList<PSModuleInfo> ImportModule_RemotelyViaPsrpSession(
935935
// Send telemetry on the imported modules
936936
foreach (PSModuleInfo moduleInfo in remotelyImportedModules)
937937
{
938-
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(usingWinCompat ? TelemetryType.WinCompatModuleLoad : TelemetryType.ModuleLoad, moduleInfo.Name, moduleInfo.Version?.ToString());
938+
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(usingWinCompat ? TelemetryType.WinCompatModuleLoad : TelemetryType.ModuleLoad, moduleInfo);
939939
}
940940

941941
return remotelyImportedModules;
@@ -1866,7 +1866,7 @@ protected override void ProcessRecord()
18661866
// of doing Get-Module -list
18671867
foreach (PSModuleInfo module in ModuleInfo)
18681868
{
1869-
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, module.Name, module.Version?.ToString());
1869+
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, module);
18701870
RemoteDiscoveryHelper.DispatchModuleInfoProcessing(
18711871
module,
18721872
localAction: () =>
@@ -1926,7 +1926,7 @@ protected override void ProcessRecord()
19261926
ImportModule_RemotelyViaPsrpSession(importModuleOptions, null, FullyQualifiedName, this.PSSession);
19271927
foreach (ModuleSpecification modulespec in FullyQualifiedName)
19281928
{
1929-
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, modulespec.Name, modulespec.Version?.ToString());
1929+
ApplicationInsightsTelemetry.SendModuleTelemetryMetric(TelemetryType.ModuleLoad, modulespec.Name);
19301930
}
19311931
}
19321932
else if (this.ParameterSetName.Equals(ParameterSet_ViaWinCompat, StringComparison.OrdinalIgnoreCase)

Diff for: src/System.Management.Automation/utils/Telemetry.cs

+53-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
using System.Collections.Generic;
66
using System.Diagnostics;
77
using System.IO;
8+
using System.Linq;
89
using System.Management.Automation;
910
using System.Runtime.InteropServices;
11+
using System.Security.AccessControl;
1012
using System.Threading;
1113

1214
using Microsoft.ApplicationInsights;
15+
using Microsoft.ApplicationInsights.Metrics;
1316
using Microsoft.ApplicationInsights.Channel;
1417
using Microsoft.ApplicationInsights.Extensibility;
1518
using Microsoft.ApplicationInsights.Extensibility.Implementation;
@@ -124,6 +127,9 @@ public static class ApplicationInsightsTelemetry
124127
// Use '0.0' as the string for an anonymous module version
125128
private const string AnonymousVersion = "0.0";
126129

130+
// Use 'n/a' as the string when there's no tag to report
131+
private const string NoTag = "n/a";
132+
127133
// the telemetry failure string
128134
private const string _telemetryFailure = "TELEMETRY_FAILURE";
129135

@@ -140,9 +146,11 @@ public static class ApplicationInsightsTelemetry
140146
private static int s_startupEventSent = 0;
141147

142148
/// Use a hashset for quick lookups.
143-
/// We send telemetry only a known set of modules.
144-
/// If it's not in the list (initialized in the static constructor), then we report anonymous.
149+
/// We send telemetry only a known set of modules and tags.
150+
/// If it's not in the list (initialized in the static constructor), then we report anonymous
151+
/// or don't report anything (in the case of tags).
145152
private static readonly HashSet<string> s_knownModules;
153+
private static readonly HashSet<string> s_knownModuleTags;
146154

147155
/// <summary>Gets a value indicating whether telemetry can be sent.</summary>
148156
public static bool CanSendTelemetry { get; private set; } = false;
@@ -601,6 +609,12 @@ static ApplicationInsightsTelemetry()
601609
"xWindowsUpdate",
602610
};
603611

612+
// use a hashset when looking for module names, it should be quicker than a string comparison
613+
s_knownModuleTags = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
614+
{
615+
"CrescendoBuilt",
616+
};
617+
604618
s_uniqueUserIdentifier = GetUniqueIdentifier().ToString();
605619
}
606620
}
@@ -671,15 +685,49 @@ private static bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
671685
return defaultValue;
672686
}
673687

688+
/// <summary>
689+
/// Send module load telemetry as a metric.
690+
/// For modules we send the module name (if allowed), and the version.
691+
/// Some modules (CIM) will continue use the string alternative method.
692+
/// </summary>
693+
/// <param name="telemetryType">The type of telemetry that we'll be sending.</param>
694+
/// <param name="moduleInfo">The module to report. If it is not allowed, then it is set to 'anonymous'.</param>
695+
internal static void SendModuleTelemetryMetric(TelemetryType telemetryType, PSModuleInfo moduleInfo)
696+
{
697+
if (!CanSendTelemetry)
698+
{
699+
return;
700+
}
701+
702+
// Package up the module name, version, and known tags as a metric.
703+
// Note that the allowed tags will be a comma separated list which will need to
704+
// be handled in the telemetry query.
705+
try
706+
{
707+
string allowedModuleName = GetModuleName(moduleInfo.Name);
708+
string allowedModuleVersion = allowedModuleName == Anonymous ? AnonymousVersion : moduleInfo.Version?.ToString();
709+
var allowedModuleTags = moduleInfo.Tags.Where(t => s_knownModuleTags.Contains(t)).Distinct();
710+
string allowedModuleTagString = allowedModuleTags.Any() ? string.Join(',', allowedModuleTags) : NoTag;
711+
712+
s_telemetryClient.
713+
GetMetric(new MetricIdentifier(string.Empty, telemetryType.ToString(), "uuid", "SessionId", "ModuleName", "Version", "Tag")).
714+
TrackValue(metricValue: 1.0, s_uniqueUserIdentifier, s_sessionId, allowedModuleName, allowedModuleVersion, allowedModuleTagString);
715+
}
716+
catch
717+
{
718+
// Ignore errors.
719+
}
720+
721+
}
722+
674723
/// <summary>
675724
/// Send module load telemetry as a metric.
676725
/// For modules we send the module name (if allowed), and the version.
677726
/// Some modules (CIM) will continue use the string alternative method.
678727
/// </summary>
679728
/// <param name="telemetryType">The type of telemetry that we'll be sending.</param>
680729
/// <param name="moduleName">The module name to report. If it is not allowed, then it is set to 'anonymous'.</param>
681-
/// <param name="moduleVersion">The module version to report. The default value is the anonymous version '0.0.0.0'.</param>
682-
internal static void SendModuleTelemetryMetric(TelemetryType telemetryType, string moduleName, string moduleVersion = AnonymousVersion)
730+
internal static void SendModuleTelemetryMetric(TelemetryType telemetryType, string moduleName)
683731
{
684732
if (!CanSendTelemetry)
685733
{
@@ -689,8 +737,7 @@ internal static void SendModuleTelemetryMetric(TelemetryType telemetryType, stri
689737
try
690738
{
691739
string allowedModuleName = GetModuleName(moduleName);
692-
string allowedModuleVersion = allowedModuleName == Anonymous ? AnonymousVersion : moduleVersion;
693-
s_telemetryClient.GetMetric(telemetryType.ToString(), "uuid", "SessionId", "ModuleName", "Version").TrackValue(metricValue: 1.0, s_uniqueUserIdentifier, s_sessionId, allowedModuleName, allowedModuleVersion);
740+
s_telemetryClient.GetMetric(telemetryType.ToString(), "uuid", "SessionId", "ModuleName", "Version").TrackValue(metricValue: 1.0, s_uniqueUserIdentifier, s_sessionId, allowedModuleName, AnonymousVersion);
694741
}
695742
catch
696743
{

0 commit comments

Comments
 (0)