diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs
index 58ba1aa107..f7c2a73ba2 100644
--- a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs
+++ b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs
@@ -157,6 +157,20 @@ namespace System.Management.Automation
EnabledExperimentalFeatureNames = ProcessEnabledFeatures(enabledFeatures);
}
+ ///
+ /// We need to notify which features were not enabled.
+ ///
+ private static void SendTelemetryForDeactivatedFeatures(ReadOnlyBag enabledFeatures)
+ {
+ foreach (var feature in EngineExperimentalFeatures)
+ {
+ if (!enabledFeatures.Contains(feature.Name))
+ {
+ ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ExperimentalEngineFeatureDeactivation, feature.Name);
+ }
+ }
+ }
+
///
/// Process the array of enabled feature names retrieved from configuration.
/// Ignore invalid feature names and unavailable engine feature names, and
@@ -198,7 +212,9 @@ namespace System.Management.Automation
}
}
- return new ReadOnlyBag(new HashSet(list, StringComparer.OrdinalIgnoreCase));
+ ReadOnlyBag features = new(new HashSet(list, StringComparer.OrdinalIgnoreCase));
+ SendTelemetryForDeactivatedFeatures(features);
+ return features;
}
///
diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs
index b825c024ef..f34fc1987b 100644
--- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs
+++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs
@@ -18,6 +18,7 @@ using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Xml;
+using Microsoft.PowerShell.Telemetry;
using Dbg = System.Management.Automation.Diagnostics;
namespace System.Management.Automation
@@ -872,8 +873,36 @@ namespace System.Management.Automation
this.commandRuntime.PipelineProcessor.ExecutionFailed = true;
- if (!ExperimentalFeature.IsEnabled(ExperimentalFeature.PSNativeCommandErrorActionPreferenceFeatureName)
- || !Command.Context.GetBooleanPreference(SpecialVariables.PSNativeCommandUseErrorActionPreferenceVarPath, defaultPref: false, out _))
+ // Feature is not enabled, so return
+ if (!ExperimentalFeature.IsEnabled(ExperimentalFeature.PSNativeCommandErrorActionPreferenceFeatureName))
+ {
+ return;
+ }
+
+ // We send telemetry information only if the feature is enabled.
+ // This shouldn't be done once, because it's a run-time check we should send telemetry every time.
+ // Report on the following conditions:
+ // - The variable is not present
+ // - The value is not set (variable is null)
+ // - The value is set to true or false
+ bool useDefaultSetting;
+ bool nativeErrorActionPreferenceSetting = Command.Context.GetBooleanPreference(
+ SpecialVariables.PSNativeCommandUseErrorActionPreferenceVarPath,
+ defaultPref: false,
+ out useDefaultSetting);
+
+ // The variable is unset
+ if (useDefaultSetting)
+ {
+ ApplicationInsightsTelemetry.SendExperimentalUseData(ExperimentalFeature.PSNativeCommandErrorActionPreferenceFeatureName, "unset");
+ return;
+ }
+
+ // Send the value that was set.
+ ApplicationInsightsTelemetry.SendExperimentalUseData(ExperimentalFeature.PSNativeCommandErrorActionPreferenceFeatureName, nativeErrorActionPreferenceSetting.ToString());
+
+ // if it was explicitly set to false, return
+ if (!nativeErrorActionPreferenceSetting)
{
return;
}
diff --git a/src/System.Management.Automation/utils/Telemetry.cs b/src/System.Management.Automation/utils/Telemetry.cs
index 6ae1a93d6d..88193cc03a 100644
--- a/src/System.Management.Automation/utils/Telemetry.cs
+++ b/src/System.Management.Automation/utils/Telemetry.cs
@@ -38,12 +38,31 @@ namespace Microsoft.PowerShell.Telemetry
///
WinCompatModuleLoad,
+ ///
+ /// Send telemetry for experimental module feature deactivation.
+ /// All experimental engine features will be have telemetry.
+ ///
+ ExperimentalEngineFeatureDeactivation,
+
///
/// Send telemetry for experimental module feature activation.
/// All experimental engine features will be have telemetry.
///
ExperimentalEngineFeatureActivation,
+ ///
+ /// Send telemetry for an experimental feature when use.
+ ///
+ ExperimentalFeatureUse,
+
+ ///
+ /// Send telemetry for experimental module feature deactivation.
+ /// Experimental module features will send telemetry based on the module it is in.
+ /// If we send telemetry for the module, we will also do so for any experimental feature
+ /// in that module.
+ ///
+ ExperimentalModuleFeatureDeactivation,
+
///
/// Send telemetry for experimental module feature activation.
/// Experimental module features will send telemetry based on the module it is in.
@@ -126,7 +145,7 @@ namespace Microsoft.PowerShell.Telemetry
private static readonly HashSet s_knownModules;
/// Gets a value indicating whether telemetry can be sent.
- public static bool CanSendTelemetry { get; private set; }
+ public static bool CanSendTelemetry { get; private set; } = false;
///
/// Initializes static members of the class.
@@ -703,9 +722,12 @@ namespace Microsoft.PowerShell.Telemetry
case TelemetryType.PowerShellCreate:
case TelemetryType.RemoteSessionOpen:
case TelemetryType.ExperimentalEngineFeatureActivation:
+ case TelemetryType.ExperimentalEngineFeatureDeactivation:
+ case TelemetryType.ExperimentalFeatureUse:
s_telemetryClient.GetMetric(metricName, "uuid", "SessionId", "Detail").TrackValue(metricValue: 1.0, s_uniqueUserIdentifier, s_sessionId, data);
break;
case TelemetryType.ExperimentalModuleFeatureActivation:
+ case TelemetryType.ExperimentalModuleFeatureDeactivation:
string experimentalFeatureName = GetExperimentalFeatureName(data);
s_telemetryClient.GetMetric(metricName, "uuid", "SessionId", "Detail").TrackValue(metricValue: 1.0, s_uniqueUserIdentifier, s_sessionId, experimentalFeatureName);
break;
@@ -718,6 +740,21 @@ namespace Microsoft.PowerShell.Telemetry
}
}
+ ///
+ /// Send additional information about an experimental feature as it is used.
+ ///
+ /// The name of the experimental feature.
+ /// The details about the experimental feature use.
+ internal static void SendExperimentalUseData(string featureName, string detail)
+ {
+ if (!CanSendTelemetry)
+ {
+ return;
+ }
+
+ ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.ExperimentalFeatureUse, string.Join(":", featureName, detail));
+ }
+
// Get the experimental feature name. If we can report it, we'll return the name of the feature, otherwise, we'll return "anonymous"
private static string GetExperimentalFeatureName(string featureNameToValidate)
{
@@ -779,6 +816,7 @@ namespace Microsoft.PowerShell.Telemetry
properties.Add("UUID", s_uniqueUserIdentifier);
properties.Add("GitCommitID", PSVersionInfo.GitCommitId);
properties.Add("OSDescription", RuntimeInformation.OSDescription);
+ properties.Add("RuntimeIdentifier", RuntimeInformation.RuntimeIdentifier);
properties.Add("OSChannel", string.IsNullOrEmpty(channel) ? "unknown" : channel);
properties.Add("StartMode", string.IsNullOrEmpty(mode) ? "unknown" : mode);