Skip to content

Commit 53fdb6e

Browse files
committed
WIP: tool install
1 parent 35778b0 commit 53fdb6e

File tree

7 files changed

+90
-20
lines changed

7 files changed

+90
-20
lines changed

Directory.Packages.props

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@
9595
<PackageVersion Include="NuGet.ProjectModel" Version="$(NuGetProjectModelPackageVersion)" />
9696
<PackageVersion Include="NuGet.Protocol" Version="$(NuGetBuildTasksPackageVersion)" />
9797
<PackageVersion Include="NuGet.Versioning" Version="$(NuGetVersioningPackageVersion)" />
98+
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
99+
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
100+
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />
98101
<PackageVersion Include="runtime.linux-musl-x64.Microsoft.NETCore.DotNetHostResolver" Version="$(MicrosoftNETCoreDotNetHostResolverPackageVersion)" />
99102
<PackageVersion Include="runtime.linux-x64.Microsoft.NETCore.DotNetHostResolver" Version="$(MicrosoftNETCoreDotNetHostResolverPackageVersion)" />
100103
<PackageVersion Include="runtime.osx-x64.Microsoft.NETCore.DotNetHostResolver" Version="$(MicrosoftNETCoreDotNetHostResolverPackageVersion)" />
@@ -127,7 +130,6 @@
127130
<PackageVersion Include="Xunit.Combinatorial" Version="$(XunitCombinatorialVersion)" />
128131
<PackageVersion Include="xunit.console" Version="$(XUnitVersion)" />
129132
</ItemGroup>
130-
131133
<!-- Use different versions of Microsoft.Build.* depending on whether the output will be used in
132134
.NET Framework (VS) or only in the .NET SDK.
133135
@@ -159,4 +161,4 @@
159161
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildMinimumVersion)" />
160162
<PackageVersion Include="Microsoft.NET.StringTools" Version="$(MicrosoftBuildMinimumVersion)" />
161163
</ItemGroup>
162-
</Project>
164+
</Project>

src/Cli/dotnet/Activities.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Diagnostics;
2+
using Microsoft.DotNet.Cli.Utils;
3+
4+
namespace Microsoft.DotNet.Cli;
5+
6+
7+
public static class Activities
8+
{
9+
public static ActivitySource s_source = new("dotnet-cli", Product.Version);
10+
}

src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ public override int Execute()
144144

145145
private int ExecuteInstallCommand(PackageId packageId)
146146
{
147+
using var _activity = Activities.s_source.StartActivity("install-tool");
148+
_activity?.DisplayName = $"Install {packageId}";
149+
_activity?.SetTag("toolId", packageId);
147150
ValidateArguments();
148151

149152
DirectoryPath? toolPath = null;
@@ -167,12 +170,14 @@ private int ExecuteInstallCommand(PackageId packageId)
167170
if (oldPackageNullable != null)
168171
{
169172
NuGetVersion nugetVersion = GetBestMatchNugetVersion(packageId, versionRange, toolPackageDownloader);
173+
_activity?.DisplayName = $"Install {packageId}@{nugetVersion}";
174+
_activity?.SetTag("toolVersion", nugetVersion);
170175

171176
if (ToolVersionAlreadyInstalled(oldPackageNullable, nugetVersion))
172177
{
173178
_reporter.WriteLine(string.Format(CliCommandStrings.ToolAlreadyInstalled, oldPackageNullable.Id, oldPackageNullable.Version.ToNormalizedString()).Green());
174179
return 0;
175-
}
180+
}
176181
}
177182

