Installer Success Reporting for Windows
Issue https://github.com/dotnet/cli/issues/7091 Add internal command dotnet internal-reportinstallsuccess. Before Windows installer finishes, run this command instead of dotnet new. It will trigger the first time experience as well as sending telemetry with installer exe name. This command blocks to ensure that the webservice call completes.
This commit is contained in:
parent
44cd1cf385
commit
191e3e3019
8 changed files with 119 additions and 5 deletions
|
@ -37,6 +37,7 @@
|
|||
</MsiPackage>
|
||||
<MsiPackage SourceFile="$(var.CLISDKMsiSourcePath)">
|
||||
<MsiProperty Name="DOTNETHOME" Value="[DOTNETHOME]" />
|
||||
<MsiProperty Name="EXEFULLPATH" Value="[WixBundleOriginalSource]" />
|
||||
</MsiPackage>
|
||||
<?if $(var.Platform)=x86?>
|
||||
<PackageGroupRef Id="PG_AspNetCorePackageStore_x86"/>
|
||||
|
|
|
@ -30,12 +30,20 @@
|
|||
|
||||
<CustomActionRef Id="WixBroadcastEnvironmentChange" />
|
||||
|
||||
<CustomAction Id="PropertyAssign" Property="QtExecDotnetnew" Value=""[DOTNETHOME]\dotnet.exe" new" Execute="immediate" />
|
||||
<CustomAction Id="QtExecDotnetnew" BinaryKey="WixCA" DllEntry="$(var.WixQuietExec)" Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||
<CustomAction Id="PropertyAssignPrimeCacheAndTelemetry"
|
||||
Property="QtExecPrimeCacheAndTelemetryTarget"
|
||||
Value=""[DOTNETHOME]\dotnet.exe" internal-reportinstallsuccess "[EXEFULLPATH]""
|
||||
Execute="immediate" />
|
||||
<CustomAction Id="QtExecPrimeCacheAndTelemetryTarget"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="$(var.WixQuietExec)"
|
||||
Execute="deferred"
|
||||
Return="ignore"
|
||||
Impersonate="no"/>
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="PropertyAssign" Before="QtExecDotnetnew" />
|
||||
<Custom Action="QtExecDotnetnew" Before="InstallFinalize" />
|
||||
<Custom Action="PropertyAssignPrimeCacheAndTelemetry" Before="QtExecPrimeCacheAndTelemetryTarget" />
|
||||
<Custom Action="QtExecPrimeCacheAndTelemetryTarget" Before="InstallFinalize" />
|
||||
</InstallExecuteSequence>
|
||||
</Product>
|
||||
<Fragment>
|
||||
|
|
|
@ -143,6 +143,10 @@ namespace Microsoft.DotNet.Cli
|
|||
["parse"] = new BuiltInCommandMetadata
|
||||
{
|
||||
Command = ParseCommand.Run
|
||||
},
|
||||
["internal-reportinstallsuccess"] = new BuiltInCommandMetadata
|
||||
{
|
||||
Command = InternalReportinstallsuccess.Run
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Microsoft.DotNet.Cli
|
|||
Create.Command("msbuild", ""),
|
||||
Create.Command("vstest", ""),
|
||||
CompleteCommandParser.Complete(),
|
||||
InternalReportinstallsuccessCommandParser.InternalReportinstallsuccess(),
|
||||
CommonOptions.HelpOption(),
|
||||
Create.Option("--info", ""),
|
||||
Create.Option("-d", ""),
|
||||
|
|
|
@ -76,6 +76,15 @@ namespace Microsoft.DotNet.Cli
|
|||
);
|
||||
}
|
||||
|
||||
public void ThreadBlockingTrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TrackEventTask(eventName, properties, measurements);
|
||||
}
|
||||
|
||||
private void InitializeTelemetry()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.DotNet.Configurer;
|
||||
|
||||
namespace Microsoft.DotNet.Cli
|
||||
{
|
||||
public class InternalReportinstallsuccess
|
||||
{
|
||||
internal const string TelemetrySessionIdEnvironmentVariableName = "DOTNET_CLI_TELEMETRY_SESSIONID";
|
||||
|
||||
public static int Run(string[] args)
|
||||
{
|
||||
var telemetry = new ThreadBlockingTelemetry();
|
||||
ProcessInputAndSendTelemetry(args, telemetry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void ProcessInputAndSendTelemetry(string[] args, ITelemetry telemetry)
|
||||
{
|
||||
var parser = Parser.Instance;
|
||||
var result = parser.ParseFrom("dotnet internal-reportinstallsuccess", args);
|
||||
|
||||
var internalReportinstallsuccess = result["dotnet"]["internal-reportinstallsuccess"];
|
||||
|
||||
var exeName = Path.GetFileName(internalReportinstallsuccess.Arguments.Single());
|
||||
telemetry.TrackEvent(
|
||||
"reportinstallsuccess",
|
||||
new Dictionary<string, string> { { "exeName", exeName } },
|
||||
new Dictionary<string, double>());
|
||||
}
|
||||
|
||||
internal class ThreadBlockingTelemetry : ITelemetry
|
||||
{
|
||||
private Telemetry telemetry;
|
||||
|
||||
internal ThreadBlockingTelemetry()
|
||||
{
|
||||
var sessionId =
|
||||
Environment.GetEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName);
|
||||
telemetry = new Telemetry(new FirstTimeUseNoticeSentinel(new CliFallbackFolderPathCalculator()), sessionId);
|
||||
}
|
||||
public bool Enabled => telemetry.Enabled;
|
||||
|
||||
public void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
|
||||
{
|
||||
telemetry.ThreadBlockingTrackEvent(eventName, properties, measurements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.Cli.CommandLine;
|
||||
|
||||
namespace Microsoft.DotNet.Cli
|
||||
{
|
||||
internal static class InternalReportinstallsuccessCommandParser
|
||||
{
|
||||
public static Command InternalReportinstallsuccess() =>
|
||||
Create.Command(
|
||||
"internal-reportinstallsuccess", "internal only",
|
||||
Accept.ExactlyOneArgument());
|
||||
}
|
||||
}
|
|
@ -17,14 +17,15 @@ namespace Microsoft.DotNet.Tests
|
|||
public bool Enabled { get; set; }
|
||||
|
||||
public string EventName { get; set; }
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
|
||||
{
|
||||
EventName = eventName;
|
||||
Properties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class TelemetryCommandTests : TestBase
|
||||
{
|
||||
[Fact]
|
||||
|
@ -35,5 +36,23 @@ namespace Microsoft.DotNet.Tests
|
|||
Microsoft.DotNet.Cli.Program.ProcessArgs(args, mockTelemetry);
|
||||
Assert.Equal(mockTelemetry.EventName, args[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InternalreportinstallsuccessCommandCollectExeNameWithEventname()
|
||||
{
|
||||
MockTelemetry mockTelemetry = new MockTelemetry();
|
||||
string[] args = { "c:\\mypath\\dotnet-sdk-latest-win-x64.exe" };
|
||||
|
||||
InternalReportinstallsuccess.ProcessInputAndSendTelemetry(args, mockTelemetry);
|
||||
|
||||
mockTelemetry.EventName.Should().Be("reportinstallsuccess");
|
||||
mockTelemetry.Properties["exeName"].Should().Be("dotnet-sdk-latest-win-x64.exe");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InternalreportinstallsuccessCommandIsRegistedInBuiltIn()
|
||||
{
|
||||
BuiltInCommandsCatalog.Commands.Should().ContainKey("internal-reportinstallsuccess");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue