Skip to content

Commit c73c4cc

Browse files
Copilotbaronfel
andcommitted
Share telemetry central logger instance between ProjectCollection and Build calls
Co-authored-by: baronfel <[email protected]>
1 parent 145a66f commit c73c4cc

File tree

5 files changed

+81
-50
lines changed

5 files changed

+81
-50
lines changed

src/Cli/dotnet/Commands/Run/RunCommand.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -402,31 +402,36 @@ internal ICommand GetTargetCommand(Func<ProjectCollection, ProjectInstance>? pro
402402

403403
Reporter.Verbose.WriteLine("Getting target command: evaluating project.");
404404
FacadeLogger? logger = LoggerUtility.DetermineBinlogger([.. MSBuildArgs.OtherMSBuildArgs], "dotnet-run");
405-
var project = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger);
405+
var (project, telemetryCentralLogger) = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger);
406406
ValidatePreconditions(project);
407-
InvokeRunArgumentsTarget(project, NoBuild, logger, MSBuildArgs);
407+
InvokeRunArgumentsTarget(project, NoBuild, logger, MSBuildArgs, telemetryCentralLogger);
408408
logger?.ReallyShutdown();
409409
var runProperties = RunProperties.FromProject(project).WithApplicationArguments(ApplicationArgs);
410410
var command = CreateCommandFromRunProperties(runProperties);
411411
return command;
412412

413-
static ProjectInstance EvaluateProject(string? projectFilePath, Func<ProjectCollection, ProjectInstance>? projectFactory, MSBuildArgs msbuildArgs, ILogger? binaryLogger)
413+
static (ProjectInstance project, ILogger? telemetryCentralLogger) EvaluateProject(string? projectFilePath, Func<ProjectCollection, ProjectInstance>? projectFactory, MSBuildArgs msbuildArgs, ILogger? binaryLogger)
414414
{
415415
Debug.Assert(projectFilePath is not null || projectFactory is not null);
416416

417417
var globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs);
418418

419-
// Include telemetry logger for evaluation
420-
var loggers = ProjectInstanceExtensions.CreateLoggersWithTelemetry(binaryLogger is null ? null : [binaryLogger]);
419+
// Include telemetry logger for evaluation and capture it for reuse in builds
420+
var (loggers, telemetryCentralLogger) = ProjectInstanceExtensions.CreateLoggersWithTelemetry(binaryLogger is null ? null : [binaryLogger]);
421421
var collection = new ProjectCollection(globalProperties: globalProperties, loggers: loggers, toolsetDefinitionLocations: ToolsetDefinitionLocations.Default);
422422

423+
ProjectInstance projectInstance;
423424
if (projectFilePath is not null)
424425
{
425-
return collection.LoadProject(projectFilePath).CreateProjectInstance();
426+
projectInstance = collection.LoadProject(projectFilePath).CreateProjectInstance();
427+
}
428+
else
429+
{
430+
Debug.Assert(projectFactory is not null);
431+
projectInstance = projectFactory(collection);
426432
}
427433

428-
Debug.Assert(projectFactory is not null);
429-
return projectFactory(collection);
434+
return (projectInstance, telemetryCentralLogger);
430435
}
431436

432437
static void ValidatePreconditions(ProjectInstance project)
@@ -482,7 +487,7 @@ static ICommand CreateCommandForCscBuiltProgram(string entryPointFileFullPath, s
482487
return command;
483488
}
484489