178183
TransactionalAction.Run(() =>
@@ -188,6 +193,7 @@ private int ExecuteInstallCommand(PackageId packageId)
188193

189194
RunWithHandlingInstallError(() =>
190195
{
196+
var toolPackageDownloaderActivity = Activities.s_source.StartActivity("download-tool-package");
191197
IToolPackage newInstalledPackage = toolPackageDownloader.InstallPackage(
192198
new PackageLocation(nugetConfig: GetConfigFile(), sourceFeedOverrides: _source, additionalFeeds: _addSource),
193199
packageId: packageId,
@@ -199,6 +205,7 @@ private int ExecuteInstallCommand(PackageId packageId)
199205
verifySignatures: _verifySignatures ?? true,
200206
restoreActionConfig: restoreActionConfig
201207
);
208+
toolPackageDownloaderActivity?.Dispose();
202209

203210
EnsureVersionIsHigher(oldPackageNullable, newInstalledPackage, _allowPackageDowngrade);
204211

@@ -215,9 +222,10 @@ private int ExecuteInstallCommand(PackageId packageId)
215222
null :
216223
NuGetFramework.Parse(_framework);
217224
}
225+
var shimActivity = Activities.s_source.StartActivity("create-shell-shim");
218226
string appHostSourceDirectory = _shellShimTemplateFinder.ResolveAppHostSourceDirectoryAsync(_architectureOption, framework, RuntimeInformation.ProcessArchitecture).Result;
219-
220227
shellShimRepository.CreateShim(newInstalledPackage.Command, newInstalledPackage.PackagedShims);
228+
shimActivity?.Dispose();
221229

222230
foreach (string w in newInstalledPackage.Warnings)
223231
{
@@ -303,7 +311,7 @@ private static void RunWithHandlingUninstallError(Action uninstallAction, Packag
303311
{
304312
try
305313
{
306-
uninstallAction();
314+
uninstallAction();
307315
}
308316
catch (Exception ex)
309317
when (ToolUninstallCommandLowLevelErrorConverter.ShouldConvertToUserFacingError(ex))
@@ -381,7 +389,7 @@ private void PrintSuccessMessage(IToolPackage oldPackage, IToolPackage newInstal
381389
{
382390
_reporter.WriteLine(
383391
string.Format(
384-
392+
385393
newInstalledPackage.Version.IsPrerelease ?
386394
CliCommandStrings.UpdateSucceededPreVersionNoChange : CliCommandStrings.UpdateSucceededStableVersionNoChange,
387395
newInstalledPackage.Id, newInstalledPackage.Version).Green());

src/Cli/dotnet/Program.cs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,45 @@
1818
using Microsoft.DotNet.Configurer;
1919
using Microsoft.Extensions.EnvironmentAbstractions;
2020
using NuGet.Frameworks;
21+
using OpenTelemetry;
22+
using OpenTelemetry.Metrics;
23+
using OpenTelemetry.Resources;
24+
using OpenTelemetry.Trace;
2125
using CommandResult = System.CommandLine.Parsing.CommandResult;
2226

2327
namespace Microsoft.DotNet.Cli;
2428

25-
public static class Activities
26-
{
27-
public static ActivitySource s_source = new("dotnet-cli", Product.Version);
28-
}
29-
3029
public class Program
3130
{
3231
private static readonly string ToolPathSentinelFileName = $"{Product.Version}.toolpath.sentinel";
3332

3433
public static ITelemetry TelemetryClient;
34+
// Create a new OpenTelemetry tracer provider and add the Azure Monitor trace exporter and the OTLP trace exporter.
35+
// It is important to keep the TracerProvider instance active throughout the process lifetime.
36+
private static TracerProvider tracerProvider = Sdk.CreateTracerProviderBuilder()
37+
.ConfigureResource(r =>
38+
{
39+
r.AddService("dotnet-cli", serviceVersion: Product.Version);
40+
})
41+
.AddSource(Activities.s_source.Name)
42+
.AddHttpClientInstrumentation()
43+
.AddOtlpExporter()
44+
.Build();
45+
46+
// Create a new OpenTelemetry meter provider and add the Azure Monitor metric exporter and the OTLP metric exporter.
47+
// It is important to keep the MetricsProvider instance active throughout the process lifetime.
48+
private static MeterProvider metricsProvider = Sdk.CreateMeterProviderBuilder()
49+
.ConfigureResource(r =>
50+
{
51+
r.AddService("dotnet-cli", serviceVersion: Product.Version);
52+
})
53+
.AddMeter(Activities.s_source.Name)
54+
.AddHttpClientInstrumentation()
55+
.AddRuntimeInstrumentation()
56+
.AddOtlpExporter()
57+
.Build();
58+
59+
3560
public static int Main(string[] args)
3661
{
3762
// capture the time to we can compute muxer/host startup overhead
@@ -88,17 +113,19 @@ public static int Main(string[] args)
88113
}
89114
finally
90115
{
116+
tracerProvider?.ForceFlush();
117+
metricsProvider?.ForceFlush();
91118
Activities.s_source.Dispose();
92119
}
93120
}
94121

95122
private static void TrackHostStartup(DateTime mainTimeStamp)
96123
{
97124
var hostStartupActivity = Activities.s_source.CreateActivity("host-startup", ActivityKind.Server);
98-
hostStartupActivity.SetStartTime(Process.GetCurrentProcess().StartTime);
99-
hostStartupActivity.SetEndTime(mainTimeStamp);
100-
hostStartupActivity.SetStatus(ActivityStatusCode.Ok);
101-
hostStartupActivity.Dispose();
125+
hostStartupActivity?.SetStartTime(Process.GetCurrentProcess().StartTime);
126+
hostStartupActivity?.SetEndTime(mainTimeStamp);
127+
hostStartupActivity?.SetStatus(ActivityStatusCode.Ok);
128+
hostStartupActivity?.Dispose();
102129
}
103130

104131
/// <summary>
@@ -181,8 +208,8 @@ internal static int ProcessArgs(string[] args)
181208
skipFirstTimeUseCheck: getStarOptionPassed);
182209
}
183210

184-
var telemetryClient = new Telemetry.Telemetry();
185-
TelemetryEventEntry.Subscribe(telemetryClient.TrackEvent);
211+
TelemetryClient = new Telemetry.Telemetry();
212+
TelemetryEventEntry.Subscribe(TelemetryClient.TrackEvent);
186213
TelemetryEventEntry.TelemetryFilter = new TelemetryFilter(Sha256Hasher.HashWithNormalizedCasing);
187214

188215
if (CommandLoggingContext.IsVerbose)
@@ -229,7 +256,7 @@ internal static int ProcessArgs(string[] args)
229256
}
230257
}
231258

232-
telemetryClient.Dispose();
259+
TelemetryClient.Dispose();
233260
return exitCode;
234261

235262
static int? TryRunFileBasedApp(ParseResult parseResult)
@@ -261,6 +288,16 @@ static void InvokeBuiltInCommand(ParseResult parseResult, out int exitCode)
261288
{
262289
Debug.Assert(parseResult.CanBeInvoked());
263290
using var _invocationActivity = Activities.s_source.StartActivity("invocation");
291+
// walk the parent command tree to find the top-level command name and get the full command name for this parseresult
292+
List<string> parentNames = [parseResult.CommandResult.Command.Name];
293+
var current = parseResult.CommandResult.Parent;
294+
while (parseResult.CommandResult.Parent is CommandResult parentCommandResult)
295+
{
296+
parentNames.Add(parentCommandResult.Command.Name);
297+
current = parentCommandResult.Parent;
298+
}
299+
parentNames.Reverse();
300+
_invocationActivity?.DisplayName = string.Join(' ', parentNames);
264301
try
265302
{
266303
exitCode = parseResult.Invoke();

src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ protected override NuGetVersion DownloadAndExtractPackage(
6161
bool includeUnlisted = false
6262
)
6363
{
64+
using var _downloadActivity = Activities.s_source.StartActivity("download-tool");
65+
_downloadActivity?.DisplayName = $"Downloading tool {packageId}@{packageVersion}";
6466
var versionFolderPathResolver = new VersionFolderPathResolver(packagesRootPath);
6567

6668
string? folderToDeleteOnFailure = null;
6769
return TransactionalAction.Run(() =>
6870
{
6971
var packagePath = nugetPackageDownloader.DownloadPackageAsync(packageId, packageVersion, packageSourceLocation,
7072
includeUnlisted: includeUnlisted, downloadFolder: new DirectoryPath(packagesRootPath)).ConfigureAwait(false).GetAwaiter().GetResult();
71-
73+
_downloadActivity?.AddEvent(new("Downloaded package"));
7274
folderToDeleteOnFailure = Path.GetDirectoryName(packagePath);
7375

7476
// look for package on disk and read the version
@@ -78,11 +80,15 @@ protected override NuGetVersion DownloadAndExtractPackage(
7880
{
7981
PackageArchiveReader reader = new(packageStream);
8082
version = new NuspecReader(reader.GetNuspec()).GetVersion();
83+
_downloadActivity?.AddEvent(new("Read package version"));
8184

8285
var packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(reader.GetNuspec()));
8386
var hashPath = versionFolderPathResolver.GetHashPath(packageId.ToString(), version);
84-
Directory.CreateDirectory(Path.GetDirectoryName(hashPath)!);
87+
_downloadActivity?.AddEvent(new("Calculated package hash"));
88+
89+
Directory.CreateDirectory(Path.GetDirectoryName(hashPath));
8590
File.WriteAllText(hashPath, packageHash);
91+
_downloadActivity?.AddEvent(new("Wrote package hash to disk"));
8692
}
8793

8894
if (verbosity.IsDetailedOrDiagnostic())
@@ -92,6 +98,7 @@ protected override NuGetVersion DownloadAndExtractPackage(
9298
// Extract the package
9399
var nupkgDir = versionFolderPathResolver.GetInstallPath(packageId.ToString(), version);
94100
nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(nupkgDir)).ConfigureAwait(false).GetAwaiter().GetResult();
101+
_downloadActivity?.AddEvent(new("Extracted package to disk"));
95102

96103
return version;
97104
}, rollback: () =>

src/Cli/dotnet/ToolPackage/ToolPackageDownloaderBase.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,10 @@ protected IToolPackage InstallGlobalToolPackageInternal(
187187
// Create parent directory in global tool store, for example dotnet\tools\.store\powershell
188188
_fileSystem.Directory.CreateDirectory(toolStoreTargetDirectory.GetParentPath().Value);
189189

190+
var _moveContentActivity = Activities.s_source.StartActivity("move-global-tool-content");
190191
// Move tool files from stage to final location
191192
FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.Directory.Move(_globalToolStageDir.Value, toolStoreTargetDirectory.Value));
193+
_moveContentActivity?.Dispose();
192194

193195
rollbackDirectory = toolStoreTargetDirectory.Value;
194196

@@ -374,6 +376,7 @@ protected void UpdateRuntimeConfig(
374376
ToolPackageInstance toolPackageInstance
375377
)
376378
{
379+
using var _updateRuntimeConfigActivity = Activities.s_source.StartActivity("update-runtimeconfig");
377380
var runtimeConfigFilePath = Path.ChangeExtension(toolPackageInstance.Command.Executable.Value, ".runtimeconfig.json");
378381

379382
// Update the runtimeconfig.json file

src/Cli/dotnet/dotnet.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
<PackageReference Include="Microsoft.Build" />
5959
<PackageReference Include="Microsoft.NET.HostModel" />
6060
<PackageReference Include="Microsoft.TemplateEngine.Orchestrator.RunnableProjects" />
61+
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
62+
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
63+
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
6164
<PackageReference Include="System.CommandLine" />
6265
<PackageReference Include="Microsoft.Deployment.DotNet.Releases" />
6366
<PackageReference Include="System.ServiceProcess.ServiceController" />

0 commit comments

Comments
 (0)