From d50700eca0acad5010c570628505730f7f685f4c Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 8 Jun 2021 14:40:07 +0200 Subject: [PATCH 01/32] WIP --- build/_build/Build.Steps.cs | 68 +++++++++----- build/_build/Build.cs | 3 + .../CustomTestFramework.cs | 22 +++++ ....Trace.ClrProfiler.IntegrationTests.csproj | 5 + .../EnvironmentHelper.cs | 92 ++++++++++--------- 5 files changed, 123 insertions(+), 67 deletions(-) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 52c479998e1f..6568dcc49d1d 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -57,32 +57,32 @@ partial class Build IEnumerable ArchitecturesForPlatform => Equals(Platform, MSBuildTargetPlatform.x64) - ? new[] {MSBuildTargetPlatform.x64, MSBuildTargetPlatform.x86} - : new[] {MSBuildTargetPlatform.x86}; + ? new[] { MSBuildTargetPlatform.x64, MSBuildTargetPlatform.x86 } + : new[] { MSBuildTargetPlatform.x86 }; bool IsArm64 => RuntimeInformation.ProcessArchitecture == Architecture.Arm64; string LinuxArchitectureIdentifier => IsArm64 ? "arm64" : Platform.ToString(); - IEnumerable LinuxPackageTypes => IsAlpine ? new[] {"tar"} : new[] {"deb", "rpm", "tar"}; + IEnumerable LinuxPackageTypes => IsAlpine ? new[] { "tar" } : new[] { "deb", "rpm", "tar" }; - IEnumerable ProjectsToPack => new [] + IEnumerable ProjectsToPack => new[] { Solution.GetProject(Projects.DatadogTrace), Solution.GetProject(Projects.DatadogTraceOpenTracing), }; - Project[] ParallelIntegrationTests => new [] + Project[] ParallelIntegrationTests => new[] { Solution.GetProject(Projects.TraceIntegrationTests), Solution.GetProject(Projects.OpenTracingIntegrationTests), }; - Project[] ClrProfilerIntegrationTests => new [] + Project[] ClrProfilerIntegrationTests => new[] { Solution.GetProject(Projects.ClrProfilerIntegrationTests) }; - readonly IEnumerable TargetFrameworks = new [] + readonly IEnumerable TargetFrameworks = new[] { TargetFramework.NET45, TargetFramework.NET461, @@ -439,7 +439,7 @@ partial class Build foreach (var packageType in LinuxPackageTypes) { - var args = new [] + var args = new[] { "-f", "-s dir", @@ -562,8 +562,8 @@ partial class Build Target CompileDependencyLibs => _ => _ .Unlisted() - .After(Restore) - .After(CompileManagedSrc) + .DependsOn(Restore) + .DependsOn(CompileManagedSrc) .Executes(() => { // Always AnyCPU @@ -623,18 +623,18 @@ partial class Build && !x.Contains("StackExchange.Redis.AssemblyConflict.LegacyProject") && !x.Contains("dependency-libs")); - // Allow restore here, otherwise things go wonky with runtime identifiers - // in some target frameworks. No, I don't know why - DotNetBuild(x => x - // .EnableNoRestore() - .EnableNoDependencies() - .SetConfiguration(BuildConfiguration) - .SetTargetPlatform(Platform) - .SetNoWarnDotNetCore3() - .When(!string.IsNullOrEmpty(NugetPackageDirectory), o => - o.SetPackageDirectory(NugetPackageDirectory)) - .CombineWith(regressionLibs, (x, project) => x - .SetProjectFile(project))); + // Allow restore here, otherwise things go wonky with runtime identifiers + // in some target frameworks. No, I don't know why + DotNetBuild(x => x + // .EnableNoRestore() + .EnableNoDependencies() + .SetConfiguration(BuildConfiguration) + .SetTargetPlatform(Platform) + .SetNoWarnDotNetCore3() + .When(!string.IsNullOrEmpty(NugetPackageDirectory), o => + o.SetPackageDirectory(NugetPackageDirectory)) + .CombineWith(regressionLibs, (x, project) => x + .SetProjectFile(project))); }); Target CompileFrameworkReproductions => _ => _ @@ -757,9 +757,10 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .SetDotnetPath(Platform) .SetConfiguration(BuildConfiguration) .SetTargetPlatform(Platform) - .EnableNoRestore() + .EnableNoRestore() .EnableNoBuild() .When(!string.IsNullOrEmpty(Filter), c => c.SetFilter(Filter)) + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(ParallelIntegrationTests, (s, project) => s .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project)), degreeOfParallelism: 4); @@ -939,7 +940,7 @@ var name when multiApiProjects.Contains(name) => false, { // Build and restore for all versions // Annoyingly this rebuilds everything again and again. - var targets = new [] { "RestoreSamplesForPackageVersionsOnly", "RestoreAndBuildSamplesForPackageVersionsOnly" }; + var targets = new[] { "RestoreSamplesForPackageVersionsOnly", "RestoreAndBuildSamplesForPackageVersionsOnly" }; // /nowarn:NU1701 - Package 'x' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.1'. DotNetMSBuild(x => x @@ -1079,6 +1080,23 @@ private void MoveLogsToBuildData() } } + private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) + { + // if (settings.Framework != TargetFramework.NETCOREAPP3_1) + // { + // return settings; + // } + + // var profilerLibFolder = Solution.GetProject(Projects.ClrProfilerIntegrationTests).Directory / "bin" / BuildConfiguration / TargetFramework.NETCOREAPP3_1 / "profiler-lib" / TargetFramework.NETCOREAPP3_1; + + return settings.SetDataCollector("XPlat Code Coverage") + .SetProcessArgumentConfigurator( + args => + args.Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") + // .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.IncludeDirectory={0}", profilerLibFolder) + .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*")); + } + protected override void OnTargetStart(string target) { if (PrintDriveSpace) @@ -1092,7 +1110,7 @@ protected override void OnTargetStart(string target) static string PrettyPrint(long bytes) { - var power = Math.Min((int) Math.Log(bytes, 1000), 4); + var power = Math.Min((int)Math.Log(bytes, 1000), 4); var normalised = bytes / Math.Pow(1000, power); return power switch { diff --git a/build/_build/Build.cs b/build/_build/Build.cs index d511c7c591be..c2f487cb0c54 100644 --- a/build/_build/Build.cs +++ b/build/_build/Build.cs @@ -59,6 +59,9 @@ partial class Build : NukeBuild [Parameter("Override the default test filters for integration tests. (Optional)")] readonly string Filter; + [Parameter("Enables code coverage")] + readonly bool CodeCoverage; + Target Info => _ => _ .Description("Describes the current configuration") .Before(Clean, Restore, BuildTracerHome) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 18b0492cf5dc..60bde0c4a95e 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -5,10 +5,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Datadog.Trace.TestHelpers; using Xunit; using Xunit.Abstractions; using Xunit.Sdk; @@ -22,6 +24,26 @@ public class CustomTestFramework : XunitTestFramework public CustomTestFramework(IMessageSink messageSink) : base(messageSink) { +#if NETCOREAPP3_1 + + var paths = EnvironmentHelper.GetProfilerPathCandidates(null).ToArray(); + + foreach (var path in paths) + { + var baseDirectory = Path.GetDirectoryName(path); + var finalDirectory = Path.Combine(baseDirectory, "netcoreapp3.1"); + + if (Directory.Exists(finalDirectory)) + { + var file = typeof(Datadog.Trace.ClrProfiler.Instrumentation).Assembly.Location; + File.Copy(file, Path.Combine(finalDirectory, Path.GetFileName(file)), true); + return; + } + } + + throw new DirectoryNotFoundException("Could not find the netcoreapp3.1 folder. Tried: " + string.Join("; ", paths)); + +#endif } protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj index f248a73bde70..d0905d6ea7f8 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj @@ -25,6 +25,11 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs index 610c1e16124a..b03c48b888d5 100644 --- a/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs +++ b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.IO; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -85,6 +86,41 @@ public static bool IsCoreClr() return RuntimeFrameworkDescription.Contains("core") || IsNet5(); } + public static string GetRuntimeIdentifier() + { + return IsCoreClr() + ? string.Empty + : $"{EnvironmentTools.GetOS()}-{EnvironmentTools.GetPlatform()}"; + } + + public static string GetSolutionDirectory() + { + return EnvironmentTools.GetSolutionDirectory(); + } + + public static IEnumerable GetProfilerPathCandidates(string sampleApplicationOutputDirectory) + { + string extension = EnvironmentTools.GetOS() switch + { + "win" => "dll", + "linux" => "so", + "osx" => "dylib", + _ => throw new PlatformNotSupportedException() + }; + + string fileName = $"Datadog.Trace.ClrProfiler.Native.{extension}"; + + var relativePath = Path.Combine("profiler-lib", fileName); + + if (sampleApplicationOutputDirectory != null) + { + yield return Path.Combine(sampleApplicationOutputDirectory, relativePath); + } + + yield return Path.Combine(GetExecutingProjectBin(), relativePath); + yield return Path.Combine(GetProfilerProjectBin(), fileName); + } + public static void ClearProfilerEnvironmentVariables() { var environmentVariables = new[] @@ -241,52 +277,24 @@ public string GetProfilerPath() { if (_profilerFileLocation == null) { - string extension = EnvironmentTools.GetOS() switch - { - "win" => "dll", - "linux" => "so", - "osx" => "dylib", - _ => throw new PlatformNotSupportedException() - }; - - string fileName = $"Datadog.Trace.ClrProfiler.Native.{extension}"; - - var directory = GetSampleApplicationOutputDirectory(); - - var relativePath = Path.Combine( - "profiler-lib", - fileName); - - _profilerFileLocation = Path.Combine( - directory, - relativePath); - - // TODO: get rid of the fallback options when we have a consistent convention + int attempt = 1; - if (!File.Exists(_profilerFileLocation)) - { - _output?.WriteLine($"Attempt 1: Unable to find profiler at {_profilerFileLocation}."); - // Let's try the executing directory, as dotnet publish ignores the Copy attributes we currently use - _profilerFileLocation = Path.Combine( - GetExecutingProjectBin(), - relativePath); - } + var paths = GetProfilerPathCandidates(GetSampleApplicationOutputDirectory()).ToArray(); - if (!File.Exists(_profilerFileLocation)) + foreach (var candidate in paths) { - _output?.WriteLine($"Attempt 2: Unable to find profiler at {_profilerFileLocation}."); - // One last attempt at the actual native project directory - _profilerFileLocation = Path.Combine( - GetProfilerProjectBin(), - fileName); - } + if (File.Exists(candidate)) + { + _profilerFileLocation = candidate; + _output?.WriteLine($"Found profiler at {_profilerFileLocation}."); + return candidate; + } - if (!File.Exists(_profilerFileLocation)) - { - throw new Exception($"Attempt 3: Unable to find profiler at {_profilerFileLocation}"); + _output?.WriteLine($"Attempt {attempt}: Unable to find profiler at {candidate}."); + attempt++; } - _output?.WriteLine($"Found profiler at {_profilerFileLocation}."); + throw new Exception($"Unable to find profiler in any of the paths: {string.Join("; ", _profilerFileLocation)}"); } return _profilerFileLocation; @@ -443,7 +451,7 @@ public string GetTargetFramework() return $"net{_major}{_minor}{_patch ?? string.Empty}"; } - private string GetProfilerProjectBin() + private static string GetProfilerProjectBin() { return Path.Combine( EnvironmentTools.GetSolutionDirectory(), @@ -454,7 +462,7 @@ private string GetProfilerProjectBin() EnvironmentTools.GetPlatform().ToLower()); } - private string GetExecutingProjectBin() + private static string GetExecutingProjectBin() { return Path.GetDirectoryName(ExecutingAssembly.Location); } From f43f39372f3c8a0160551515b7a8825fa32df5fb Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 11 Jun 2021 11:54:52 +0200 Subject: [PATCH 02/32] Add code coverage to windows integration tests --- .azure-pipelines/ultimate-pipeline.yml | 39 +++++++++++++++++++++++++- build/_build/Build.Steps.cs | 7 +++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index b9c0a3c4745b..ad6319c743c6 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -350,7 +350,7 @@ stages: displayName: 'Start CosmosDB Emulator' workingDirectory: $(Pipeline.Workspace) - - script: build.cmd BuildAndRunWindowsIntegrationTests --PrintDriveSpace + - script: build.cmd BuildAndRunWindowsIntegrationTests --PrintDriveSpace --code-coverage displayName: Run integration tests - task: PublishTestResults@2 @@ -359,6 +359,11 @@ stages: testResultsFormat: VSTest testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true - stage: integration_tests_windows_iis condition: and(succeeded(), eq(variables['isScheduledBuild'], 'False')) @@ -424,6 +429,11 @@ stages: testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true + - task: DockerCompose@0 displayName: docker-compose stop services inputs: @@ -932,3 +942,30 @@ stages: displayName: Crank env: DD_SERVICE: dd-trace-dotnet +- stage: coverage + condition: and(succeeded(), eq(variables['benchmarksOnly'], 'False')) + dependsOn: [integration_tests_windows, integration_tests_windows_iis] + jobs: + - job: Windows + timeoutInMinutes: 30 + + steps: + - template: steps/install-dotnet-sdks.yml + - template: steps/restore-working-directory.yml + + - task: DownloadPipelineArtifact@2 + inputs: + patterns: '**/coverage.cobertura.xml' + path: $(Build.SourcesDirectory)/cover + + - task: reportgenerator@4 + inputs: + reports: '$(Build.SourcesDirectory)\cover\*\*\coverage.cobertura.xml' + targetdir: '$(Build.SourcesDirectory)\coveragereport' + sourcedirs: '$(Build.SourcesDirectory)' + reporttypes: 'Cobertura' + + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: 'Cobertura' + summaryFileLocation: '$(Build.SourcesDirectory)/coveragereport/Cobertura.xml' \ No newline at end of file diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 6568dcc49d1d..62a65a3fcb21 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -745,6 +745,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .After(CompileIntegrationTests) .After(CompileSamples) .After(CompileFrameworkReproductions) + .After(BuildWindowsIntegrationTests) .Requires(() => IsWin) .Executes(() => { @@ -775,6 +776,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .EnableNoRestore() .EnableNoBuild() .SetFilter(Filter ?? "(RunOnWindows=True|Category=Smoke)&LoadFromGAC!=True&IIS!=True") + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(ClrProfilerIntegrationTests, (s, project) => s .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project))); @@ -805,6 +807,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .EnableNoRestore() .EnableNoBuild() .SetFilter(Filter ?? "(RunOnWindows=True|Category=Smoke)&LoadFromGAC=True") + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(ClrProfilerIntegrationTests, (s, project) => s .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project))); @@ -1092,8 +1095,8 @@ private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) return settings.SetDataCollector("XPlat Code Coverage") .SetProcessArgumentConfigurator( args => - args.Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") - // .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.IncludeDirectory={0}", profilerLibFolder) + args.Add("--") + .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*")); } From 4b645abce88a21e5c848f05625ea0ca87f8f0311 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 11 Jun 2021 13:20:24 +0200 Subject: [PATCH 03/32] Change path and dump directory structure --- .azure-pipelines/ultimate-pipeline.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index ad6319c743c6..3142b064bcd1 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -958,9 +958,13 @@ stages: patterns: '**/coverage.cobertura.xml' path: $(Build.SourcesDirectory)/cover + - task: CmdLine@2 + inputs: + script: 'tree $(Build.SourcesDirectory)\cover /F /A' + - task: reportgenerator@4 inputs: - reports: '$(Build.SourcesDirectory)\cover\*\*\coverage.cobertura.xml' + reports: '$(Build.SourcesDirectory)\cover\**\coverage.cobertura.xml' targetdir: '$(Build.SourcesDirectory)\coveragereport' sourcedirs: '$(Build.SourcesDirectory)' reporttypes: 'Cobertura' From afff6511c385bff296a8ee2ac46d0e23df6e4340 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 11 Jun 2021 14:38:53 +0200 Subject: [PATCH 04/32] Change pool --- .azure-pipelines/ultimate-pipeline.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 3142b064bcd1..cb28ffd78354 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -949,6 +949,9 @@ stages: - job: Windows timeoutInMinutes: 30 + pool: + vmImage: windows-2019 + steps: - template: steps/install-dotnet-sdks.yml - template: steps/restore-working-directory.yml From 1193769db37be5f9e0533f8b5aded9143b6b9f49 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 11 Jun 2021 17:20:55 +0200 Subject: [PATCH 05/32] Enable coverage on Linux --- .azure-pipelines/ultimate-pipeline.yml | 5 +++++ build/_build/Build.Steps.cs | 9 ++------- docker-compose.yml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index cb28ffd78354..5df5ad7712db 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -612,6 +612,11 @@ stages: testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true + - stage: benchmarks dependsOn: build_windows jobs: diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 62a65a3fcb21..99a2dd073dac 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -1035,6 +1035,7 @@ var name when multiApiProjects.Contains(name) => false, .SetFilter(filter) .When(TestAllPackageVersions, o => o .SetProcessEnvironmentVariable("TestAllPackageVersions", "true")) + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(ParallelIntegrationTests, (s, project) => s .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project)), @@ -1051,6 +1052,7 @@ var name when multiApiProjects.Contains(name) => false, .SetFilter(filter) .When(TestAllPackageVersions, o => o .SetProcessEnvironmentVariable("TestAllPackageVersions", "true")) + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(ClrProfilerIntegrationTests, (s, project) => s .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project)) @@ -1085,13 +1087,6 @@ private void MoveLogsToBuildData() private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) { - // if (settings.Framework != TargetFramework.NETCOREAPP3_1) - // { - // return settings; - // } - - // var profilerLibFolder = Solution.GetProject(Projects.ClrProfilerIntegrationTests).Directory / "bin" / BuildConfiguration / TargetFramework.NETCOREAPP3_1 / "profiler-lib" / TargetFramework.NETCOREAPP3_1; - return settings.SetDataCollector("XPlat Code Coverage") .SetProcessArgumentConfigurator( args => diff --git a/docker-compose.yml b/docker-compose.yml index 04ba378c10f0..952e361e34aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -217,7 +217,7 @@ services: args: - DOTNETSDK_VERSION=${dotnetCoreSdk5Version:-5.0.103} image: dd-trace-dotnet/${baseImage:-debian}-tester - command: dotnet /build/bin/Debug/_build.dll RunLinuxIntegrationTests --framework ${framework:-netcoreapp3.1} + command: dotnet /build/bin/Debug/_build.dll RunLinuxIntegrationTests --framework ${framework:-netcoreapp3.1} --code-coverage volumes: - ./:/project environment: From 5c59395d4ed11664bb444fd2cce85805e51c11db Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 14 Jun 2021 15:41:56 +0200 Subject: [PATCH 06/32] Add collector to more projects --- .../Datadog.Trace.ClrProfiler.Managed.Tests.csproj | 5 +++++ .../Datadog.Trace.IntegrationTests.csproj | 5 +++++ .../Datadog.Trace.OpenTracing.IntegrationTests.csproj | 5 +++++ .../Datadog.Trace.OpenTracing.Tests.csproj | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj index 536ef4a187f4..25dd7cb13edc 100644 --- a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj @@ -4,6 +4,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj index 83c2274e425c..0e49e379ca44 100644 --- a/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj +++ b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj @@ -19,6 +19,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj index 728c1c43c8ae..1abb0b5ccbd1 100644 --- a/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj +++ b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj @@ -4,6 +4,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj index 3bda276b409d..8cdfb45c8493 100644 --- a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj +++ b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj @@ -4,6 +4,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From fa1f198b9e960fc4f778970a89d5e136f90899cd Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 14 Jun 2021 17:44:07 +0200 Subject: [PATCH 07/32] Disable coverlet in OpenTracing integration tests --- .../Datadog.Trace.OpenTracing.IntegrationTests.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj index 1abb0b5ccbd1..728c1c43c8ae 100644 --- a/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj +++ b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj @@ -4,11 +4,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - From 852078c6fad9e4783333a591fce620a25b3dbc24 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 15 Jun 2021 12:31:37 +0200 Subject: [PATCH 08/32] Remove from Datadog.Trace.OpenTracing.Tests --- .../Datadog.Trace.OpenTracing.Tests.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj index 8cdfb45c8493..54c1c547e439 100644 --- a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj +++ b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj @@ -5,10 +5,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - From 66e6c9f6468c31666ba8ec433bd558d546a963e9 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 15 Jun 2021 15:14:59 +0200 Subject: [PATCH 09/32] Improvements --- .azure-pipelines/ultimate-pipeline.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 5df5ad7712db..453c6dd74a57 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -958,7 +958,6 @@ stages: vmImage: windows-2019 steps: - - template: steps/install-dotnet-sdks.yml - template: steps/restore-working-directory.yml - task: DownloadPipelineArtifact@2 @@ -968,16 +967,17 @@ stages: - task: CmdLine@2 inputs: - script: 'tree $(Build.SourcesDirectory)\cover /F /A' + script: 'tree $(Build.SourcesDirectory) /F /A' - task: reportgenerator@4 inputs: reports: '$(Build.SourcesDirectory)\cover\**\coverage.cobertura.xml' targetdir: '$(Build.SourcesDirectory)\coveragereport' - sourcedirs: '$(Build.SourcesDirectory)' + sourcedirs: '$(Build.SourcesDirectory);..' reporttypes: 'Cobertura' - task: PublishCodeCoverageResults@1 inputs: codeCoverageTool: 'Cobertura' - summaryFileLocation: '$(Build.SourcesDirectory)/coveragereport/Cobertura.xml' \ No newline at end of file + summaryFileLocation: '$(Build.SourcesDirectory)/coveragereport/Cobertura.xml' + pathToSources: '$(Build.SourcesDirectory)' \ No newline at end of file From cad11d2029a8a0040ac34e9fa90290045e8aafd2 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 15 Jun 2021 17:41:53 +0200 Subject: [PATCH 10/32] Cleanup --- .azure-pipelines/ultimate-pipeline.yml | 6 +----- build/_build/Build.Steps.cs | 6 +++--- .../Datadog.Trace.OpenTracing.Tests.csproj | 1 - 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 453c6dd74a57..8b04bc277843 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -964,11 +964,7 @@ stages: inputs: patterns: '**/coverage.cobertura.xml' path: $(Build.SourcesDirectory)/cover - - - task: CmdLine@2 - inputs: - script: 'tree $(Build.SourcesDirectory) /F /A' - + - task: reportgenerator@4 inputs: reports: '$(Build.SourcesDirectory)\cover\**\coverage.cobertura.xml' diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 99a2dd073dac..bdc24471c640 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -562,8 +562,8 @@ partial class Build Target CompileDependencyLibs => _ => _ .Unlisted() - .DependsOn(Restore) - .DependsOn(CompileManagedSrc) + .After(Restore) + .After(CompileManagedSrc) .Executes(() => { // Always AnyCPU @@ -758,7 +758,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .SetDotnetPath(Platform) .SetConfiguration(BuildConfiguration) .SetTargetPlatform(Platform) - .EnableNoRestore() + .EnableNoRestore() .EnableNoBuild() .When(!string.IsNullOrEmpty(Filter), c => c.SetFilter(Filter)) .When(CodeCoverage, ConfigureCodeCoverage) diff --git a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj index 54c1c547e439..3bda276b409d 100644 --- a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj +++ b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj @@ -4,7 +4,6 @@ - From 7a52cc43b171b052672f986aff39bdefe10ecd39 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 15 Jun 2021 18:00:02 +0200 Subject: [PATCH 11/32] Enable code coverage for unit tests --- .azure-pipelines/ultimate-pipeline.yml | 21 ++++++++++++++++--- build/_build/Build.Steps.cs | 1 + .../Datadog.Trace.DuckTyping.Tests.csproj | 5 +++++ .../Datadog.Trace.Tests.csproj | 5 +++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 8b04bc277843..27fd4e935a2e 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -200,7 +200,7 @@ stages: - template: steps/install-dotnet.yml - template: steps/restore-working-directory.yml - - script: build.cmd BuildAndRunManagedUnitTests + - script: build.cmd BuildAndRunManagedUnitTests --code-coverage displayName: Build and Test - publish: build_data @@ -213,6 +213,11 @@ stages: testResultsFormat: VSTest testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true - job: native steps: @@ -241,7 +246,7 @@ stages: parameters: artifact: build-macos-working-directory - - script: ./build.sh BuildAndRunManagedUnitTests + - script: ./build.sh BuildAndRunManagedUnitTests --code-coverage displayName: Build and Test - publish: build_data @@ -254,6 +259,11 @@ stages: testResultsFormat: VSTest testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true - stage: unit_tests_linux condition: and(succeeded(), eq(variables['isScheduledBuild'], 'False')) @@ -278,7 +288,7 @@ stages: parameters: build: true baseImage: $(baseImage) - command: "BuildAndRunManagedUnitTests" + command: "BuildAndRunManagedUnitTests --code-coverage" - publish: build_data artifact: profiler-logs_unit_tests_linux_$(Agent.JobName)_$(System.JobAttempt) @@ -290,6 +300,11 @@ stages: testResultsFormat: VSTest testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: 'build_data/results/' + continueOnError: true - stage: unit_tests_arm64 condition: and(succeeded(), eq(variables['isScheduledBuild'], 'False')) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index bdc24471c640..c158f962ffca 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -522,6 +522,7 @@ partial class Build .SetTargetPlatformAnyCPU() .SetDDEnvironmentVariables("dd-tracer-dotnet") .EnableMemoryDumps() + .When(CodeCoverage, ConfigureCodeCoverage) .CombineWith(testProjects, (x, project) => x .EnableTrxLogOutput(GetResultsDirectory(project)) .SetProjectFile(project))); diff --git a/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj b/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj index f654a698bbf1..083c9ef62623 100644 --- a/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj +++ b/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj @@ -8,6 +8,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + $(DefineConstants);INTERFACE_DEFAULTS diff --git a/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj index 8e1f86d6eb54..97c7dd1146b9 100644 --- a/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj +++ b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj @@ -15,6 +15,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 399e664a2d17b4030cb2e4877b5a3783fc4e6e6a Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 16 Jun 2021 11:49:26 +0200 Subject: [PATCH 12/32] Try fix strong naming error --- build/_build/Build.Steps.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index c158f962ffca..ddb91fda80f1 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -1092,6 +1092,7 @@ private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) .SetProcessArgumentConfigurator( args => args.Add("--") + .Add("RunConfiguration.DisableAppDomain=true") // https://github.com/coverlet-coverage/coverlet/issues/347 .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*")); } From 05d4857bcf730d6e347171d66a66c434d4f7f2b9 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 16 Jun 2021 14:40:08 +0200 Subject: [PATCH 13/32] Remove duplicate publish steps --- .azure-pipelines/ultimate-pipeline.yml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 27fd4e935a2e..2668eeb07196 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -214,11 +214,6 @@ stages: testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() - - task: PublishPipelineArtifact@1 - inputs: - targetPath: 'build_data/results/' - continueOnError: true - - job: native steps: - template: steps/install-dotnet.yml @@ -260,10 +255,7 @@ stages: testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() - - task: PublishPipelineArtifact@1 - inputs: - targetPath: 'build_data/results/' - continueOnError: true + - stage: unit_tests_linux condition: and(succeeded(), eq(variables['isScheduledBuild'], 'False')) @@ -627,11 +619,6 @@ stages: testResultsFiles: build_data/results/**/*.trx condition: succeededOrFailed() - - task: PublishPipelineArtifact@1 - inputs: - targetPath: 'build_data/results/' - continueOnError: true - - stage: benchmarks dependsOn: build_windows jobs: From d457bdf475ce8cfa826848cdf833cbe6e01b4dbe Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 16 Jun 2021 18:18:54 +0200 Subject: [PATCH 14/32] Extend coverage to all supported TFMs --- .../CustomTestFramework.cs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 60bde0c4a95e..184412633991 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -24,14 +24,14 @@ public class CustomTestFramework : XunitTestFramework public CustomTestFramework(IMessageSink messageSink) : base(messageSink) { -#if NETCOREAPP3_1 + var targetFrameworkDirectory = GetTargetFrameworkDirectory(); var paths = EnvironmentHelper.GetProfilerPathCandidates(null).ToArray(); foreach (var path in paths) { var baseDirectory = Path.GetDirectoryName(path); - var finalDirectory = Path.Combine(baseDirectory, "netcoreapp3.1"); + var finalDirectory = Path.Combine(baseDirectory, targetFrameworkDirectory); if (Directory.Exists(finalDirectory)) { @@ -41,9 +41,7 @@ public CustomTestFramework(IMessageSink messageSink) } } - throw new DirectoryNotFoundException("Could not find the netcoreapp3.1 folder. Tried: " + string.Join("; ", paths)); - -#endif + throw new DirectoryNotFoundException($"Could not find the {targetFrameworkDirectory} folder. Tried: {string.Join("; ", paths)}"); } protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) @@ -51,6 +49,21 @@ protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyNa return new CustomExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink); } + private static string GetTargetFrameworkDirectory() + { +#if NETCOREAPP3_1_OR_GREATER + return "netcoreapp3.1"; +#elif NETCOREAPP || NETSTANDARD + return "netstandard2.0"; +#elif NET461_OR_GREATER + return "net461"; +#elif NET45_OR_GREATER + return "net45"; +#else + throw new InvalidOperationException("Unexpected TFM"); +#endif + } + private class CustomExecutor : XunitTestFrameworkExecutor { public CustomExecutor(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink) From c7b85d4dcc1362d9d224755d2abb39e7fc5402f0 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Thu, 17 Jun 2021 10:57:14 +0200 Subject: [PATCH 15/32] Add missing dependencies to the coverage job --- .azure-pipelines/ultimate-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 2668eeb07196..54b97f1dbebf 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -951,7 +951,7 @@ stages: DD_SERVICE: dd-trace-dotnet - stage: coverage condition: and(succeeded(), eq(variables['benchmarksOnly'], 'False')) - dependsOn: [integration_tests_windows, integration_tests_windows_iis] + dependsOn: [integration_tests_windows, integration_tests_windows_iis, integration_tests_linux, unit_tests_linux, unit_tests_macos, unit_tests_windows] jobs: - job: Windows timeoutInMinutes: 30 From a241ab5bb856fe88919d86a3152f4d8d87775cf9 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 18 Jun 2021 13:14:55 +0200 Subject: [PATCH 16/32] Ignore auto properties --- build/_build/Build.Steps.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index ddb91fda80f1..058bc757e0bc 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -1093,6 +1093,7 @@ private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) args => args.Add("--") .Add("RunConfiguration.DisableAppDomain=true") // https://github.com/coverlet-coverage/coverlet/issues/347 + .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.SkipAutoProps=true") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*")); } From d5c078229d5d718f292739951783fe48b4b1fb13 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Fri, 18 Jun 2021 15:45:11 +0200 Subject: [PATCH 17/32] Exclude unrelated assemblies --- build/_build/Build.Steps.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 058bc757e0bc..e7de26197b43 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -1095,7 +1095,8 @@ private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) .Add("RunConfiguration.DisableAppDomain=true") // https://github.com/coverlet-coverage/coverlet/issues/347 .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.SkipAutoProps=true") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") - .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*")); + .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*,") + .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Include=\"[Datadog.Trace.ClrProfiler.*]*,[Datadog.Trace]*,[Datadog.Trace.AspNet]*\"")); } protected override void OnTargetStart(string target) From 09b2cfe11caf8cbf2116fd76111833db3476694d Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 21 Jun 2021 10:48:04 +0200 Subject: [PATCH 18/32] Add diagnostic messages --- .../CustomTestFramework.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 184412633991..964ccca0d40f 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -36,12 +36,20 @@ public CustomTestFramework(IMessageSink messageSink) if (Directory.Exists(finalDirectory)) { var file = typeof(Datadog.Trace.ClrProfiler.Instrumentation).Assembly.Location; - File.Copy(file, Path.Combine(finalDirectory, Path.GetFileName(file)), true); + var destination = Path.Combine(finalDirectory, Path.GetFileName(file)); + File.Copy(file, destination, true); + + messageSink.OnMessage(new DiagnosticMessage("Replaced {0} with {1} to setup code coverage", file, destination)); + return; } } - throw new DirectoryNotFoundException($"Could not find the {targetFrameworkDirectory} folder. Tried: {string.Join("; ", paths)}"); + var message = $"Could not find the {targetFrameworkDirectory} folder. Tried: {string.Join("; ", paths)}"; + + messageSink.OnMessage(new DiagnosticMessage(message)); + + throw new DirectoryNotFoundException(message); } protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) From b6e1dc50a5ce1ae4bd2816342901e08b8547e309 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 21 Jun 2021 14:52:48 +0200 Subject: [PATCH 19/32] Replace TFM exception with compile-time error --- .../CustomTestFramework.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 964ccca0d40f..4584003c43cf 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -68,7 +68,7 @@ private static string GetTargetFrameworkDirectory() #elif NET45_OR_GREATER return "net45"; #else - throw new InvalidOperationException("Unexpected TFM"); +#error Unexpected TFM #endif } From 7e18dc12c4b68012a5a9ef34a90fba59b6752a3c Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 21 Jun 2021 15:54:23 +0200 Subject: [PATCH 20/32] Make TFM conditions more robust --- .../CustomTestFramework.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 4584003c43cf..804619b64a07 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -59,13 +59,15 @@ protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyNa private static string GetTargetFrameworkDirectory() { -#if NETCOREAPP3_1_OR_GREATER + // The conditions looks weird, but it seems like _OR_GREATER is not supported yet in all environments + // We can trim all the additional conditions when this is fixed +#if NETCOREAPP3_1_OR_GREATER || NETCOREAPP3_1 || NET50 return "netcoreapp3.1"; #elif NETCOREAPP || NETSTANDARD return "netstandard2.0"; -#elif NET461_OR_GREATER +#elif NET461_OR_GREATER || NET461 || NET47 || NET471 || NET472 || NET48 return "net461"; -#elif NET45_OR_GREATER +#elif NET45_OR_GREATER || NET45 || NET451 || NET452 || NET46 return "net45"; #else #error Unexpected TFM From 8b8a1723d81d205337c31ad8abfd4edf4ebb2be3 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 22 Jun 2021 10:52:35 +0200 Subject: [PATCH 21/32] Remove references to ClrProfiler in Samples --- .../integrations/Samples.GraphQL/Program.cs | 20 +++++++++++++++++-- .../Samples.GraphQL/Samples.GraphQL.csproj | 4 ---- .../integrations/Samples.MongoDB/Program.cs | 20 +++++++++++++++++-- .../Samples.MongoDB/Samples.MongoDB.csproj | 1 - .../ExpenseItDemo/ExpenseItDemo.csproj | 10 ---------- .../Samples.AspNetCoreSimpleController.csproj | 4 ---- 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/test/test-applications/integrations/Samples.GraphQL/Program.cs b/test/test-applications/integrations/Samples.GraphQL/Program.cs index db0ede4327b9..e8d565d65ea5 100644 --- a/test/test-applications/integrations/Samples.GraphQL/Program.cs +++ b/test/test-applications/integrations/Samples.GraphQL/Program.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Datadog.Trace.ClrProfiler; using System; using System.Linq; using System.Collections.Generic; @@ -29,7 +28,8 @@ public static void Main(string[] args) .Build(); var logger = host.Services.GetRequiredService>(); - logger.LogInformation($"Instrumentation.ProfilerAttached = {Instrumentation.ProfilerAttached}"); + + logger.LogInformation($"Instrumentation.ProfilerAttached = {IsProfilerAttached()}"); var prefixes = new[] { "COR_", "CORECLR_", "DD_", "DATADOG_" }; var envVars = from envVar in Environment.GetEnvironmentVariables().Cast() @@ -47,5 +47,21 @@ orderby key host.Run(); } + + private static bool IsProfilerAttached() + { + var instrumentationType = Type.GetType("Datadog.Trace.ClrProfiler.Instrumentation", throwOnError: false); + + if (instrumentationType == null) + { + return false; + } + + var property = instrumentationType.GetProperty("ProfilerAttached"); + + var isAttached = property?.GetValue(null) as bool?; + + return isAttached ?? false; + } } } diff --git a/test/test-applications/integrations/Samples.GraphQL/Samples.GraphQL.csproj b/test/test-applications/integrations/Samples.GraphQL/Samples.GraphQL.csproj index 4609595b6728..19675be3cd2b 100644 --- a/test/test-applications/integrations/Samples.GraphQL/Samples.GraphQL.csproj +++ b/test/test-applications/integrations/Samples.GraphQL/Samples.GraphQL.csproj @@ -5,10 +5,6 @@ net461;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1;net5.0 - - - - diff --git a/test/test-applications/integrations/Samples.MongoDB/Program.cs b/test/test-applications/integrations/Samples.MongoDB/Program.cs index d5205f1736cf..cce12d49b845 100644 --- a/test/test-applications/integrations/Samples.MongoDB/Program.cs +++ b/test/test-applications/integrations/Samples.MongoDB/Program.cs @@ -4,7 +4,6 @@ using System.Threading; using System.Threading.Tasks; using Datadog.Trace; -using Datadog.Trace.ClrProfiler; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.Core.Clusters; @@ -21,7 +20,24 @@ private static string Host() public static void Main(string[] args) { - Console.WriteLine($"Profiler attached: {Instrumentation.ProfilerAttached}"); + bool IsProfilerAttached() + { + var instrumentationType = Type.GetType("Datadog.Trace.ClrProfiler.Instrumentation", throwOnError: false); + + if (instrumentationType == null) + { + return false; + } + + var property = instrumentationType.GetProperty("ProfilerAttached"); + + var isAttached = property?.GetValue(null) as bool?; + + return isAttached ?? false; + } + + + Console.WriteLine($"Profiler attached: {IsProfilerAttached()}"); Console.WriteLine($"Platform: {(Environment.Is64BitProcess ? "x64" : "x32")}"); var newDocument = new BsonDocument diff --git a/test/test-applications/integrations/Samples.MongoDB/Samples.MongoDB.csproj b/test/test-applications/integrations/Samples.MongoDB/Samples.MongoDB.csproj index cc7c0d314427..4d04841b02f7 100644 --- a/test/test-applications/integrations/Samples.MongoDB/Samples.MongoDB.csproj +++ b/test/test-applications/integrations/Samples.MongoDB/Samples.MongoDB.csproj @@ -11,7 +11,6 @@ - diff --git a/test/test-applications/regression/Reproduction.Wpf.ExpenseIt/ExpenseIt/ExpenseItDemo/ExpenseItDemo.csproj b/test/test-applications/regression/Reproduction.Wpf.ExpenseIt/ExpenseIt/ExpenseItDemo/ExpenseItDemo.csproj index 086fd0ec198e..ad33ceb7b626 100644 --- a/test/test-applications/regression/Reproduction.Wpf.ExpenseIt/ExpenseIt/ExpenseItDemo/ExpenseItDemo.csproj +++ b/test/test-applications/regression/Reproduction.Wpf.ExpenseIt/ExpenseIt/ExpenseItDemo/ExpenseItDemo.csproj @@ -128,16 +128,6 @@ - - - {d95d5e26-f32a-481d-a15a-ef7b3b56d2e0} - Datadog.Trace.ClrProfiler.Managed.Core - - - {85f35aaf-d102-4960-8b41-3bd9cbd0e77f} - Datadog.Trace.ClrProfiler.Managed - - diff --git a/test/test-applications/throughput/Samples.AspNetCoreSimpleController/Samples.AspNetCoreSimpleController.csproj b/test/test-applications/throughput/Samples.AspNetCoreSimpleController/Samples.AspNetCoreSimpleController.csproj index 0edc1f7de344..2494cfe38831 100644 --- a/test/test-applications/throughput/Samples.AspNetCoreSimpleController/Samples.AspNetCoreSimpleController.csproj +++ b/test/test-applications/throughput/Samples.AspNetCoreSimpleController/Samples.AspNetCoreSimpleController.csproj @@ -5,8 +5,4 @@ x64;x86;AnyCPU - - - - From a3d7db81f3e5643bd0e2b60db6499b36bc036902 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 22 Jun 2021 16:08:20 +0200 Subject: [PATCH 22/32] Try excluding the profiler from linux samples --- build/_build/Build.Steps.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index e7de26197b43..7a06a733aab1 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -954,6 +954,8 @@ var name when multiApiProjects.Contains(name) => false, .SetProperty("TargetFramework", Framework.ToString()) .SetProperty("ManagedProfilerOutputDirectory", TracerHomeDirectory) .SetProperty("BuildInParallel", "true") + .SetProperty("ExcludeManagedProfiler", "true") + .SetProperty("ExcludeNativeProfiler", "true") .SetProcessArgumentConfigurator(arg => arg.Add("/nowarn:NU1701")) .AddProcessEnvironmentVariable("TestAllPackageVersions", "true") .When(TestAllPackageVersions, o => o.SetProperty("TestAllPackageVersions", "true")) From de8b36be4bb2b3203a8100bd5b55e1527acf06f5 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 22 Jun 2021 17:47:33 +0200 Subject: [PATCH 23/32] Fix diagnostic message --- .../CustomTestFramework.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 804619b64a07..5a09049f0e52 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -39,7 +39,7 @@ public CustomTestFramework(IMessageSink messageSink) var destination = Path.Combine(finalDirectory, Path.GetFileName(file)); File.Copy(file, destination, true); - messageSink.OnMessage(new DiagnosticMessage("Replaced {0} with {1} to setup code coverage", file, destination)); + messageSink.OnMessage(new DiagnosticMessage("Replaced {0} with {1} to setup code coverage", destination, file)); return; } From 47392f6f61044ddb61bc41ca028239777e47c0d5 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 23 Jun 2021 11:25:57 +0200 Subject: [PATCH 24/32] Exclude profiler in more projects --- build/_build/Build.Steps.cs | 4 +++- .../CallTargetNativeTest.csproj | 5 +++++ ...ssageHandler.StackOverflowException.csproj | 4 ++++ .../Program.cs | 19 +++++++++++++++++-- .../Program.cs | 19 +++++++++++++++++-- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 7a06a733aab1..38e5d473d1a2 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -735,7 +735,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .SetProperty("DeployOnBuild", true) .SetProperty("PublishProfile", publishProfile) .SetMaxCpuCount(null) - .CombineWith(aspnetProjects, (c, project ) => c + .CombineWith(aspnetProjects, (c, project) => c .SetTargetPath(project)) ); }); @@ -908,6 +908,8 @@ var name when multiApiProjects.Contains(name) => false, .SetFramework(Framework) // .SetTargetPlatform(Platform) .SetNoWarnDotNetCore3() + .SetProperty("ExcludeManagedProfiler", "true") + .SetProperty("ExcludeNativeProfiler", "true") .SetProperty("ManagedProfilerOutputDirectory", TracerHomeDirectory) .When(TestAllPackageVersions, o => o.SetProperty("TestAllPackageVersions", "true")) .When(!string.IsNullOrEmpty(NugetPackageDirectory), o => o.SetPackageDirectory(NugetPackageDirectory)) diff --git a/test/test-applications/instrumentation/CallTargetNativeTest/CallTargetNativeTest.csproj b/test/test-applications/instrumentation/CallTargetNativeTest/CallTargetNativeTest.csproj index 51e5167f674f..aa503fdfe53f 100644 --- a/test/test-applications/instrumentation/CallTargetNativeTest/CallTargetNativeTest.csproj +++ b/test/test-applications/instrumentation/CallTargetNativeTest/CallTargetNativeTest.csproj @@ -10,4 +10,9 @@ + + + + + diff --git a/test/test-applications/regression/HttpMessageHandler.StackOverflowException/HttpMessageHandler.StackOverflowException.csproj b/test/test-applications/regression/HttpMessageHandler.StackOverflowException/HttpMessageHandler.StackOverflowException.csproj index aa22ab973d2e..a337ff4b0b46 100644 --- a/test/test-applications/regression/HttpMessageHandler.StackOverflowException/HttpMessageHandler.StackOverflowException.csproj +++ b/test/test-applications/regression/HttpMessageHandler.StackOverflowException/HttpMessageHandler.StackOverflowException.csproj @@ -6,4 +6,8 @@ + + + + diff --git a/test/test-applications/regression/HttpMessageHandler.StackOverflowException/Program.cs b/test/test-applications/regression/HttpMessageHandler.StackOverflowException/Program.cs index 27626453e3da..a843ecbb792b 100644 --- a/test/test-applications/regression/HttpMessageHandler.StackOverflowException/Program.cs +++ b/test/test-applications/regression/HttpMessageHandler.StackOverflowException/Program.cs @@ -3,7 +3,6 @@ using System.Threading; using System.Threading.Tasks; using Datadog.Trace; -using Datadog.Trace.ClrProfiler; namespace HttpMessageHandler.StackOverflowException { @@ -13,7 +12,7 @@ private static async Task Main() { try { - Console.WriteLine($"Profiler attached: {Instrumentation.ProfilerAttached}"); + Console.WriteLine($"Profiler attached: {IsProfilerAttached()}"); var baseAddress = new Uri("https://www.example.com/"); var regularHttpClient = new HttpClient { BaseAddress = baseAddress }; @@ -47,6 +46,22 @@ private static async Task Main() return (int)ExitCode.Success; } + + private static bool IsProfilerAttached() + { + var instrumentationType = Type.GetType("Datadog.Trace.ClrProfiler.Instrumentation", throwOnError: false); + + if (instrumentationType == null) + { + return false; + } + + var property = instrumentationType.GetProperty("ProfilerAttached"); + + var isAttached = property?.GetValue(null) as bool?; + + return isAttached ?? false; + } } public class DerivedHandler : HttpClientHandler diff --git a/test/test-applications/regression/StackExchange.Redis.StackOverflowException/Program.cs b/test/test-applications/regression/StackExchange.Redis.StackOverflowException/Program.cs index 29a7de586a79..0af7ff8511f2 100644 --- a/test/test-applications/regression/StackExchange.Redis.StackOverflowException/Program.cs +++ b/test/test-applications/regression/StackExchange.Redis.StackOverflowException/Program.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler; namespace StackExchange.Redis.StackOverflowException { @@ -12,7 +11,7 @@ private static async Task Main() { try { - Console.WriteLine($"Profiler attached: {Instrumentation.ProfilerAttached}"); + Console.WriteLine($"Profiler attached: {IsProfilerAttached()}"); string host = Environment.GetEnvironmentVariable("STACKEXCHANGE_REDIS_HOST") ?? "localhost:6389"; const int database = 1; @@ -65,6 +64,22 @@ public static IEnumerable> CreateKeyValuePair count++; } } + + private static bool IsProfilerAttached() + { + var instrumentationType = Type.GetType("Datadog.Trace.ClrProfiler.Instrumentation", throwOnError: false); + + if (instrumentationType == null) + { + return false; + } + + var property = instrumentationType.GetProperty("ProfilerAttached"); + + var isAttached = property?.GetValue(null) as bool?; + + return isAttached ?? false; + } } enum ExitCode : int From b28d69caa0578a203939f83f1181c65833b01948 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 23 Jun 2021 15:33:29 +0200 Subject: [PATCH 25/32] Try killing gracefully the graphql process --- .../GraphQLTests.cs | 9 ++++++++- .../integrations/Samples.GraphQL/Program.cs | 2 +- .../integrations/Samples.GraphQL/Startup.cs | 12 +++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/GraphQLTests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/GraphQLTests.cs index 1fe4bb46c75b..8be077672c0d 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/GraphQLTests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/GraphQLTests.cs @@ -155,7 +155,14 @@ public void SubmitsTraces(bool enableCallTarget) if (!process.HasExited) { - process.Kill(); + // Try shutting down gracefully + var shutdownRequest = new RequestInfo() { HttpMethod = "GET", Url = "/shutdown" }; + SubmitRequest(aspNetCorePort, shutdownRequest); + + if (!process.WaitForExit(5000)) + { + process.Kill(); + } } var spans = graphQLValidateSpans.Concat(graphQLExecuteSpans).ToList(); diff --git a/test/test-applications/integrations/Samples.GraphQL/Program.cs b/test/test-applications/integrations/Samples.GraphQL/Program.cs index e8d565d65ea5..d97580702254 100644 --- a/test/test-applications/integrations/Samples.GraphQL/Program.cs +++ b/test/test-applications/integrations/Samples.GraphQL/Program.cs @@ -29,7 +29,7 @@ public static void Main(string[] args) var logger = host.Services.GetRequiredService>(); - logger.LogInformation($"Instrumentation.ProfilerAttached = {IsProfilerAttached()}"); + logger.LogInformation($"Instrumentation.ProfilerAttached = {IsProfilerAttached()}"); var prefixes = new[] { "COR_", "CORECLR_", "DD_", "DATADOG_" }; var envVars = from envVar in Environment.GetEnvironmentVariables().Cast() diff --git a/test/test-applications/integrations/Samples.GraphQL/Startup.cs b/test/test-applications/integrations/Samples.GraphQL/Startup.cs index d637e63ffe96..6b5303812cca 100644 --- a/test/test-applications/integrations/Samples.GraphQL/Startup.cs +++ b/test/test-applications/integrations/Samples.GraphQL/Startup.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging; using GraphQL.StarWars; using GraphQL.StarWars.Types; +using System.Threading.Tasks; namespace Samples.GraphQL { @@ -58,7 +59,7 @@ public void Configure(IApplicationBuilder app, var starWarsSchema = (StarWarsSchema)app.ApplicationServices.GetService(typeof(ISchema)); // Get StarWarsSubscription Singleton - var starWarsSubscription = (StarWarsExtensions.StarWarsSubscription) app.ApplicationServices.GetService(typeof(StarWarsExtensions.StarWarsSubscription)); + var starWarsSubscription = (StarWarsExtensions.StarWarsSubscription)app.ApplicationServices.GetService(typeof(StarWarsExtensions.StarWarsSubscription)); // Set the subscription // We do this roundabout mechanism to keep using the GraphQL.StarWars NuGet package @@ -66,6 +67,15 @@ public void Configure(IApplicationBuilder app, app.UseDeveloperExceptionPage(); app.UseWelcomePage("/alive-check"); + app.Map("/shutdown", builder => + { + builder.Run(async context => + { + await context.Response.WriteAsync("Shutting down"); + _ = Task.Run(() => builder.ApplicationServices.GetService().StopApplication()); + }); + }); + // add http for Schema at default url /graphql app.UseGraphQL("/graphql"); From 0a1c09a92cbc44f8ee291f6750e8dccd68bd4e39 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 23 Jun 2021 16:24:00 +0200 Subject: [PATCH 26/32] Add shutdown handler to aspnetcore --- .../AspNetCore/AspNetCoreMvcTestBase.cs | 14 ++++++++++---- .../Samples.AspNetCoreMvc21/Startup.cs | 11 +++++++++++ .../Samples.AspNetCoreMvc30/Startup.cs | 11 +++++++++++ .../Samples.AspNetCoreMvc31/Startup.cs | 11 +++++++++++ .../integrations/Samples.GraphQL/Startup.cs | 3 +++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs index db2263b29862..b82855921ab7 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs @@ -224,7 +224,13 @@ public async Task RunTraceTestOnSelfHosted(string packageVersion) if (!process.HasExited) { - process.Kill(); + // Try shutting down gracefully + await SubmitRequest(aspNetCorePort, "/shutdown"); + + if (!process.WaitForExit(5000)) + { + process.Kill(); + } } SpanTestHelpers.AssertExpectationsMet(Expectations, spans); @@ -248,9 +254,9 @@ protected void CreateTopLevelExpectation( resourceName, httpStatus, httpMethod) - { - OriginalUri = url, - }; + { + OriginalUri = url, + }; expectation.RegisterDelegateExpectation(additionalCheck); diff --git a/test/test-applications/integrations/Samples.AspNetCoreMvc21/Startup.cs b/test/test-applications/integrations/Samples.AspNetCoreMvc21/Startup.cs index 85c5d8e72f78..656f636fe620 100644 --- a/test/test-applications/integrations/Samples.AspNetCoreMvc21/Startup.cs +++ b/test/test-applications/integrations/Samples.AspNetCoreMvc21/Startup.cs @@ -1,6 +1,8 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -41,6 +43,15 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF app.UseDeveloperExceptionPage(); } + app.Map("/shutdown", builder => + { + builder.Run(async context => + { + await context.Response.WriteAsync("Shutting down"); + _ = Task.Run(() => builder.ApplicationServices.GetService().StopApplication()); + }); + }); + app.UseMvc(routes => { routes.MapRoute( diff --git a/test/test-applications/integrations/Samples.AspNetCoreMvc30/Startup.cs b/test/test-applications/integrations/Samples.AspNetCoreMvc30/Startup.cs index 87fa513c7ca1..9a7ac47b5f26 100644 --- a/test/test-applications/integrations/Samples.AspNetCoreMvc30/Startup.cs +++ b/test/test-applications/integrations/Samples.AspNetCoreMvc30/Startup.cs @@ -1,5 +1,7 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -29,6 +31,15 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } + app.Map("/shutdown", builder => + { + builder.Run(async context => + { + await context.Response.WriteAsync("Shutting down"); + _ = Task.Run(() => builder.ApplicationServices.GetService().StopApplication()); + }); + }); + app.UseRouting(); app.UseEndpoints(endpoints => diff --git a/test/test-applications/integrations/Samples.AspNetCoreMvc31/Startup.cs b/test/test-applications/integrations/Samples.AspNetCoreMvc31/Startup.cs index 87fa513c7ca1..9a7ac47b5f26 100644 --- a/test/test-applications/integrations/Samples.AspNetCoreMvc31/Startup.cs +++ b/test/test-applications/integrations/Samples.AspNetCoreMvc31/Startup.cs @@ -1,5 +1,7 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -29,6 +31,15 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } + app.Map("/shutdown", builder => + { + builder.Run(async context => + { + await context.Response.WriteAsync("Shutting down"); + _ = Task.Run(() => builder.ApplicationServices.GetService().StopApplication()); + }); + }); + app.UseRouting(); app.UseEndpoints(endpoints => diff --git a/test/test-applications/integrations/Samples.GraphQL/Startup.cs b/test/test-applications/integrations/Samples.GraphQL/Startup.cs index 6b5303812cca..30b12d1a04b0 100644 --- a/test/test-applications/integrations/Samples.GraphQL/Startup.cs +++ b/test/test-applications/integrations/Samples.GraphQL/Startup.cs @@ -72,7 +72,10 @@ public void Configure(IApplicationBuilder app, builder.Run(async context => { await context.Response.WriteAsync("Shutting down"); + +#pragma warning disable CS0618 // Type or member is obsolete _ = Task.Run(() => builder.ApplicationServices.GetService().StopApplication()); +#pragma warning restore CS0618 // Type or member is obsolete }); }); From a15e0ffc8502d25ed27e1519a307dde5ef547fd9 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 23 Jun 2021 18:42:38 +0200 Subject: [PATCH 27/32] Add coverage for GAC'd assemblies --- .azure-pipelines/ultimate-pipeline.yml | 8 +--- build/_build/Build.Steps.cs | 3 ++ nuget.config | 1 + .../AspNet/AspNetMvc4Tests.cs | 1 + .../CustomTestFramework.cs | 36 +++++++++++------ ....Trace.ClrProfiler.IntegrationTests.csproj | 3 +- .../Helpers/GacFixture.cs | 40 +++++++++++++++++++ .../Helpers/IisFixture.cs | 20 +++++++++- .../MultiDomainHostTests.cs | 34 ++++++++++------ ...dog.Trace.ClrProfiler.Managed.Tests.csproj | 2 +- .../Datadog.Trace.DuckTyping.Tests.csproj | 2 +- .../Datadog.Trace.IntegrationTests.csproj | 2 +- .../Datadog.Trace.Tests.csproj | 2 +- .../Controllers/HomeController.cs | 19 +++++++++ 14 files changed, 135 insertions(+), 38 deletions(-) create mode 100644 test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/GacFixture.cs diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index 54b97f1dbebf..e0092a883cc0 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -420,13 +420,7 @@ stages: containerregistrytype: Container Registry dockerComposeCommand: up -d IntegrationTests.IIS - - powershell: | - [System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") - $publish = New-Object System.EnterpriseServices.Internal.Publish - Get-ChildItem $(tracerHome)/net45 -Filter *.dll | Foreach-Object { $publish.GacInstall($_.FullName) } - displayName: Add net45 Datadog.Trace.ClrProfiler.Managed assets to the GAC - - - script: build.cmd RunWindowsIisIntegrationTests + - script: build.cmd RunWindowsIisIntegrationTests --code-coverage displayName: RunWindowsIisIntegrationTests - task: PublishTestResults@2 diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 38e5d473d1a2..5b81a18fe311 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -1092,6 +1092,8 @@ private void MoveLogsToBuildData() private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) { + var strongNameKeyPath = Solution.Directory / "Datadog.Trace.snk"; + return settings.SetDataCollector("XPlat Code Coverage") .SetProcessArgumentConfigurator( args => @@ -1099,6 +1101,7 @@ private DotNetTestSettings ConfigureCodeCoverage(DotNetTestSettings settings) .Add("RunConfiguration.DisableAppDomain=true") // https://github.com/coverlet-coverage/coverlet/issues/347 .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.SkipAutoProps=true") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura") + .Add($"DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.StrongNameKey=\"{strongNameKeyPath}\"") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[*]Datadog.Trace.Vendors.*,") .Add("DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Include=\"[Datadog.Trace.ClrProfiler.*]*,[Datadog.Trace]*,[Datadog.Trace.AspNet]*\"")); } diff --git a/nuget.config b/nuget.config index 6ce97590acdd..e6579a70d9d7 100644 --- a/nuget.config +++ b/nuget.config @@ -3,6 +3,7 @@ + diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc4Tests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc4Tests.cs index 0a079b741e59..943ea73d210f 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc4Tests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc4Tests.cs @@ -106,6 +106,7 @@ public AspNetMvc4Tests(IisFixture iisFixture, ITestOutputHelper output, bool ena } _iisFixture = iisFixture; + _iisFixture.ShutdownPath = "/home/shutdown"; _iisFixture.TryStartIis(this, classicMode); _testName = nameof(AspNetMvc4Tests) + (enableCallTarget ? ".CallSite" : ".CallTarget") diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs index 5a09049f0e52..1fd07de2234d 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/CustomTestFramework.cs @@ -23,6 +23,28 @@ public class CustomTestFramework : XunitTestFramework { public CustomTestFramework(IMessageSink messageSink) : base(messageSink) + { + var targetPath = GetProfilerTargetFolder(); + + if (targetPath != null) + { + var file = typeof(Instrumentation).Assembly.Location; + var destination = Path.Combine(targetPath, Path.GetFileName(file)); + File.Copy(file, destination, true); + + messageSink.OnMessage(new DiagnosticMessage("Replaced {0} with {1} to setup code coverage", destination, file)); + + return; + } + + var message = "Could not find the target framework directory"; + + messageSink.OnMessage(new DiagnosticMessage(message)); + + throw new DirectoryNotFoundException(message); + } + + internal static string GetProfilerTargetFolder() { var targetFrameworkDirectory = GetTargetFrameworkDirectory(); @@ -35,21 +57,11 @@ public CustomTestFramework(IMessageSink messageSink) if (Directory.Exists(finalDirectory)) { - var file = typeof(Datadog.Trace.ClrProfiler.Instrumentation).Assembly.Location; - var destination = Path.Combine(finalDirectory, Path.GetFileName(file)); - File.Copy(file, destination, true); - - messageSink.OnMessage(new DiagnosticMessage("Replaced {0} with {1} to setup code coverage", destination, file)); - - return; + return finalDirectory; } } - var message = $"Could not find the {targetFrameworkDirectory} folder. Tried: {string.Join("; ", paths)}"; - - messageSink.OnMessage(new DiagnosticMessage(message)); - - throw new DirectoryNotFoundException(message); + return null; } protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj index d0905d6ea7f8..e595682242d1 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj @@ -25,7 +25,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -36,6 +36,7 @@ + diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/GacFixture.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/GacFixture.cs new file mode 100644 index 000000000000..093953112885 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/GacFixture.cs @@ -0,0 +1,40 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +using System.IO; + +namespace Datadog.Trace.ClrProfiler.IntegrationTests +{ + public class GacFixture + { + public void AddAssembliesToGac() + { +#if NETFRAMEWORK + var publish = new System.EnterpriseServices.Internal.Publish(); + + var targetFolder = CustomTestFramework.GetProfilerTargetFolder(); + + foreach (var file in Directory.GetFiles(targetFolder, "*.dll")) + { + publish.GacInstall(file); + } +#endif + } + + public void RemoveAssembliesFromGac() + { +#if NETFRAMEWORK + var publish = new System.EnterpriseServices.Internal.Publish(); + + var targetFolder = CustomTestFramework.GetProfilerTargetFolder(); + + foreach (var file in Directory.GetFiles(targetFolder, "*.dll")) + { + publish.GacRemove(file); + } +#endif + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs index 9ac74c83ac80..ae2cfafa21fd 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs @@ -6,12 +6,13 @@ using System; using System.Diagnostics; using System.IO; +using System.Net; using Datadog.Core.Tools; using Datadog.Trace.TestHelpers; namespace Datadog.Trace.ClrProfiler.IntegrationTests { - public sealed class IisFixture : IDisposable + public sealed class IisFixture : GacFixture, IDisposable { private (Process Process, string ConfigFile) _iisExpress; @@ -19,17 +20,20 @@ public sealed class IisFixture : IDisposable public int HttpPort { get; private set; } + public string ShutdownPath { get; set; } + public void TryStartIis(TestHelper helper, bool classicMode) { lock (this) { if (_iisExpress.Process == null) { + AddAssembliesToGac(); + var initialAgentPort = TcpPortProvider.GetOpenPort(); Agent = new MockTracerAgent(initialAgentPort); HttpPort = TcpPortProvider.GetOpenPort(); - _iisExpress = helper.StartIISExpress(Agent.Port, HttpPort, classicMode); } } @@ -37,6 +41,12 @@ public void TryStartIis(TestHelper helper, bool classicMode) public void Dispose() { + if (ShutdownPath != null) + { + var request = WebRequest.CreateHttp($"http://localhost:{HttpPort}{ShutdownPath}"); + request.GetResponse().Close(); + } + Agent?.Dispose(); lock (this) @@ -69,6 +79,12 @@ public void Dispose() catch { } + +#if NETFRAMEWORK + // If the operation fails, it could leave files in the GAC and impact the next tests + // Therefore, we don't wrap this in a try/catch + RemoveAssembliesFromGac(); +#endif } } } diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs index bfac1dfabee2..e6cc5ff90c8d 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs @@ -18,11 +18,14 @@ namespace Datadog.Trace.ClrProfiler.IntegrationTests { - public class MultiDomainHostTests : TestHelper + public class MultiDomainHostTests : TestHelper, IClassFixture { - public MultiDomainHostTests(ITestOutputHelper output) + private readonly GacFixture _gacFixture; + + public MultiDomainHostTests(GacFixture gacFixture, ITestOutputHelper output) : base("MultiDomainHost.Runner", output) { + _gacFixture = gacFixture; SetServiceVersion("1.0.0"); } @@ -71,20 +74,27 @@ public void WorksOutsideTheGAC(string targetFramework) [Trait("LoadFromGAC", "True")] public void WorksInsideTheGAC(string targetFramework) { - Assert.True(typeof(Instrumentation).Assembly.GlobalAssemblyCache, "Datadog.Trace.ClrProfiler.Managed was not loaded from the GAC. Ensure that the assembly and its dependencies are installed in the GAC when running this test."); + _gacFixture.AddAssembliesToGac(); - var expectedMap = new Dictionary() + try { - { "Samples.MultiDomainHost.App.FrameworkHttpNoRedirects-http-client", 2 }, - { "Samples.MultiDomainHost.App.NuGetHttpNoRedirects-http-client", 2 }, - { "Samples.MultiDomainHost.App.NuGetJsonWithRedirects-http-client", 2 }, - }; - if (!targetFramework.StartsWith("net45")) + var expectedMap = new Dictionary() + { + { "Samples.MultiDomainHost.App.FrameworkHttpNoRedirects-http-client", 2 }, + { "Samples.MultiDomainHost.App.NuGetHttpNoRedirects-http-client", 2 }, + { "Samples.MultiDomainHost.App.NuGetJsonWithRedirects-http-client", 2 }, + }; + if (!targetFramework.StartsWith("net45")) + { + expectedMap.Add("Samples.MultiDomainHost.App.NuGetHttpWithRedirects-http-client", 2); + } + + RunSampleAndAssertAgainstExpectations(targetFramework, expectedMap); + } + finally { - expectedMap.Add("Samples.MultiDomainHost.App.NuGetHttpWithRedirects-http-client", 2); + _gacFixture.RemoveAssembliesFromGac(); } - - RunSampleAndAssertAgainstExpectations(targetFramework, expectedMap); } [Theory] diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj index 25dd7cb13edc..d07318482795 100644 --- a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj @@ -5,7 +5,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj b/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj index 083c9ef62623..0163960bf979 100644 --- a/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj +++ b/test/Datadog.Trace.DuckTyping.Tests/Datadog.Trace.DuckTyping.Tests.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj index 0e49e379ca44..751f8463cd76 100644 --- a/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj +++ b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj index 97c7dd1146b9..bcc94f630db4 100644 --- a/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj +++ b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj @@ -16,7 +16,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/test-applications/aspnet/Samples.AspNetMvc4/Controllers/HomeController.cs b/test/test-applications/aspnet/Samples.AspNetMvc4/Controllers/HomeController.cs index 82de29a856aa..4c859264e543 100644 --- a/test/test-applications/aspnet/Samples.AspNetMvc4/Controllers/HomeController.cs +++ b/test/test-applications/aspnet/Samples.AspNetMvc4/Controllers/HomeController.cs @@ -24,6 +24,25 @@ orderby key return View(envVars.ToList()); } + public ActionResult Shutdown() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assembly in assemblies) + { + foreach (var type in assembly.DefinedTypes) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker") + { + var unloadModuleMethod = type.GetMethod("UnloadModule", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + unloadModuleMethod.Invoke(null, new object[] { this, EventArgs.Empty }); + } + } + } + + return RedirectToAction("Index"); + } + public ActionResult About() { ViewBag.Message = "Your application description page."; From 6d2ef30f590a219bb3a700cfb0c270a928781458 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Mon, 28 Jun 2021 16:48:29 +0200 Subject: [PATCH 28/32] Don't target incompatible versions --- .../MultiDomainHostTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs index e6cc5ff90c8d..7a8768abd3a8 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs @@ -36,12 +36,14 @@ public MultiDomainHostTests(GacFixture gacFixture, ITestOutputHelper output) new object[] { "net451" }, new object[] { "net452" }, new object[] { "net46" }, +#if !NET45 && !NET451 && !NET452 && !NET46 new object[] { "net461" }, new object[] { "net462" }, new object[] { "net47" }, new object[] { "net471" }, new object[] { "net472" }, new object[] { "net48" }, +#endif }; [Theory] From 16c29fb40608bce6ec71c291e944d9c4f2d12113 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 29 Jun 2021 11:18:03 +0200 Subject: [PATCH 29/32] Enable coverage on the remaining IIS Express tests --- .../AspNet/AspNetMvc5Tests.cs | 1 + .../AspNet/AspNetWebApi2Tests.cs | 1 + .../AspNet/AspNetWebFormsTests.cs | 1 + .../AspNet/OwinWebApi2Tests.cs | 4 ++- .../MultiDomainHostTests.cs | 2 ++ .../Controllers/HomeController.cs | 19 ++++++++++++++ .../Samples.WebForms/Account/Login.aspx.cs | 25 ++++++++++++++++++- .../Controllers/HomeController.cs | 24 +++++++++++++++++- 8 files changed, 74 insertions(+), 3 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc5Tests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc5Tests.cs index 5f05f26df0ff..6b81a04768d9 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc5Tests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetMvc5Tests.cs @@ -106,6 +106,7 @@ public AspNetMvc5Tests(IisFixture iisFixture, ITestOutputHelper output, bool ena } _iisFixture = iisFixture; + _iisFixture.ShutdownPath = "/home/shutdown"; _iisFixture.TryStartIis(this, classicMode); _testName = nameof(AspNetMvc5Tests) + (enableCallTarget ? ".CallSite" : ".CallTarget") diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebApi2Tests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebApi2Tests.cs index 9507f70a8864..f19851ad53e2 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebApi2Tests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebApi2Tests.cs @@ -106,6 +106,7 @@ public AspNetWebApi2Tests(IisFixture iisFixture, ITestOutputHelper output, bool } _iisFixture = iisFixture; + _iisFixture.ShutdownPath = "/home/shutdown"; _iisFixture.TryStartIis(this, classicMode); _testName = nameof(AspNetWebApi2Tests) + (enableCallTarget ? ".CallSite" : ".CallTarget") diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebFormsTests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebFormsTests.cs index de6e9e1c9bb2..bdca6990ca2a 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebFormsTests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/AspNetWebFormsTests.cs @@ -28,6 +28,7 @@ public AspNetWebFormsTests(IisFixture iisFixture, ITestOutputHelper output) SetServiceVersion("1.0.0"); _iisFixture = iisFixture; + _iisFixture.ShutdownPath = "/account/login?shutdown=1"; _iisFixture.TryStartIis(this, classicMode: false); } diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs index a25fd9483164..255172ba1e42 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs @@ -176,6 +176,8 @@ public void Dispose() { if (!_process.HasExited) { + SubmitRequest(null, "/shutdown").GetAwaiter().GetResult(); + _process.Kill(); } } @@ -275,7 +277,7 @@ private async Task SubmitRequest(ITestOutputHelper output, strin { HttpResponseMessage response = await _httpClient.GetAsync($"http://localhost:{HttpPort}{path}"); string responseText = await response.Content.ReadAsStringAsync(); - output.WriteLine($"[http] {response.StatusCode} {responseText}"); + output?.WriteLine($"[http] {response.StatusCode} {responseText}"); return response.StatusCode; } } diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs index 7a8768abd3a8..7010223401f2 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/MultiDomainHostTests.cs @@ -18,6 +18,8 @@ namespace Datadog.Trace.ClrProfiler.IntegrationTests { + // Not actually an IIS test but it shouldn't run concurrently with them + [Collection("IisTests")] public class MultiDomainHostTests : TestHelper, IClassFixture { private readonly GacFixture _gacFixture; diff --git a/test/test-applications/aspnet/Samples.AspNetMvc5/Controllers/HomeController.cs b/test/test-applications/aspnet/Samples.AspNetMvc5/Controllers/HomeController.cs index e51c254599bc..d61f77009dcc 100644 --- a/test/test-applications/aspnet/Samples.AspNetMvc5/Controllers/HomeController.cs +++ b/test/test-applications/aspnet/Samples.AspNetMvc5/Controllers/HomeController.cs @@ -25,6 +25,25 @@ orderby key return View(envVars.ToList()); } + public ActionResult Shutdown() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assembly in assemblies) + { + foreach (var type in assembly.DefinedTypes) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker") + { + var unloadModuleMethod = type.GetMethod("UnloadModule", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + unloadModuleMethod.Invoke(null, new object[] { this, EventArgs.Empty }); + } + } + } + + return RedirectToAction("Index"); + } + public ActionResult Get(int id) { return View("Delay", id); diff --git a/test/test-applications/aspnet/Samples.WebForms/Account/Login.aspx.cs b/test/test-applications/aspnet/Samples.WebForms/Account/Login.aspx.cs index 054adb1fafca..3c71ee9462a5 100644 --- a/test/test-applications/aspnet/Samples.WebForms/Account/Login.aspx.cs +++ b/test/test-applications/aspnet/Samples.WebForms/Account/Login.aspx.cs @@ -5,12 +5,35 @@ namespace Samples.WebForms.Account { public partial class Login : Page { - protected void Page_Load(object sender, EventArgs e) { } + protected void Page_Load(object sender, EventArgs e) + { + if (Request.QueryString["shutdown"] == "1") + { + Shutdown(); + } + } protected void LogIn(object sender, EventArgs e) { FailureText.Text = "Invalid username or password."; ErrorMessage.Visible = true; } + + private void Shutdown() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assembly in assemblies) + { + foreach (var type in assembly.DefinedTypes) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker") + { + var unloadModuleMethod = type.GetMethod("UnloadModule", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + unloadModuleMethod.Invoke(null, new object[] { this, EventArgs.Empty }); + } + } + } + } } } diff --git a/test/test-applications/integrations/Samples.Owin.WebApi2/Controllers/HomeController.cs b/test/test-applications/integrations/Samples.Owin.WebApi2/Controllers/HomeController.cs index 01fb5b541bc6..9d17b6d5707b 100644 --- a/test/test-applications/integrations/Samples.Owin.WebApi2/Controllers/HomeController.cs +++ b/test/test-applications/integrations/Samples.Owin.WebApi2/Controllers/HomeController.cs @@ -1,4 +1,5 @@ -using System.Web.Http; +using System; +using System.Web.Http; namespace Samples.Owin.WebApi2.Controllers { @@ -11,5 +12,26 @@ public string IsAlive() { return "Yes"; } + + [HttpGet] + [Route("shutdown")] + public string Shutdown() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assembly in assemblies) + { + foreach (var type in assembly.DefinedTypes) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker") + { + var unloadModuleMethod = type.GetMethod("UnloadModule", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + unloadModuleMethod.Invoke(null, new object[] { this, EventArgs.Empty }); + } + } + } + + return "Code coverage data has been flushed"; + } } } From a4b98775a98e0936e3366a8d91eeaa31b175e0dd Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Thu, 1 Jul 2021 11:16:41 +0200 Subject: [PATCH 30/32] Explicitly unload the appdomain --- build/_build/Build.Steps.cs | 1 + .../Samples.MultiDomainHost.Runner/Program.cs | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/build/_build/Build.Steps.cs b/build/_build/Build.Steps.cs index 5b81a18fe311..268767c9aa49 100644 --- a/build/_build/Build.Steps.cs +++ b/build/_build/Build.Steps.cs @@ -805,6 +805,7 @@ _ when projectPath.ToString().Contains("Samples.OracleMDA") => false, .SetDotnetPath(Platform) .SetConfiguration(BuildConfiguration) .SetTargetPlatform(Platform) + .When(Framework != null, o => o.SetFramework(Framework)) .EnableNoRestore() .EnableNoBuild() .SetFilter(Filter ?? "(RunOnWindows=True|Category=Smoke)&LoadFromGAC=True") diff --git a/test/test-applications/integrations/Samples.MultiDomainHost.Runner/Program.cs b/test/test-applications/integrations/Samples.MultiDomainHost.Runner/Program.cs index ecddcfd10e0e..9bf1093a2324 100644 --- a/test/test-applications/integrations/Samples.MultiDomainHost.Runner/Program.cs +++ b/test/test-applications/integrations/Samples.MultiDomainHost.Runner/Program.cs @@ -57,6 +57,8 @@ static int Main(string[] args) private static void CreateAndRunAppDomain(string appName) { + AppDomain domain = null; + try { // Construct and initialize settings for a second AppDomain. @@ -69,7 +71,7 @@ private static void CreateAndRunAppDomain(string appName) Path.Combine(ads.ApplicationBase, appName + ".exe.config"); PermissionSet ps = new PermissionSet(PermissionState.Unrestricted); - System.AppDomain appDomain1 = System.AppDomain.CreateDomain( + domain = System.AppDomain.CreateDomain( appName, System.AppDomain.CurrentDomain.Evidence, ads, @@ -77,7 +79,7 @@ private static void CreateAndRunAppDomain(string appName) Console.WriteLine("**********************************************"); Console.WriteLine($"Starting code execution in AppDomain {appName}"); - appDomain1.ExecuteAssemblyByName( + domain.ExecuteAssemblyByName( appName, new string[0]); } @@ -90,6 +92,13 @@ private static void CreateAndRunAppDomain(string appName) Console.WriteLine($"Finished code execution in AppDomain {appName}"); Console.WriteLine("**********************************************"); Console.WriteLine(); + + if (domain != null) + { + // Wait for traces to be flushed, then unload the domain + Thread.Sleep(2000); + AppDomain.Unload(domain); + } } } } From 3b4af8e78f2fbbea0aee007c72fc35263f906104 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Tue, 6 Jul 2021 16:05:16 +0200 Subject: [PATCH 31/32] Address PR feedback --- .../AspNet/OwinWebApi2Tests.cs | 2 +- .../AspNetCore/AspNetCoreMvcTestBase.cs | 2 +- .../Helpers/IisFixture.cs | 2 -- test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs | 7 +------ 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs index 255172ba1e42..4ee0f9110bd8 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNet/OwinWebApi2Tests.cs @@ -270,7 +270,7 @@ private bool IsNotServerLifeCheck(MockTracerAgent.Span span) return true; } - return !url.Contains("alive-check"); + return !url.Contains("alive-check") && !url.Contains("shutdown"); } private async Task SubmitRequest(ITestOutputHelper output, string path) diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs index b82855921ab7..d79a896bf809 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/AspNetCore/AspNetCoreMvcTestBase.cs @@ -299,7 +299,7 @@ private bool IsNotServerLifeCheck(MockTracerAgent.Span span) return true; } - return !url.Contains("alive-check"); + return !url.Contains("alive-check") && !url.Contains("shutdown"); } } } diff --git a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs index ae2cfafa21fd..4754b2950e24 100644 --- a/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs +++ b/test/Datadog.Trace.ClrProfiler.IntegrationTests/Helpers/IisFixture.cs @@ -80,11 +80,9 @@ public void Dispose() { } -#if NETFRAMEWORK // If the operation fails, it could leave files in the GAC and impact the next tests // Therefore, we don't wrap this in a try/catch RemoveAssembliesFromGac(); -#endif } } } diff --git a/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs index b03c48b888d5..d10dcb8d7308 100644 --- a/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs +++ b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs @@ -277,8 +277,6 @@ public string GetProfilerPath() { if (_profilerFileLocation == null) { - int attempt = 1; - var paths = GetProfilerPathCandidates(GetSampleApplicationOutputDirectory()).ToArray(); foreach (var candidate in paths) @@ -289,12 +287,9 @@ public string GetProfilerPath() _output?.WriteLine($"Found profiler at {_profilerFileLocation}."); return candidate; } - - _output?.WriteLine($"Attempt {attempt}: Unable to find profiler at {candidate}."); - attempt++; } - throw new Exception($"Unable to find profiler in any of the paths: {string.Join("; ", _profilerFileLocation)}"); + throw new Exception($"Unable to find profiler in any of the paths: {string.Join("; ", paths)}"); } return _profilerFileLocation; From 6e9e0d24698b5bc3e5244bf937a75b16b2fabe68 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Thu, 8 Jul 2021 17:07:30 +0200 Subject: [PATCH 32/32] Change schedule variable --- .azure-pipelines/ultimate-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index e0092a883cc0..dd429bc43553 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -944,7 +944,7 @@ stages: env: DD_SERVICE: dd-trace-dotnet - stage: coverage - condition: and(succeeded(), eq(variables['benchmarksOnly'], 'False')) + condition: and(succeeded(), eq(variables['isScheduledBuild'], 'False')) dependsOn: [integration_tests_windows, integration_tests_windows_iis, integration_tests_linux, unit_tests_linux, unit_tests_macos, unit_tests_windows] jobs: - job: Windows