485-
static void InvokeRunArgumentsTarget(ProjectInstance project, bool noBuild, FacadeLogger? binaryLogger, MSBuildArgs buildArgs)
490+
static void InvokeRunArgumentsTarget(ProjectInstance project, bool noBuild, FacadeLogger? binaryLogger, MSBuildArgs buildArgs, ILogger? telemetryCentralLogger)
486491
{
487492
List<ILogger> loggersForBuild = [
488493
TerminalLogger.CreateTerminalOrConsoleLogger([$"--verbosity:{LoggerVerbosity.Quiet.ToString().ToLowerInvariant()}", ..buildArgs.OtherMSBuildArgs])
@@ -492,7 +497,7 @@ static void InvokeRunArgumentsTarget(ProjectInstance project, bool noBuild, Faca
492497
loggersForBuild.Add(binaryLogger);
493498
}
494499

495-
if (!project.BuildWithTelemetry([Constants.ComputeRunArguments], loggersForBuild, null, out _))
500+
if (!project.BuildWithTelemetry([Constants.ComputeRunArguments], loggersForBuild, null, out _, telemetryCentralLogger))
496501
{
497502
throw new GracefulException(CliCommandStrings.RunCommandEvaluationExceptionBuildFailed, Constants.ComputeRunArguments);
498503
}

src/Cli/dotnet/Commands/Test/MTP/MSBuildUtility.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.Build.Evaluation;
77
using Microsoft.Build.Evaluation.Context;
88
using Microsoft.Build.Execution;
9+
using Microsoft.Build.Framework;
910
using Microsoft.DotNet.Cli.Commands.Restore;
1011
using Microsoft.DotNet.Cli.Commands.Run;
1112
using Microsoft.DotNet.Cli.Extensions;
@@ -37,11 +38,11 @@ public static (IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModul
3738

3839
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments(buildOptions.MSBuildArgs, CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption());
3940

40-
// Include telemetry logger for evaluation
41-
var loggers = ProjectInstanceExtensions.CreateLoggersWithTelemetry(logger is null ? null : [logger]);
41+
// Include telemetry logger for evaluation and capture it for reuse in builds
42+
var (loggers, telemetryCentralLogger) = ProjectInstanceExtensions.CreateLoggersWithTelemetry(logger is null ? null : [logger]);
4243
using var collection = new ProjectCollection(globalProperties: CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs), loggers: loggers, toolsetDefinitionLocations: ToolsetDefinitionLocations.Default);
4344
var evaluationContext = EvaluationContext.Create(EvaluationContext.SharingPolicy.Shared);
44-
ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerModules> projects = GetProjectsProperties(collection, evaluationContext, solutionModel.SolutionProjects.Select(p => Path.Combine(rootDirectory, p.FilePath)), buildOptions);
45+
ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerModules> projects = GetProjectsProperties(collection, evaluationContext, solutionModel.SolutionProjects.Select(p => Path.Combine(rootDirectory, p.FilePath)), buildOptions, telemetryCentralLogger);
4546
logger?.ReallyShutdown();
4647
collection.UnloadAllProjects();
4748

@@ -61,11 +62,11 @@ public static (IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModul
6162

6263
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments(buildOptions.MSBuildArgs, CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption());
6364

64-
// Include telemetry logger for evaluation
65-
var loggers = ProjectInstanceExtensions.CreateLoggersWithTelemetry(logger is null ? null : [logger]);
65+
// Include telemetry logger for evaluation and capture it for reuse in builds
66+
var (loggers, telemetryCentralLogger) = ProjectInstanceExtensions.CreateLoggersWithTelemetry(logger is null ? null : [logger]);
6667
using var collection = new ProjectCollection(globalProperties: CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs), loggers, toolsetDefinitionLocations: ToolsetDefinitionLocations.Default);
6768
var evaluationContext = EvaluationContext.Create(EvaluationContext.SharingPolicy.Shared);
68-
IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projects = SolutionAndProjectUtility.GetProjectProperties(projectFilePath, collection, evaluationContext, buildOptions);
69+
IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projects = SolutionAndProjectUtility.GetProjectProperties(projectFilePath, collection, evaluationContext, buildOptions, telemetryCentralLogger);
6970
logger?.ReallyShutdown();
7071
collection.UnloadAllProjects();
7172
return (projects, isBuiltOrRestored);
@@ -134,7 +135,7 @@ private static bool BuildOrRestoreProjectOrSolution(string filePath, BuildOption
134135
return result == (int)BuildResultCode.Success;
135136
}
136137

137-
private static ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerModules> GetProjectsProperties(ProjectCollection projectCollection, EvaluationContext evaluationContext, IEnumerable<string> projects, BuildOptions buildOptions)
138+
private static ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerModules> GetProjectsProperties(ProjectCollection projectCollection, EvaluationContext evaluationContext, IEnumerable<string> projects, BuildOptions buildOptions, ILogger? telemetryCentralLogger)
138139
{
139140
var allProjects = new ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerModules>();
140141

@@ -145,7 +146,7 @@ private static ConcurrentBag<ParallelizableTestModuleGroupWithSequentialInnerMod
145146
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
146147
(project) =>
147148
{
148-
IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projectsMetadata = SolutionAndProjectUtility.GetProjectProperties(project, projectCollection, evaluationContext, buildOptions);
149+
IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projectsMetadata = SolutionAndProjectUtility.GetProjectProperties(project, projectCollection, evaluationContext, buildOptions, telemetryCentralLogger);
149150
foreach (var projectMetadata in projectsMetadata)
150151
{
151152
allProjects.Add(projectMetadata);

src/Cli/dotnet/Commands/Test/MTP/SolutionAndProjectUtility.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.Build.Evaluation;
77
using Microsoft.Build.Evaluation.Context;
88
using Microsoft.Build.Execution;
9+
using Microsoft.Build.Framework;
910
using Microsoft.DotNet.Cli.Commands.Run;
1011
using Microsoft.DotNet.Cli.Commands.Run.LaunchSettings;
1112
using Microsoft.DotNet.Cli.Extensions;
@@ -217,7 +218,7 @@ public static string GetRootDirectory(string solutionOrProjectFilePath)
217218
return string.IsNullOrEmpty(fileDirectory) ? Directory.GetCurrentDirectory() : fileDirectory;
218219
}
219220

220-
public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> GetProjectProperties(string projectFilePath, ProjectCollection projectCollection, EvaluationContext evaluationContext, BuildOptions buildOptions)
221+
public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> GetProjectProperties(string projectFilePath, ProjectCollection projectCollection, EvaluationContext evaluationContext, BuildOptions buildOptions, ILogger? telemetryCentralLogger = null)
221222
{
222223
var projects = new List<ParallelizableTestModuleGroupWithSequentialInnerModules>();
223224
ProjectInstance projectInstance = EvaluateProject(projectCollection, evaluationContext, projectFilePath, null);
@@ -229,7 +230,7 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
229230

230231
if (!string.IsNullOrEmpty(targetFramework) || string.IsNullOrEmpty(targetFrameworks))
231232
{
232-
if (GetModuleFromProject(projectInstance, buildOptions) is { } module)
233+
if (GetModuleFromProject(projectInstance, buildOptions, telemetryCentralLogger) is { } module)
233234
{
234235
projects.Add(new ParallelizableTestModuleGroupWithSequentialInnerModules(module));
235236
}
@@ -257,7 +258,7 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
257258
projectInstance = EvaluateProject(projectCollection, evaluationContext, projectFilePath, framework);
258259
Logger.LogTrace($"Loaded inner project '{Path.GetFileName(projectFilePath)}' has '{ProjectProperties.IsTestingPlatformApplication}' = '{projectInstance.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication)}' (TFM: '{framework}').");
259260

260-
if (GetModuleFromProject(projectInstance, buildOptions) is { } module)
261+
if (GetModuleFromProject(projectInstance, buildOptions, telemetryCentralLogger) is { } module)
261262
{
262263
projects.Add(new ParallelizableTestModuleGroupWithSequentialInnerModules(module));
263264
}
@@ -271,7 +272,7 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
271272
projectInstance = EvaluateProject(projectCollection, evaluationContext, projectFilePath, framework);
272273
Logger.LogTrace($"Loaded inner project '{Path.GetFileName(projectFilePath)}' has '{ProjectProperties.IsTestingPlatformApplication}' = '{projectInstance.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication)}' (TFM: '{framework}').");
273274

274-
if (GetModuleFromProject(projectInstance, buildOptions) is { } module)
275+
if (GetModuleFromProject(projectInstance, buildOptions, telemetryCentralLogger) is { } module)
275276
{
276277
innerModules ??= new List<TestModule>();
277278
innerModules.Add(module);
@@ -288,7 +289,7 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
288289
return projects;
289290
}
290291

291-
private static TestModule? GetModuleFromProject(ProjectInstance project, BuildOptions buildOptions)
292+
private static TestModule? GetModuleFromProject(ProjectInstance project, BuildOptions buildOptions, ILogger? telemetryCentralLogger = null)
292293
{
293294
_ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestProject), out bool isTestProject);
294295
_ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication), out bool isTestingPlatformApplication);
@@ -306,7 +307,7 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
306307
RunProperties runProperties;
307308
if (isTestingPlatformApplication)
308309
{
309-
runProperties = GetRunProperties(project);
310+
runProperties = GetRunProperties(project, telemetryCentralLogger);
310311

311312
// dotnet run throws the same if RunCommand is null or empty.
312313
// In dotnet test, we are additionally checking that RunCommand is not dll.
@@ -346,15 +347,15 @@ public static IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModule
346347

347348
return new TestModule(runProperties, PathUtility.FixFilePath(projectFullPath), targetFramework, isTestingPlatformApplication, launchSettings, project.GetPropertyValue(ProjectProperties.TargetPath), rootVariableName);
348349

349-
static RunProperties GetRunProperties(ProjectInstance project)
350+
static RunProperties GetRunProperties(ProjectInstance project, ILogger? telemetryCentralLogger)
350351
{
351352
// Build API cannot be called in parallel, even if the projects are different.
352353
// Otherwise, BuildManager in MSBuild will fail:
353354
// System.InvalidOperationException: The operation cannot be completed because a build is already in progress.
354355
// NOTE: BuildManager is singleton.
355356
lock (s_buildLock)
356357
{
357-
if (!project.BuildWithTelemetry(s_computeRunArgumentsTarget))
358+
if (!project.BuildWithTelemetry(s_computeRunArgumentsTarget, telemetryCentralLogger: telemetryCentralLogger))
358359
{
359360
throw new GracefulException(CliCommandStrings.RunCommandEvaluationExceptionBuildFailed, s_computeRunArgumentsTarget[0]);
360361
}

0 commit comments

Comments
 (0)