diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b7fa1b5f3..effa4408ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,19 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h - .NET Framework only, following packages updated - `OpenTelemetry.Instrumentation.AspNet` from `1.12.0-beta.1` to `1.12.0-beta.2`. +#### Dependencies on .Net Framework + +When OpenTelemetry .NET AutoInstrumentation is compiled for .NET Framework, +it uses the net462 Target Framework Moniker (TFM). As a result, the ZIP archive +deployment contained dependency assemblies targeted for .NET Framework 4.6.2. +Some of these assemblies were not designed to be used with later versions of +.NET Framework. + +Now, when the OpenTelemetry ZIP archive is built, dependency assemblies are +included for all supported .NET Framework versions. OpenTelemetry .NET +AutoInstrumentation detects the .NET Framework version at install time +and runtime, then loads the correct version of dependency assemblies. + ### Deprecated ### Removed diff --git a/OpenTelemetry.AutoInstrumentation.sln b/OpenTelemetry.AutoInstrumentation.sln index 5c95a2bc98..0775f4cf04 100644 --- a/OpenTelemetry.AutoInstrumentation.sln +++ b/OpenTelemetry.AutoInstrumentation.sln @@ -253,6 +253,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.ProfilerSpa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.NoCode", "test\test-applications\integrations\TestApplication.NoCode\TestApplication.NoCode.csproj", "{500BF40F-EECB-4F6A-377B-EDBDFFDE09BE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework", "src\OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework\OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj", "{B69564D4-7D5B-7147-6CBA-233BB8A33C50}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1585,6 +1587,22 @@ Global {500BF40F-EECB-4F6A-377B-EDBDFFDE09BE}.Release|x64.Build.0 = Release|x64 {500BF40F-EECB-4F6A-377B-EDBDFFDE09BE}.Release|x86.ActiveCfg = Release|x86 {500BF40F-EECB-4F6A-377B-EDBDFFDE09BE}.Release|x86.Build.0 = Release|x86 + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|ARM64.Build.0 = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|x64.ActiveCfg = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|x64.Build.0 = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|x86.ActiveCfg = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Debug|x86.Build.0 = Debug|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|Any CPU.Build.0 = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|ARM64.ActiveCfg = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|ARM64.Build.0 = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|x64.ActiveCfg = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|x64.Build.0 = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|x86.ActiveCfg = Release|Any CPU + {B69564D4-7D5B-7147-6CBA-233BB8A33C50}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1678,6 +1696,7 @@ Global {FD1A1ABD-6A48-4E94-B5F7-2081AFCD1BBB} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {665280EB-F428-4C04-A293-33228C73BF8A} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {500BF40F-EECB-4F6A-377B-EDBDFFDE09BE} = {E409ADD3-9574-465C-AB09-4324D205CC7C} + {B69564D4-7D5B-7147-6CBA-233BB8A33C50} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} diff --git a/build/AssemblyRedirectionSourceGenerator.cs b/build/AssemblyRedirectionSourceGenerator.cs index cb2c42fcda..35a7860393 100644 --- a/build/AssemblyRedirectionSourceGenerator.cs +++ b/build/AssemblyRedirectionSourceGenerator.cs @@ -1,4 +1,5 @@ using System.Text; +using System.Text.RegularExpressions; using Mono.Cecil; using Serilog; @@ -7,8 +8,36 @@ public static class AssemblyRedirectionSourceGenerator public static void Generate(string assembliesFolderPath, string generatedFilePath) { Log.Debug("Generating assembly redirection file {0}", generatedFilePath); - var assemblies = new SortedDictionary(); - foreach (var fileName in Directory.EnumerateFiles(assembliesFolderPath)) + var assemblies = new SortedDictionary>(); + + var folders = new Dictionary(); + + var frameworkVersionRegEx = new Regex(@"^net(?\d{2,3})$"); + foreach (var directory in Directory.EnumerateDirectories(assembliesFolderPath)) + { + var folderName = Path.GetFileName(directory); + var framework = frameworkVersionRegEx.Match(folderName).Groups["version"].Value; + if (framework == string.Empty) + { + Log.Error("Unexpected folder name: {0}, will not be processed", framework); + continue; + } + var frameworkVersion = int.Parse(framework); + if (frameworkVersion < 100) + { + frameworkVersion *= 10; + } + + if (folders.TryGetValue(frameworkVersion, out var folder)) + { + Log.Error("For {0}: already registered folder {1}, {2} will be skipped", frameworkVersion, folder, directory); + continue; + } + folders[frameworkVersion] = directory; + assemblies[frameworkVersion] = new SortedDictionary(); + } + + void Process(string fileName, int? framework) { try { @@ -17,11 +46,16 @@ public static void Generate(string assembliesFolderPath, string generatedFilePat if (assemblyDef.Name == "netstandard") { // Skip netstandard, since it doesn't need redirection. - continue; + return; } - assemblies[assemblyDef.Name] = assemblyDef; - Log.Debug("Adding {0} assembly to the redirection map. Targeted version {1}", assemblyDef.Name, assemblyDef.Version); + + foreach (var keys in framework != null ? (IEnumerable)[framework.Value] : assemblies.Keys) + { + assemblies[keys][assemblyDef.Name] = assemblyDef; + Log.Debug("Adding {0} assembly to the redirection map {1}. Targeted version {2}", assemblyDef.Name, + keys, assemblyDef.Version); + } } catch (BadImageFormatException) { @@ -29,13 +63,33 @@ public static void Generate(string assembliesFolderPath, string generatedFilePat } } + foreach (var fileName in Directory.EnumerateFiles(assembliesFolderPath)) + { + Process(fileName, null); + } + + foreach (var fx in folders) + { + foreach (var fileName in Directory.EnumerateFiles(fx.Value)) + { + var filenameToProcess = fileName; + if (Path.GetExtension(fileName) == ".link") + { + filenameToProcess = Path.Combine(assembliesFolderPath, File.ReadAllText(fileName), + Path.GetFileNameWithoutExtension(fileName)); + } + + Process(filenameToProcess, fx.Key); + } + } + var sourceContents = GenerateSourceContents(assemblies); File.WriteAllText(generatedFilePath, sourceContents); Log.Information("Assembly redirection source generated {0}", generatedFilePath); } - private static string GenerateSourceContents(SortedDictionary assemblies) + private static string GenerateSourceContents(SortedDictionary> assemblies) { #pragma warning disable format return @@ -70,22 +124,26 @@ namespace trace #pragma warning restore format } - private static string GenerateEntries(SortedDictionary assemblies) + private static string GenerateEntries(SortedDictionary> frameworks) { - var longLineLength = 80; - var sb = new StringBuilder(assemblies.Count * longLineLength); + var sb = new StringBuilder(); - foreach (var kvp in assemblies) + foreach (var fx in frameworks) { - var v = kvp.Value.Version!; - if (kvp.Key != "OpenTelemetry.AutoInstrumentation") - { - sb.AppendLine($" {{ L\"{kvp.Key}\", {{{v.Major}, {v.Minor}, {v.Build}, {v.Revision}}} }},"); - } - else + sb.AppendLine($" {{ {fx.Key}, {{"); + foreach (var kvp in fx.Value) { - sb.AppendLine($" {{ L\"{kvp.Key}\", {{auto_major, 0, 0, 0}} }},"); + var v = kvp.Value.Version!; + if (kvp.Key != "OpenTelemetry.AutoInstrumentation") + { + sb.AppendLine($" {{ L\"{kvp.Key}\", {{{v.Major}, {v.Minor}, {v.Build}, {v.Revision}}} }},"); + } + else + { + sb.AppendLine($" {{ L\"{kvp.Key}\", {{auto_major, 0, 0, 0}} }},"); + } } + sb.AppendLine(" }},"); } return sb.ToString() diff --git a/build/Build.NuGet.Steps.cs b/build/Build.NuGet.Steps.cs index f809f46487..b56c295b64 100644 --- a/build/Build.NuGet.Steps.cs +++ b/build/Build.NuGet.Steps.cs @@ -30,7 +30,7 @@ partial class Build .Description("Build the NuGet packages that are generated directly from src/**/*.csproj files") .Executes(() => { - foreach (var project in Solution.GetManagedSrcProjects().Where(p => !p.Name.EndsWith("AdditionalDeps"))) + foreach (var project in Solution.GetManagedSrcProjects().Where(p => !p.Name.EndsWith("AdditionalDeps") && !p.Name.Contains("Assemblies"))) { DotNetPack(x => x .SetProject(project) diff --git a/build/Build.Steps.Windows.cs b/build/Build.Steps.Windows.cs index 6743580a7c..0ad47fcfa2 100644 --- a/build/Build.Steps.Windows.cs +++ b/build/Build.Steps.Windows.cs @@ -1,4 +1,6 @@ using DependencyListGenerator; +using Extensions; +using NuGet.Versioning; using Nuke.Common; using Nuke.Common.IO; using Nuke.Common.ProjectModel; @@ -208,46 +210,41 @@ void BuildDockerImage(Project project, params string[] targets) .Executes(() => { // The target project needs to have its NuGet packages restored prior to running the tool. - var targetProject = Solution.GetProjectByName(Projects.AutoInstrumentation); + var targetProject = Solution.GetProjectByName(Projects.AutoInstrumentationNetFxAssemblies); DotNetRestore(s => s.SetProjectFile(targetProject)); var project = targetProject.GetMSBuildProject(); - var packages = Solution.Directory / "src" / "Directory.Packages.props"; - - const string label = $"Transient dependencies auto-generated by {nameof(GenerateNetFxTransientDependencies)}"; + var deps = Generator.EnumerateDependencies(project.FullPath); + var packages = Solution.Directory / "src" / Projects.AutoInstrumentationNetFxAssemblies / "Directory.Packages.props"; + var packagesProject = ProjectModelTasks.ParseProject(packages); - var packagesGroup = project.Xml.ItemGroups.FirstOrDefault(x => x.Label == label); - if (packagesGroup == null) + foreach (var framework in targetProject.GetTargetFrameworks() ?? []) { - packagesGroup = project.Xml.AddItemGroup(); - packagesGroup.Label = label; - packagesGroup.Condition = " '$(TargetFramework)' == 'net462' AND $(_IsPacking) != true "; - } + var label = + $"Transient dependencies auto-generated by {nameof(GenerateNetFxTransientDependencies)} for {framework}"; - var packagesProject = ProjectModelTasks.ParseProject(packages); - var versionGroup = packagesProject.Xml.ItemGroups.FirstOrDefault(x => x.Label == label); - if (versionGroup == null) - { - versionGroup = packagesProject.Xml.AddItemGroup(); - versionGroup.Label = label; - } + var projectForTfm = targetProject.GetMSBuildProject(targetFramework: framework); + var definedVersions = projectForTfm + .Items.Where(it => it.ItemType == "PackageVersion").ToDictionary(item => item.EvaluatedInclude, item => item.GetMetadata("Version")); - var deps = Generator.EnumerateDependencies(project.FullPath); - foreach (var item in deps) - { - if (!packagesGroup.Items.Any(x => x.Include == item.Name)) + var versionGroup = packagesProject.Xml.ItemGroups.FirstOrDefault(x => x.Label == label); + if (versionGroup == null) { - packagesGroup.AddItem("PackageReference", item.Name); + versionGroup = packagesProject.Xml.AddItemGroup(); + versionGroup.Label = label; + versionGroup.Condition = $" '$(TargetFramework)' == '{framework}' "; } - if (!versionGroup.Items.Any(x => x.Include == item.Name)) + foreach (var item in deps[framework]) { - var reference = versionGroup.AddItem("PackageVersion", item.Name); - reference.AddMetadata("Version", item.Version, expressAsAttribute: true); + if (!definedVersions.ContainsKey(item.Name)) + { + var reference = versionGroup.AddItem("PackageVersion", item.Name); + reference.AddMetadata("Version", item.Version, expressAsAttribute: true); + } } } - project.Save(); packagesProject.Save(); }); @@ -288,9 +285,16 @@ private void RunNetFxGacOperation(string operation) throw new InvalidOperationException("This target must be run on Windows as Administrator."); } - var netFxAssembliesFolder = TracerHomeDirectory / MapToFolderOutput(TargetFramework.NET462); + // We assume that dev machine running test has .Net Framework not older than TargetFrameworksNetFx.Last() + var netFxCommonAssembliesFolder = TracerHomeDirectory / MapToFolderOutput(TargetFrameworksNetFx.Last()); + var netFxAssembliesFolder = TracerHomeDirectory / MapToFolderOutputNetFx(TargetFrameworksNetFx.Last()); var installTool = Solution.GetProjectByName(Projects.Tools.GacInstallTool); + DotNetRun(s => s + .SetProjectFile(installTool) + .SetConfiguration(BuildConfiguration) + .SetApplicationArguments(operation, netFxCommonAssembliesFolder)); + DotNetRun(s => s .SetProjectFile(installTool) .SetConfiguration(BuildConfiguration) diff --git a/build/Build.Steps.cs b/build/Build.Steps.cs index 96ff2b5526..dd40cc6144 100644 --- a/build/Build.Steps.cs +++ b/build/Build.Steps.cs @@ -1,5 +1,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; using System.Text.Json; using System.Text.Json.Nodes; using Extensions; @@ -42,9 +44,17 @@ partial class Build : new[] { MSBuildTargetPlatform.x86 }; private static readonly IEnumerable TargetFrameworks = new[] + { + TargetFramework.NET8_0, + TargetFramework.NET462, + }; + + private static readonly IEnumerable TargetFrameworksNetFx = new[] { TargetFramework.NET462, - TargetFramework.NET8_0 + TargetFramework.NET47, + TargetFramework.NET471, + TargetFramework.NET472, }; private static readonly IEnumerable TestFrameworks = TargetFrameworks @@ -267,18 +277,33 @@ DotNetBuildSettings BuildTestApplication(DotNetBuildSettings x, string targetFra { var targetFrameworks = IsWin ? TargetFrameworks - : TargetFrameworks.Where(framework => !framework.ToString().StartsWith("net4")); + : TargetFrameworks.ExceptNetFramework(); + // Publish Projects.AutoInstrumentation for .NET targets DotNetPublish(s => s .SetProject(Solution.GetProjectByName(Projects.AutoInstrumentation)) .SetConfiguration(BuildConfiguration) .SetTargetPlatformAnyCPU() .EnableNoBuild() .SetNoRestore(NoRestore) - .CombineWith(targetFrameworks, (p, framework) => p + .CombineWith(targetFrameworks.ExceptNetFramework(), (p, framework) => p .SetFramework(framework) .SetOutput(TracerHomeDirectory / MapToFolderOutput(framework)))); + if (IsWin) + { + // Publish OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework for .NET Framework targets + DotNetPublish(s => s + .SetProject(Solution.GetProjectByName(Projects.AutoInstrumentationNetFxAssemblies)) + .SetConfiguration(BuildConfiguration) + .SetTargetPlatformAnyCPU() + .EnableNoBuild() + .SetNoRestore(NoRestore) + .CombineWith(TargetFrameworksNetFx, (p, framework) => p + .SetFramework(framework) + .SetOutput(TracerHomeDirectory / MapToFolderOutputNetFx(framework)))); + } + // StartupHook is supported starting .Net Core 3.1. // We need to emit AutoInstrumentationStartupHook for .Net Core 3.1 target framework // to avoid application crash with .Net Core 3.1 and .NET 5.0 apps. @@ -313,6 +338,8 @@ DotNetBuildSettings BuildTestApplication(DotNetBuildSettings x, string targetFra RemoveFilesInNetFolderAvailableInAdditionalStore(); RemoveNonLibraryFilesFromOutput(); + + RemoveDuplicateNetFxLibraries(); }); void RemoveNonLibraryFilesFromOutput() @@ -356,6 +383,72 @@ void RemoveFilesInNetFolderAvailableInAdditionalStore() } } + void RemoveDuplicateNetFxLibraries() + { + bool FilesAreEqual(string filePath1, string filePath2) + { + using var hashAlg = SHA256.Create(); + using var stream1 = File.OpenRead(filePath1); + using var stream2 = File.OpenRead(filePath2); + + var hash1 = hashAlg.ComputeHash(stream1); + var hash2 = hashAlg.ComputeHash(stream2); + + return hash1.SequenceEqual(hash2); + } + + if (IsWin) + { + (TracerHomeDirectory / "netfx").GlobFiles("**/*.link").DeleteFiles(); + (TracerHomeDirectory / "netfx").GlobFiles("**/_._").DeleteFiles(); + var latestFramework = TargetFramework.NetFramework.Last(); + (TracerHomeDirectory / "netfx" / latestFramework).GlobFiles("*.*") + .Where(file => TargetFramework.NetFramework.TakeUntil(older => older == latestFramework) + .All(olderFramework => + { + var duplicateCandidate = TracerHomeDirectory / "netfx" / olderFramework / file.Name; + return File.Exists(duplicateCandidate) && FilesAreEqual(file, duplicateCandidate); + })).ForEach(file => + { + file.MoveToDirectory(TracerHomeDirectory / "netfx", ExistsPolicy.FileOverwrite); + TargetFramework.NetFramework.TakeUntil(older => older == latestFramework) + .ForEach(olderFramework => + (TracerHomeDirectory / "netfx" / olderFramework / file.Name).DeleteFile()); + } + ); + + foreach (var currentFramework in TargetFramework.NetFramework.Skip(1).Reverse()) + { + (TracerHomeDirectory / "netfx" / currentFramework).GlobFiles("*.dll").ForEach(file => + { + foreach (var olderFramework in TargetFramework.NetFramework.TakeUntil(older => + older == currentFramework)) + { + var duplicateCandidate = TracerHomeDirectory / "netfx" / olderFramework / file.Name; + if (File.Exists(duplicateCandidate) && FilesAreEqual(file, duplicateCandidate)) + { + file.DeleteFile(); + (TracerHomeDirectory / "netfx" / currentFramework / (file.Name + ".link")).WriteAllText( + olderFramework, Encoding.ASCII, false); + break; + } + } + } + ); + } + + // Create placeholder file for empty directories + foreach (var currentFramework in TargetFramework.NetFramework) + { + if ((TracerHomeDirectory / "netfx" / currentFramework).GlobFiles("*.*").Count == 0) + { + (TracerHomeDirectory / "netfx" / currentFramework / "_._") + .WriteAllText(string.Empty, Encoding.ASCII, false); + } + } + } + } + Target PublishNativeProfiler => _ => _ .Unlisted() .DependsOn(PublishNativeProfilerWindows) @@ -726,7 +819,12 @@ private void RunBootstrappingTests() private string MapToFolderOutput(TargetFramework targetFramework) { - return targetFramework.ToString().StartsWith("net4") ? "netfx" : "net"; + return targetFramework.ToString().StartsWith("net4") ? $"netfx" : "net"; + } + + private string MapToFolderOutputNetFx(TargetFramework targetFramework) + { + return $"netfx/{targetFramework}"; } private void RestoreLegacyNuGetPackagesConfig(IEnumerable legacyRestoreProjects) diff --git a/build/Projects.cs b/build/Projects.cs index b4258ffafd..46b224d841 100644 --- a/build/Projects.cs +++ b/build/Projects.cs @@ -1,6 +1,7 @@ public static class Projects { public const string AutoInstrumentation = "OpenTelemetry.AutoInstrumentation"; + public const string AutoInstrumentationNetFxAssemblies = "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework"; public const string AutoInstrumentationLoader = "OpenTelemetry.AutoInstrumentation.Loader"; public const string AutoInstrumentationNative = "OpenTelemetry.AutoInstrumentation.Native"; public const string AutoInstrumentationStartupHook = "OpenTelemetry.AutoInstrumentation.StartupHook"; diff --git a/build/ProjectsHelper.cs b/build/ProjectsHelper.cs index d9ab9e033b..c1162bdaaf 100644 --- a/build/ProjectsHelper.cs +++ b/build/ProjectsHelper.cs @@ -26,7 +26,8 @@ public static IEnumerable GetManagedSrcProjects(this Solution solution) // Should contain in the src directory SrcDirectory.Contains(x.Directory) && // Should not be native projects - !x.Name.Contains(NativeProjectMarker)); + !x.Name.Contains(NativeProjectMarker) + && (!x.Name.EndsWith(NetFrameworkMarker) || EnvironmentInfo.IsWin)); } public static IEnumerable GetNativeSrcProjects(this Solution solution) diff --git a/build/TargetFramework.cs b/build/TargetFramework.cs index e68fcd7321..f40e1a5bbb 100644 --- a/build/TargetFramework.cs +++ b/build/TargetFramework.cs @@ -9,12 +9,16 @@ public class TargetFramework : Enumeration { public static readonly TargetFramework NOT_SPECIFIED = new() { Value = string.Empty }; public static readonly TargetFramework NET462 = new() { Value = "net462" }; + public static readonly TargetFramework NET47 = new() { Value = "net47" }; + public static readonly TargetFramework NET471 = new() { Value = "net471" }; + public static readonly TargetFramework NET472 = new() { Value = "net472" }; public static readonly TargetFramework NETCore3_1 = new() { Value = "netcoreapp3.1" }; public static readonly TargetFramework NET8_0 = new() { Value = "net8.0" }; public static readonly TargetFramework NET9_0 = new() { Value = "net9.0" }; + // should be in version order public static readonly TargetFramework[] NetFramework = { - NET462 + NET462, NET47, NET471, NET472, NET472 }; public static implicit operator string(TargetFramework framework) diff --git a/docs/README.md b/docs/README.md index b9f0f2b11d..3f6ac54811 100644 --- a/docs/README.md +++ b/docs/README.md @@ -317,6 +317,14 @@ Unregister-OpenTelemetryForWindowsService -WindowsServiceName MyServiceName Uninstall-OpenTelemetryCore ``` +#### Update .Net Framework version + +By default, `Install-OpenTelemetryCore` and `Update-OpenTelemetryCore` register OpenTelemetry (and dependencies) +assemblies in the Global Assembly Cache (GAC). Some of these assemblies are tightly coupled to specific .NET Framework versions. + +When upgrading from .NET Framework versions older than 4.7.2, these assemblies should be removed from the GAC. +For such upgrade scenarios, it is recommended to uninstall and reinstall OpenTelemetry after the .NET Framework update is complete. + ## Instrument a container You can find our demonstrative example diff --git a/script-templates/OpenTelemetry.DotNet.Auto.psm1.template b/script-templates/OpenTelemetry.DotNet.Auto.psm1.template index 482ceaa312..9107a9614c 100644 --- a/script-templates/OpenTelemetry.DotNet.Auto.psm1.template +++ b/script-templates/OpenTelemetry.DotNet.Auto.psm1.template @@ -250,7 +250,6 @@ function Get-OpenTelemetry-Archive([string] $Version, [string] $LocalPath) { function Test-AssemblyNotForGAC([string] $Name) { switch ($Name) { - "netstandard.dll" { return $true } "grpc_csharp_ext.x64.dll" { return $true } "grpc_csharp_ext.x86.dll" { return $true } } @@ -308,8 +307,33 @@ function Register-AssembliesInGAC() { # Register .NET Framework dlls in GAC [System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null - $publish = New-Object System.EnterpriseServices.Internal.Publish - $dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File + $publish = New-Object System.EnterpriseServices.Internal.Publish + + $dlls = @() + + $release = Get-ItemPropertyValue -LiteralPath 'HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' -Name Release + switch ($release) { + { $_ -ge 461808 } { $fxversion = 'net472'; break } + { $_ -ge 461308 } { $fxversion = 'net471'; break } + { $_ -ge 460798 } { $fxversion = 'net47'; break } + { $_ -ge 394802 } { $fxversion = 'net462'; break } + default { $version = $null; break } + } + if (-not $fxversion) { + Write-Error ".NET Framework bellow 4.6.2 is not supported" + return + } + + $dlls = @() + $dlls = $dlls + (Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File) + $dlls = $dlls + (Get-ChildItem -Path $installDir\netfx\$fxversion\ -Filter *.dll -File) + + $linkedDlls = Get-ChildItem -Path $installDir\netfx\$fxversion\ -Filter *.dll.link -File + foreach($link in $linkedDlls) { + $linkTarget = Get-Content $($link.FullName) + $dlls = $dlls + (Get-ChildItem -Path $installDir\netfx\$linkTarget\$($link.Basename) -File) + } + for ($i = 0; $i -lt $dlls.Count; $i++) { $percentageComplete = $i / $dlls.Count * 100 Write-Progress -Activity "Registering .NET Framework dlls in GAC" ` @@ -319,7 +343,7 @@ function Register-AssembliesInGAC() { if (Test-AssemblyNotForGAC $dlls[$i].Name) { continue } - + #Write-Host $dlls[$i].FullName $publish.GacInstall($dlls[$i].FullName) } Write-Progress -Activity "Registering .NET Framework dlls in GAC" -Status "Ready" -Completed @@ -394,7 +418,7 @@ function Uninstall-OpenTelemetryCore() { # Unregister .NET Framwework dlls from GAC [System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null $publish = New-Object System.EnterpriseServices.Internal.Publish - $dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File + $dlls = Get-ChildItem -Path $installDir\netfx\ -Recurse -Filter *.dll -File for ($i = 0; $i -lt $dlls.Count; $i++) { $percentageComplete = $i / $dlls.Count * 100 Write-Progress -Activity "Unregistering .NET Framework dlls from GAC" ` @@ -456,7 +480,7 @@ function Update-OpenTelemetryCore() { Remove-Module OpenTelemetry.Dotnet.Auto Import-Module $modulePath - Install-OpenTelemetryCore -InstallDir $installDir -RegisterAssembliesInGAC $$RegisterAssembliesInGAC + Install-OpenTelemetryCore -InstallDir $installDir -RegisterAssembliesInGAC $RegisterAssembliesInGAC if ($RegisterIIS) { Register-OpenTelemetryForIIS } diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 6ab6d1fd9a..16ef13c919 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -45,30 +45,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/Directory.Packages.props b/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/Directory.Packages.props new file mode 100644 index 0000000000..219a79d4f1 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/Directory.Packages.props @@ -0,0 +1,124 @@ + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj b/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj new file mode 100644 index 0000000000..d174f2c4eb --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework/OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj @@ -0,0 +1,19 @@ + + + + + + net462;net47;net471;net472 + none + false + false + true + false + false + + + + + + + diff --git a/src/OpenTelemetry.AutoInstrumentation.Loader/AssemblyResolver.NetFramework.cs b/src/OpenTelemetry.AutoInstrumentation.Loader/AssemblyResolver.NetFramework.cs index 2b71da4b6e..2e04a62d62 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Loader/AssemblyResolver.NetFramework.cs +++ b/src/OpenTelemetry.AutoInstrumentation.Loader/AssemblyResolver.NetFramework.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; +using Microsoft.Win32; namespace OpenTelemetry.AutoInstrumentation.Loader; @@ -19,7 +20,45 @@ private static string ResolveManagedProfilerDirectory() { var tracerHomeDirectory = ReadEnvironmentVariable("OTEL_DOTNET_AUTO_HOME") ?? string.Empty; var tracerFrameworkDirectory = "netfx"; - return Path.Combine(tracerHomeDirectory, tracerFrameworkDirectory); + var frameworkVersion = GetNetFrameworkVersionFolder(); + + return Path.Combine(tracerHomeDirectory, tracerFrameworkDirectory, frameworkVersion); + } + + private static string GetNetFrameworkVersionFolder() + { + try + { + // Try to get version from Windows Registry first (most reliable method) + using var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default); + using var subKey = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"); + var releaseValue = subKey?.GetValue("Release"); + if (releaseValue is int release) + { + // Map release number to framework version number + // Based on https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed + if (release >= 461808) + { + return "net472"; // .NET Framework 4.7.2 + } + + if (release >= 461308) + { + return "net471"; // .NET Framework 4.7.1 + } + + if (release >= 460798) + { + return "net47"; // .NET Framework 4.7 + } + } + } + catch (Exception ex) + { + logger.Debug(ex, "Error getting .NET Framework version from Windows Registry"); + } + + return "net462"; } internal static Assembly? AssemblyResolve_ManagedProfilerDependencies(object sender, ResolveEventArgs args) @@ -61,7 +100,33 @@ private static string ResolveManagedProfilerDirectory() return null; } - var path = Path.Combine(ManagedProfilerDirectory, $"{assemblyName}.dll"); + var path = Path.Combine(Path.GetDirectoryName(ManagedProfilerDirectory) ?? ManagedProfilerDirectory, $"{assemblyName}.dll"); + if (!File.Exists(path)) + { + path = Path.Combine(ManagedProfilerDirectory, $"{assemblyName}.dll"); + if (!File.Exists(path)) + { + var link = Path.Combine(ManagedProfilerDirectory, $"{assemblyName}.dll.link"); + if (File.Exists(link)) + { + try + { + var linkPath = File.ReadAllText(link).Trim(); + path = Path.Combine(Path.GetDirectoryName(ManagedProfilerDirectory) ?? ManagedProfilerDirectory, linkPath, $"{assemblyName}.dll"); + } + catch (Exception ex) + { + logger.Debug(ex, "Error reading .link file {0}", link); + } + } + else + { + // Not found + return null; + } + } + } + if (File.Exists(path)) { try diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp index fca639ef8d..daa7a32cfd 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp +++ b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp @@ -125,6 +125,7 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un // code is ready to get runtime information runtime_information_ = GetRuntimeInformation(this->info_); + if (Logger::IsDebugEnabled()) { if (runtime_information_.is_desktop()) @@ -153,6 +154,7 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un if (runtime_information_.is_desktop() && IsNetFxAssemblyRedirectionEnabled()) { InitNetFxAssemblyRedirectsMap(); + DetectFrameworkVersionTableForRedirectsMap(); } #endif @@ -369,6 +371,11 @@ HRESULT STDMETHODCALLTYPE CorProfiler::AssemblyLoadFinished(AssemblyID assembly_ void CorProfiler::RedirectAssemblyReferences(const ComPtr& assembly_import, const ComPtr& assembly_emit) { + if (!assembly_version_redirect_map_current_framework_) + { + return; + } + HRESULT hr = S_FALSE; HCORENUM core_enum_handle = NULL; const ULONG assembly_refs_sz = 16; @@ -416,8 +423,8 @@ void CorProfiler::RedirectAssemblyReferences(const ComPtr(&releaseValue), &dataSize); + + RegCloseKey(hKey); + + if (result != ERROR_SUCCESS || valueType != REG_DWORD) + { + Logger::Warn( + "DetectFrameworkVersionTableForRedirectsMap: Failed to read Release value, using default version 462"); + } + else + { + + // Map release numbers to framework versions + // Based on Microsoft documentation: + // https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed + if (releaseValue >= 533320) + { + frameworkVersion = 481; // 4.8.1 + } + else if (releaseValue >= 528040) + { + frameworkVersion = 480; // 4.8 + } + else if (releaseValue >= 461808) + { + frameworkVersion = 472; // 4.7.2 + } + else if (releaseValue >= 461308) + { + frameworkVersion = 471; // 4.7.1 + } + else if (releaseValue >= 460798) + { + frameworkVersion = 470; // 4.7 + } + else if (releaseValue >= 394802) + { + frameworkVersion = 462; // 4.6.2 + } + else + { + Logger::Warn( + "DetectFrameworkVersionTableForRedirectsMap: Old .Net Framework detected, use 462 as fallback"); + } + } + + Logger::Debug("DetectFrameworkVersionTableForRedirectsMap: Detected .NET Framework version ", frameworkVersion, + " (Release: ", releaseValue, ")"); + } + + int selectedKey = 0; + for (auto& [key, values] : assembly_version_redirect_map_) + { + if (key <= frameworkVersion && key > selectedKey) + { + selectedKey = key; + assembly_version_redirect_map_current_framework_ = &values; + } + } + + if (selectedKey != 0) + { + Logger::Debug("DetectFrameworkVersionTableForRedirectsMap: Use assembly redirection table for ", selectedKey); + } + else + { + Logger::Warn("DetectFrameworkVersionTableForRedirectsMap: No assembly redirection tables found. Assembly " + "version redirecting will be disabled."); + } +} +#endif + } // namespace trace \ No newline at end of file diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h index 2b54636aff..fb00c47271 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h @@ -95,7 +95,8 @@ class CorProfiler : public CorProfilerBase // // Assembly redirect private members. // - std::unordered_map assembly_version_redirect_map_; + std::unordered_map> assembly_version_redirect_map_; + std::unordered_map* assembly_version_redirect_map_current_framework_; void InitNetFxAssemblyRedirectsMap(); void RedirectAssemblyReferences( const ComPtr& assembly_import, @@ -112,6 +113,7 @@ class CorProfiler : public CorProfilerBase mdMethodDef* patch_app_domain_setup_method); HRESULT ModifyAppDomainCreate(const ModuleID module_id, mdMethodDef patch_app_domain_setup_method); HRESULT AddIISPreStartInitFlags(const ModuleID module_id, const mdToken function_token); + void DetectFrameworkVersionTableForRedirectsMap(); #endif // diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h b/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h index 937da8851f..f7823a67ec 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h @@ -18,148 +18,404 @@ void CorProfiler::InitNetFxAssemblyRedirectsMap() const USHORT auto_major = atoi(AUTO_MAJOR); assembly_version_redirect_map_.insert({ - { L"Microsoft.Bcl.AsyncInterfaces", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Configuration", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Configuration.Abstractions", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Configuration.Binder", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.DependencyInjection", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.DependencyInjection.Abstractions", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Diagnostics.Abstractions", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Logging", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Logging.Abstractions", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Logging.Configuration", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Options", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Options.ConfigurationExtensions", {9, 0, 0, 8} }, - { L"Microsoft.Extensions.Primitives", {9, 0, 0, 8} }, - { L"Microsoft.Win32.Primitives", {4, 0, 3, 0} }, - { L"OpenTelemetry", {1, 0, 0, 0} }, - { L"OpenTelemetry.Api", {1, 0, 0, 0} }, - { L"OpenTelemetry.Api.ProviderBuilderExtensions", {1, 0, 0, 0} }, - { L"OpenTelemetry.AutoInstrumentation", {auto_major, 0, 0, 0} }, - { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, - { L"OpenTelemetry.Exporter.OpenTelemetryProtocol", {1, 0, 0, 0} }, - { L"OpenTelemetry.Exporter.Prometheus.HttpListener", {1, 0, 0, 0} }, - { L"OpenTelemetry.Exporter.Zipkin", {1, 0, 0, 0} }, - { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, - { L"OpenTelemetry.Instrumentation.AspNet", {1, 12, 0, 658} }, - { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 12, 0, 658} }, - { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 12, 0, 492} }, - { L"OpenTelemetry.Instrumentation.Http", {1, 12, 0, 493} }, - { L"OpenTelemetry.Instrumentation.Process", {1, 12, 0, 494} }, - { L"OpenTelemetry.Instrumentation.Quartz", {1, 12, 0, 495} }, - { L"OpenTelemetry.Instrumentation.Runtime", {1, 12, 0, 496} }, - { L"OpenTelemetry.Instrumentation.SqlClient", {1, 12, 0, 667} }, - { L"OpenTelemetry.Instrumentation.Wcf", {1, 12, 0, 500} }, - { L"OpenTelemetry.Resources.Azure", {1, 12, 0, 501} }, - { L"OpenTelemetry.Resources.Host", {1, 12, 0, 503} }, - { L"OpenTelemetry.Resources.OperatingSystem", {1, 12, 0, 504} }, - { L"OpenTelemetry.Resources.Process", {1, 12, 0, 505} }, - { L"OpenTelemetry.Resources.ProcessRuntime", {1, 12, 0, 506} }, - { L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} }, - { L"OpenTracing", {0, 12, 1, 0} }, - { L"System.AppContext", {4, 1, 2, 0} }, - { L"System.Buffers", {4, 0, 5, 0} }, - { L"System.Collections", {4, 0, 11, 0} }, - { L"System.Collections.Concurrent", {4, 0, 11, 0} }, - { L"System.Collections.NonGeneric", {4, 0, 3, 0} }, - { L"System.Collections.Specialized", {4, 0, 3, 0} }, - { L"System.ComponentModel", {4, 0, 1, 0} }, - { L"System.ComponentModel.EventBasedAsync", {4, 0, 11, 0} }, - { L"System.ComponentModel.Primitives", {4, 1, 2, 0} }, - { L"System.ComponentModel.TypeConverter", {4, 1, 2, 0} }, - { L"System.Console", {4, 0, 2, 0} }, - { L"System.Data.Common", {4, 2, 0, 0} }, - { L"System.Diagnostics.Contracts", {4, 0, 1, 0} }, - { L"System.Diagnostics.Debug", {4, 0, 11, 0} }, - { L"System.Diagnostics.DiagnosticSource", {9, 0, 0, 8} }, - { L"System.Diagnostics.FileVersionInfo", {4, 0, 2, 0} }, - { L"System.Diagnostics.Process", {4, 1, 2, 0} }, - { L"System.Diagnostics.StackTrace", {4, 1, 0, 0} }, - { L"System.Diagnostics.TextWriterTraceListener", {4, 0, 2, 0} }, - { L"System.Diagnostics.Tools", {4, 0, 1, 0} }, - { L"System.Diagnostics.TraceSource", {4, 0, 2, 0} }, - { L"System.Diagnostics.Tracing", {4, 2, 0, 0} }, - { L"System.Drawing.Primitives", {4, 0, 2, 0} }, - { L"System.Dynamic.Runtime", {4, 0, 11, 0} }, - { L"System.Globalization", {4, 0, 11, 0} }, - { L"System.Globalization.Calendars", {4, 0, 3, 0} }, - { L"System.Globalization.Extensions", {4, 1, 0, 0} }, - { L"System.IO", {4, 1, 2, 0} }, - { L"System.IO.Compression", {4, 2, 0, 0} }, - { L"System.IO.Compression.ZipFile", {4, 0, 3, 0} }, - { L"System.IO.FileSystem", {4, 0, 3, 0} }, - { L"System.IO.FileSystem.DriveInfo", {4, 0, 2, 0} }, - { L"System.IO.FileSystem.Primitives", {4, 0, 3, 0} }, - { L"System.IO.FileSystem.Watcher", {4, 0, 2, 0} }, - { L"System.IO.IsolatedStorage", {4, 0, 2, 0} }, - { L"System.IO.MemoryMappedFiles", {4, 0, 2, 0} }, - { L"System.IO.Pipelines", {9, 0, 0, 8} }, - { L"System.IO.Pipes", {4, 0, 2, 0} }, - { L"System.IO.UnmanagedMemoryStream", {4, 0, 3, 0} }, - { L"System.Linq", {4, 1, 2, 0} }, - { L"System.Linq.Expressions", {4, 1, 2, 0} }, - { L"System.Linq.Parallel", {4, 0, 1, 0} }, - { L"System.Linq.Queryable", {4, 0, 1, 0} }, - { L"System.Memory", {4, 0, 5, 0} }, - { L"System.Net.Http", {4, 2, 0, 0} }, - { L"System.Net.NameResolution", {4, 0, 2, 0} }, - { L"System.Net.NetworkInformation", {4, 1, 2, 0} }, - { L"System.Net.Ping", {4, 0, 2, 0} }, - { L"System.Net.Primitives", {4, 0, 11, 0} }, - { L"System.Net.Requests", {4, 0, 11, 0} }, - { L"System.Net.Security", {4, 0, 2, 0} }, - { L"System.Net.Sockets", {4, 2, 0, 0} }, - { L"System.Net.WebHeaderCollection", {4, 0, 1, 0} }, - { L"System.Net.WebSockets", {4, 0, 2, 0} }, - { L"System.Net.WebSockets.Client", {4, 0, 2, 0} }, - { L"System.Numerics.Vectors", {4, 1, 6, 0} }, - { L"System.ObjectModel", {4, 0, 11, 0} }, - { L"System.Reflection", {4, 1, 2, 0} }, - { L"System.Reflection.Extensions", {4, 0, 1, 0} }, - { L"System.Reflection.Primitives", {4, 0, 1, 0} }, - { L"System.Resources.Reader", {4, 0, 2, 0} }, - { L"System.Resources.ResourceManager", {4, 0, 1, 0} }, - { L"System.Resources.Writer", {4, 0, 2, 0} }, - { L"System.Runtime", {4, 1, 2, 0} }, - { L"System.Runtime.CompilerServices.Unsafe", {6, 0, 3, 0} }, - { L"System.Runtime.CompilerServices.VisualC", {4, 0, 2, 0} }, - { L"System.Runtime.Extensions", {4, 1, 2, 0} }, - { L"System.Runtime.Handles", {4, 0, 1, 0} }, - { L"System.Runtime.InteropServices", {4, 1, 2, 0} }, - { L"System.Runtime.InteropServices.RuntimeInformation", {4, 0, 2, 0} }, - { L"System.Runtime.Numerics", {4, 0, 1, 0} }, - { L"System.Runtime.Serialization.Formatters", {4, 0, 2, 0} }, - { L"System.Runtime.Serialization.Json", {4, 0, 1, 0} }, - { L"System.Runtime.Serialization.Primitives", {4, 2, 0, 0} }, - { L"System.Runtime.Serialization.Xml", {4, 1, 3, 0} }, - { L"System.Security.Claims", {4, 0, 3, 0} }, - { L"System.Security.Cryptography.Algorithms", {4, 3, 0, 0} }, - { L"System.Security.Cryptography.Csp", {4, 0, 2, 0} }, - { L"System.Security.Cryptography.Encoding", {4, 0, 2, 0} }, - { L"System.Security.Cryptography.Primitives", {4, 0, 2, 0} }, - { L"System.Security.Cryptography.X509Certificates", {4, 1, 2, 0} }, - { L"System.Security.Principal", {4, 0, 1, 0} }, - { L"System.Security.SecureString", {4, 1, 0, 0} }, - { L"System.Text.Encoding", {4, 0, 11, 0} }, - { L"System.Text.Encoding.Extensions", {4, 0, 11, 0} }, - { L"System.Text.Encodings.Web", {9, 0, 0, 8} }, - { L"System.Text.Json", {9, 0, 0, 8} }, - { L"System.Text.RegularExpressions", {4, 1, 1, 0} }, - { L"System.Threading", {4, 0, 11, 0} }, - { L"System.Threading.Overlapped", {4, 1, 0, 0} }, - { L"System.Threading.Tasks", {4, 0, 11, 0} }, - { L"System.Threading.Tasks.Extensions", {4, 2, 4, 0} }, - { L"System.Threading.Tasks.Parallel", {4, 0, 1, 0} }, - { L"System.Threading.Thread", {4, 0, 2, 0} }, - { L"System.Threading.ThreadPool", {4, 0, 12, 0} }, - { L"System.Threading.Timer", {4, 0, 1, 0} }, - { L"System.ValueTuple", {4, 0, 5, 0} }, - { L"System.Xml.ReaderWriter", {4, 1, 1, 0} }, - { L"System.Xml.XDocument", {4, 0, 11, 0} }, - { L"System.Xml.XmlDocument", {4, 0, 3, 0} }, - { L"System.Xml.XmlSerializer", {4, 0, 11, 0} }, - { L"System.Xml.XPath", {4, 0, 3, 0} }, - { L"System.Xml.XPath.XDocument", {4, 1, 0, 0} } + { 462, { + { L"Microsoft.Bcl.AsyncInterfaces", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Binder", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Diagnostics.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options.ConfigurationExtensions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Primitives", {9, 0, 0, 8} }, + { L"Microsoft.Win32.Primitives", {4, 0, 3, 0} }, + { L"OpenTelemetry", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api.ProviderBuilderExtensions", {1, 0, 0, 0} }, + { L"OpenTelemetry.AutoInstrumentation", {auto_major, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.OpenTelemetryProtocol", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Prometheus.HttpListener", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Zipkin", {1, 0, 0, 0} }, + { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.AspNet", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 12, 0, 492} }, + { L"OpenTelemetry.Instrumentation.Http", {1, 12, 0, 493} }, + { L"OpenTelemetry.Instrumentation.Process", {1, 12, 0, 494} }, + { L"OpenTelemetry.Instrumentation.Quartz", {1, 12, 0, 495} }, + { L"OpenTelemetry.Instrumentation.Runtime", {1, 12, 0, 496} }, + { L"OpenTelemetry.Instrumentation.SqlClient", {1, 12, 0, 667} }, + { L"OpenTelemetry.Instrumentation.Wcf", {1, 12, 0, 500} }, + { L"OpenTelemetry.Resources.Azure", {1, 12, 0, 501} }, + { L"OpenTelemetry.Resources.Host", {1, 12, 0, 503} }, + { L"OpenTelemetry.Resources.OperatingSystem", {1, 12, 0, 504} }, + { L"OpenTelemetry.Resources.Process", {1, 12, 0, 505} }, + { L"OpenTelemetry.Resources.ProcessRuntime", {1, 12, 0, 506} }, + { L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} }, + { L"OpenTracing", {0, 12, 1, 0} }, + { L"System.AppContext", {4, 1, 2, 0} }, + { L"System.Buffers", {4, 0, 5, 0} }, + { L"System.Collections", {4, 0, 11, 0} }, + { L"System.Collections.Concurrent", {4, 0, 11, 0} }, + { L"System.Collections.NonGeneric", {4, 0, 3, 0} }, + { L"System.Collections.Specialized", {4, 0, 3, 0} }, + { L"System.ComponentModel", {4, 0, 1, 0} }, + { L"System.ComponentModel.EventBasedAsync", {4, 0, 11, 0} }, + { L"System.ComponentModel.Primitives", {4, 1, 2, 0} }, + { L"System.ComponentModel.TypeConverter", {4, 1, 2, 0} }, + { L"System.Console", {4, 0, 2, 0} }, + { L"System.Data.Common", {4, 2, 0, 0} }, + { L"System.Diagnostics.Contracts", {4, 0, 1, 0} }, + { L"System.Diagnostics.Debug", {4, 0, 11, 0} }, + { L"System.Diagnostics.DiagnosticSource", {9, 0, 0, 8} }, + { L"System.Diagnostics.FileVersionInfo", {4, 0, 2, 0} }, + { L"System.Diagnostics.Process", {4, 1, 2, 0} }, + { L"System.Diagnostics.StackTrace", {4, 1, 0, 0} }, + { L"System.Diagnostics.TextWriterTraceListener", {4, 0, 2, 0} }, + { L"System.Diagnostics.Tools", {4, 0, 1, 0} }, + { L"System.Diagnostics.TraceSource", {4, 0, 2, 0} }, + { L"System.Diagnostics.Tracing", {4, 2, 0, 0} }, + { L"System.Drawing.Primitives", {4, 0, 2, 0} }, + { L"System.Dynamic.Runtime", {4, 0, 11, 0} }, + { L"System.Globalization", {4, 0, 11, 0} }, + { L"System.Globalization.Calendars", {4, 0, 3, 0} }, + { L"System.Globalization.Extensions", {4, 1, 0, 0} }, + { L"System.IO", {4, 1, 2, 0} }, + { L"System.IO.Compression", {4, 2, 0, 0} }, + { L"System.IO.Compression.ZipFile", {4, 0, 3, 0} }, + { L"System.IO.FileSystem", {4, 0, 3, 0} }, + { L"System.IO.FileSystem.DriveInfo", {4, 0, 2, 0} }, + { L"System.IO.FileSystem.Primitives", {4, 0, 3, 0} }, + { L"System.IO.FileSystem.Watcher", {4, 0, 2, 0} }, + { L"System.IO.IsolatedStorage", {4, 0, 2, 0} }, + { L"System.IO.MemoryMappedFiles", {4, 0, 2, 0} }, + { L"System.IO.Pipelines", {9, 0, 0, 8} }, + { L"System.IO.Pipes", {4, 0, 2, 0} }, + { L"System.IO.UnmanagedMemoryStream", {4, 0, 3, 0} }, + { L"System.Linq", {4, 1, 2, 0} }, + { L"System.Linq.Expressions", {4, 1, 2, 0} }, + { L"System.Linq.Parallel", {4, 0, 1, 0} }, + { L"System.Linq.Queryable", {4, 0, 1, 0} }, + { L"System.Memory", {4, 0, 5, 0} }, + { L"System.Net.Http", {4, 2, 0, 0} }, + { L"System.Net.NameResolution", {4, 0, 2, 0} }, + { L"System.Net.NetworkInformation", {4, 1, 2, 0} }, + { L"System.Net.Ping", {4, 0, 2, 0} }, + { L"System.Net.Primitives", {4, 0, 11, 0} }, + { L"System.Net.Requests", {4, 0, 11, 0} }, + { L"System.Net.Security", {4, 0, 2, 0} }, + { L"System.Net.Sockets", {4, 2, 0, 0} }, + { L"System.Net.WebHeaderCollection", {4, 0, 1, 0} }, + { L"System.Net.WebSockets", {4, 0, 2, 0} }, + { L"System.Net.WebSockets.Client", {4, 0, 2, 0} }, + { L"System.Numerics.Vectors", {4, 1, 6, 0} }, + { L"System.ObjectModel", {4, 0, 11, 0} }, + { L"System.Reflection", {4, 1, 2, 0} }, + { L"System.Reflection.Extensions", {4, 0, 1, 0} }, + { L"System.Reflection.Primitives", {4, 0, 1, 0} }, + { L"System.Resources.Reader", {4, 0, 2, 0} }, + { L"System.Resources.ResourceManager", {4, 0, 1, 0} }, + { L"System.Resources.Writer", {4, 0, 2, 0} }, + { L"System.Runtime", {4, 1, 2, 0} }, + { L"System.Runtime.CompilerServices.Unsafe", {6, 0, 3, 0} }, + { L"System.Runtime.CompilerServices.VisualC", {4, 0, 2, 0} }, + { L"System.Runtime.Extensions", {4, 1, 2, 0} }, + { L"System.Runtime.Handles", {4, 0, 1, 0} }, + { L"System.Runtime.InteropServices", {4, 1, 2, 0} }, + { L"System.Runtime.InteropServices.RuntimeInformation", {4, 0, 2, 0} }, + { L"System.Runtime.Numerics", {4, 0, 1, 0} }, + { L"System.Runtime.Serialization.Formatters", {4, 0, 2, 0} }, + { L"System.Runtime.Serialization.Json", {4, 0, 1, 0} }, + { L"System.Runtime.Serialization.Primitives", {4, 2, 0, 0} }, + { L"System.Runtime.Serialization.Xml", {4, 1, 3, 0} }, + { L"System.Security.Claims", {4, 0, 3, 0} }, + { L"System.Security.Cryptography.Algorithms", {4, 3, 0, 0} }, + { L"System.Security.Cryptography.Csp", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.Encoding", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.Primitives", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.X509Certificates", {4, 1, 2, 0} }, + { L"System.Security.Principal", {4, 0, 1, 0} }, + { L"System.Security.SecureString", {4, 1, 0, 0} }, + { L"System.Text.Encoding", {4, 0, 11, 0} }, + { L"System.Text.Encoding.Extensions", {4, 0, 11, 0} }, + { L"System.Text.Encodings.Web", {9, 0, 0, 8} }, + { L"System.Text.Json", {9, 0, 0, 8} }, + { L"System.Text.RegularExpressions", {4, 1, 1, 0} }, + { L"System.Threading", {4, 0, 11, 0} }, + { L"System.Threading.Overlapped", {4, 1, 0, 0} }, + { L"System.Threading.Tasks", {4, 0, 11, 0} }, + { L"System.Threading.Tasks.Extensions", {4, 2, 4, 0} }, + { L"System.Threading.Tasks.Parallel", {4, 0, 1, 0} }, + { L"System.Threading.Thread", {4, 0, 2, 0} }, + { L"System.Threading.ThreadPool", {4, 0, 12, 0} }, + { L"System.Threading.Timer", {4, 0, 1, 0} }, + { L"System.ValueTuple", {4, 0, 5, 0} }, + { L"System.Xml.ReaderWriter", {4, 1, 1, 0} }, + { L"System.Xml.XDocument", {4, 0, 11, 0} }, + { L"System.Xml.XmlDocument", {4, 0, 3, 0} }, + { L"System.Xml.XmlSerializer", {4, 0, 11, 0} }, + { L"System.Xml.XPath", {4, 0, 3, 0} }, + { L"System.Xml.XPath.XDocument", {4, 1, 0, 0} }, + }}, + { 470, { + { L"Microsoft.Bcl.AsyncInterfaces", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Binder", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Diagnostics.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options.ConfigurationExtensions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Primitives", {9, 0, 0, 8} }, + { L"Microsoft.Win32.Primitives", {4, 0, 3, 0} }, + { L"OpenTelemetry", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api.ProviderBuilderExtensions", {1, 0, 0, 0} }, + { L"OpenTelemetry.AutoInstrumentation", {auto_major, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.OpenTelemetryProtocol", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Prometheus.HttpListener", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Zipkin", {1, 0, 0, 0} }, + { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.AspNet", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 12, 0, 492} }, + { L"OpenTelemetry.Instrumentation.Http", {1, 12, 0, 493} }, + { L"OpenTelemetry.Instrumentation.Process", {1, 12, 0, 494} }, + { L"OpenTelemetry.Instrumentation.Quartz", {1, 12, 0, 495} }, + { L"OpenTelemetry.Instrumentation.Runtime", {1, 12, 0, 496} }, + { L"OpenTelemetry.Instrumentation.SqlClient", {1, 12, 0, 667} }, + { L"OpenTelemetry.Instrumentation.Wcf", {1, 12, 0, 500} }, + { L"OpenTelemetry.Resources.Azure", {1, 12, 0, 501} }, + { L"OpenTelemetry.Resources.Host", {1, 12, 0, 503} }, + { L"OpenTelemetry.Resources.OperatingSystem", {1, 12, 0, 504} }, + { L"OpenTelemetry.Resources.Process", {1, 12, 0, 505} }, + { L"OpenTelemetry.Resources.ProcessRuntime", {1, 12, 0, 506} }, + { L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} }, + { L"OpenTracing", {0, 12, 1, 0} }, + { L"System.AppContext", {4, 1, 2, 0} }, + { L"System.Buffers", {4, 0, 5, 0} }, + { L"System.Collections", {4, 0, 11, 0} }, + { L"System.Collections.Concurrent", {4, 0, 11, 0} }, + { L"System.Collections.NonGeneric", {4, 0, 3, 0} }, + { L"System.Collections.Specialized", {4, 0, 3, 0} }, + { L"System.ComponentModel", {4, 0, 1, 0} }, + { L"System.ComponentModel.EventBasedAsync", {4, 0, 11, 0} }, + { L"System.ComponentModel.Primitives", {4, 1, 2, 0} }, + { L"System.ComponentModel.TypeConverter", {4, 1, 2, 0} }, + { L"System.Console", {4, 0, 2, 0} }, + { L"System.Data.Common", {4, 2, 0, 0} }, + { L"System.Diagnostics.Contracts", {4, 0, 1, 0} }, + { L"System.Diagnostics.Debug", {4, 0, 11, 0} }, + { L"System.Diagnostics.DiagnosticSource", {9, 0, 0, 8} }, + { L"System.Diagnostics.FileVersionInfo", {4, 0, 2, 0} }, + { L"System.Diagnostics.Process", {4, 1, 2, 0} }, + { L"System.Diagnostics.StackTrace", {4, 1, 0, 0} }, + { L"System.Diagnostics.TextWriterTraceListener", {4, 0, 2, 0} }, + { L"System.Diagnostics.Tools", {4, 0, 1, 0} }, + { L"System.Diagnostics.TraceSource", {4, 0, 2, 0} }, + { L"System.Diagnostics.Tracing", {4, 2, 0, 0} }, + { L"System.Drawing.Primitives", {4, 0, 2, 0} }, + { L"System.Dynamic.Runtime", {4, 0, 11, 0} }, + { L"System.Globalization", {4, 0, 11, 0} }, + { L"System.Globalization.Calendars", {4, 0, 3, 0} }, + { L"System.Globalization.Extensions", {4, 1, 0, 0} }, + { L"System.IO", {4, 1, 2, 0} }, + { L"System.IO.Compression", {4, 2, 0, 0} }, + { L"System.IO.Compression.ZipFile", {4, 0, 3, 0} }, + { L"System.IO.FileSystem", {4, 0, 3, 0} }, + { L"System.IO.FileSystem.DriveInfo", {4, 0, 2, 0} }, + { L"System.IO.FileSystem.Primitives", {4, 0, 3, 0} }, + { L"System.IO.FileSystem.Watcher", {4, 0, 2, 0} }, + { L"System.IO.IsolatedStorage", {4, 0, 2, 0} }, + { L"System.IO.MemoryMappedFiles", {4, 0, 2, 0} }, + { L"System.IO.Pipelines", {9, 0, 0, 8} }, + { L"System.IO.Pipes", {4, 0, 2, 0} }, + { L"System.IO.UnmanagedMemoryStream", {4, 0, 3, 0} }, + { L"System.Linq", {4, 1, 2, 0} }, + { L"System.Linq.Expressions", {4, 1, 2, 0} }, + { L"System.Linq.Parallel", {4, 0, 1, 0} }, + { L"System.Linq.Queryable", {4, 0, 1, 0} }, + { L"System.Memory", {4, 0, 5, 0} }, + { L"System.Net.Http", {4, 2, 0, 0} }, + { L"System.Net.NameResolution", {4, 0, 2, 0} }, + { L"System.Net.NetworkInformation", {4, 1, 2, 0} }, + { L"System.Net.Ping", {4, 0, 2, 0} }, + { L"System.Net.Primitives", {4, 0, 11, 0} }, + { L"System.Net.Requests", {4, 0, 11, 0} }, + { L"System.Net.Security", {4, 0, 2, 0} }, + { L"System.Net.Sockets", {4, 2, 0, 0} }, + { L"System.Net.WebHeaderCollection", {4, 0, 1, 0} }, + { L"System.Net.WebSockets", {4, 0, 2, 0} }, + { L"System.Net.WebSockets.Client", {4, 0, 2, 0} }, + { L"System.Numerics.Vectors", {4, 1, 6, 0} }, + { L"System.ObjectModel", {4, 0, 11, 0} }, + { L"System.Reflection", {4, 1, 2, 0} }, + { L"System.Reflection.Extensions", {4, 0, 1, 0} }, + { L"System.Reflection.Primitives", {4, 0, 1, 0} }, + { L"System.Resources.Reader", {4, 0, 2, 0} }, + { L"System.Resources.ResourceManager", {4, 0, 1, 0} }, + { L"System.Resources.Writer", {4, 0, 2, 0} }, + { L"System.Runtime", {4, 1, 2, 0} }, + { L"System.Runtime.CompilerServices.Unsafe", {6, 0, 3, 0} }, + { L"System.Runtime.CompilerServices.VisualC", {4, 0, 2, 0} }, + { L"System.Runtime.Extensions", {4, 1, 2, 0} }, + { L"System.Runtime.Handles", {4, 0, 1, 0} }, + { L"System.Runtime.InteropServices", {4, 1, 2, 0} }, + { L"System.Runtime.InteropServices.RuntimeInformation", {4, 0, 2, 0} }, + { L"System.Runtime.Numerics", {4, 0, 1, 0} }, + { L"System.Runtime.Serialization.Formatters", {4, 0, 2, 0} }, + { L"System.Runtime.Serialization.Json", {4, 0, 1, 0} }, + { L"System.Runtime.Serialization.Primitives", {4, 2, 0, 0} }, + { L"System.Runtime.Serialization.Xml", {4, 1, 3, 0} }, + { L"System.Security.Claims", {4, 0, 3, 0} }, + { L"System.Security.Cryptography.Algorithms", {4, 3, 0, 0} }, + { L"System.Security.Cryptography.Csp", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.Encoding", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.Primitives", {4, 0, 2, 0} }, + { L"System.Security.Cryptography.X509Certificates", {4, 1, 2, 0} }, + { L"System.Security.Principal", {4, 0, 1, 0} }, + { L"System.Security.SecureString", {4, 1, 0, 0} }, + { L"System.Text.Encoding", {4, 0, 11, 0} }, + { L"System.Text.Encoding.Extensions", {4, 0, 11, 0} }, + { L"System.Text.Encodings.Web", {9, 0, 0, 8} }, + { L"System.Text.Json", {9, 0, 0, 8} }, + { L"System.Text.RegularExpressions", {4, 1, 1, 0} }, + { L"System.Threading", {4, 0, 11, 0} }, + { L"System.Threading.Overlapped", {4, 1, 0, 0} }, + { L"System.Threading.Tasks", {4, 0, 11, 0} }, + { L"System.Threading.Tasks.Extensions", {4, 2, 4, 0} }, + { L"System.Threading.Tasks.Parallel", {4, 0, 1, 0} }, + { L"System.Threading.Thread", {4, 0, 2, 0} }, + { L"System.Threading.ThreadPool", {4, 0, 12, 0} }, + { L"System.Threading.Timer", {4, 0, 1, 0} }, + { L"System.ValueTuple", {4, 0, 5, 0} }, + { L"System.Xml.ReaderWriter", {4, 1, 1, 0} }, + { L"System.Xml.XDocument", {4, 0, 11, 0} }, + { L"System.Xml.XmlDocument", {4, 0, 3, 0} }, + { L"System.Xml.XmlSerializer", {4, 0, 11, 0} }, + { L"System.Xml.XPath", {4, 0, 3, 0} }, + { L"System.Xml.XPath.XDocument", {4, 1, 0, 0} }, + }}, + { 471, { + { L"Microsoft.Bcl.AsyncInterfaces", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Binder", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Diagnostics.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options.ConfigurationExtensions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Primitives", {9, 0, 0, 8} }, + { L"OpenTelemetry", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api.ProviderBuilderExtensions", {1, 0, 0, 0} }, + { L"OpenTelemetry.AutoInstrumentation", {auto_major, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.OpenTelemetryProtocol", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Prometheus.HttpListener", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Zipkin", {1, 0, 0, 0} }, + { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.AspNet", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 12, 0, 492} }, + { L"OpenTelemetry.Instrumentation.Http", {1, 12, 0, 493} }, + { L"OpenTelemetry.Instrumentation.Process", {1, 12, 0, 494} }, + { L"OpenTelemetry.Instrumentation.Quartz", {1, 12, 0, 495} }, + { L"OpenTelemetry.Instrumentation.Runtime", {1, 12, 0, 496} }, + { L"OpenTelemetry.Instrumentation.SqlClient", {1, 12, 0, 667} }, + { L"OpenTelemetry.Instrumentation.Wcf", {1, 12, 0, 500} }, + { L"OpenTelemetry.Resources.Azure", {1, 12, 0, 501} }, + { L"OpenTelemetry.Resources.Host", {1, 12, 0, 503} }, + { L"OpenTelemetry.Resources.OperatingSystem", {1, 12, 0, 504} }, + { L"OpenTelemetry.Resources.Process", {1, 12, 0, 505} }, + { L"OpenTelemetry.Resources.ProcessRuntime", {1, 12, 0, 506} }, + { L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} }, + { L"OpenTracing", {0, 12, 1, 0} }, + { L"System.Buffers", {4, 0, 5, 0} }, + { L"System.Data.Common", {4, 2, 0, 0} }, + { L"System.Diagnostics.DiagnosticSource", {9, 0, 0, 8} }, + { L"System.Diagnostics.StackTrace", {4, 1, 0, 0} }, + { L"System.Diagnostics.Tracing", {4, 2, 0, 0} }, + { L"System.Globalization.Extensions", {4, 1, 0, 0} }, + { L"System.IO.Compression", {4, 2, 0, 0} }, + { L"System.IO.Pipelines", {9, 0, 0, 8} }, + { L"System.Memory", {4, 0, 5, 0} }, + { L"System.Net.Http", {4, 2, 0, 0} }, + { L"System.Net.Sockets", {4, 2, 0, 0} }, + { L"System.Numerics.Vectors", {4, 1, 6, 0} }, + { L"System.Runtime.CompilerServices.Unsafe", {6, 0, 3, 0} }, + { L"System.Runtime.Serialization.Primitives", {4, 2, 0, 0} }, + { L"System.Security.Cryptography.Algorithms", {4, 3, 0, 0} }, + { L"System.Security.SecureString", {4, 1, 0, 0} }, + { L"System.Text.Encodings.Web", {9, 0, 0, 8} }, + { L"System.Text.Json", {9, 0, 0, 8} }, + { L"System.Threading.Overlapped", {4, 1, 0, 0} }, + { L"System.Threading.Tasks.Extensions", {4, 2, 4, 0} }, + { L"System.Xml.XPath.XDocument", {4, 1, 0, 0} }, + }}, + { 472, { + { L"Microsoft.Bcl.AsyncInterfaces", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Configuration.Binder", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.DependencyInjection.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Diagnostics.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Abstractions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Logging.Configuration", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Options.ConfigurationExtensions", {9, 0, 0, 8} }, + { L"Microsoft.Extensions.Primitives", {9, 0, 0, 8} }, + { L"OpenTelemetry", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api.ProviderBuilderExtensions", {1, 0, 0, 0} }, + { L"OpenTelemetry.AutoInstrumentation", {auto_major, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.OpenTelemetryProtocol", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Prometheus.HttpListener", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Zipkin", {1, 0, 0, 0} }, + { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.AspNet", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 12, 0, 658} }, + { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 12, 0, 492} }, + { L"OpenTelemetry.Instrumentation.Http", {1, 12, 0, 493} }, + { L"OpenTelemetry.Instrumentation.Process", {1, 12, 0, 494} }, + { L"OpenTelemetry.Instrumentation.Quartz", {1, 12, 0, 495} }, + { L"OpenTelemetry.Instrumentation.Runtime", {1, 12, 0, 496} }, + { L"OpenTelemetry.Instrumentation.SqlClient", {1, 12, 0, 667} }, + { L"OpenTelemetry.Instrumentation.Wcf", {1, 12, 0, 500} }, + { L"OpenTelemetry.Resources.Azure", {1, 12, 0, 501} }, + { L"OpenTelemetry.Resources.Host", {1, 12, 0, 503} }, + { L"OpenTelemetry.Resources.OperatingSystem", {1, 12, 0, 504} }, + { L"OpenTelemetry.Resources.Process", {1, 12, 0, 505} }, + { L"OpenTelemetry.Resources.ProcessRuntime", {1, 12, 0, 506} }, + { L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} }, + { L"OpenTracing", {0, 12, 1, 0} }, + { L"System.Buffers", {4, 0, 5, 0} }, + { L"System.Diagnostics.DiagnosticSource", {9, 0, 0, 8} }, + { L"System.IO.Pipelines", {9, 0, 0, 8} }, + { L"System.Memory", {4, 0, 5, 0} }, + { L"System.Numerics.Vectors", {4, 1, 6, 0} }, + { L"System.Runtime.CompilerServices.Unsafe", {6, 0, 3, 0} }, + { L"System.Text.Encodings.Web", {9, 0, 0, 8} }, + { L"System.Text.Json", {9, 0, 0, 8} }, + { L"System.Threading.Tasks.Extensions", {4, 2, 4, 0} }, + }} }); } } diff --git a/src/OpenTelemetry.AutoInstrumentation/OpenTelemetry.AutoInstrumentation.csproj b/src/OpenTelemetry.AutoInstrumentation/OpenTelemetry.AutoInstrumentation.csproj index 11b865a9c1..79ad3521ce 100644 --- a/src/OpenTelemetry.AutoInstrumentation/OpenTelemetry.AutoInstrumentation.csproj +++ b/src/OpenTelemetry.AutoInstrumentation/OpenTelemetry.AutoInstrumentation.csproj @@ -8,6 +8,7 @@ true Generated $(GeneratedFolder)\$(TargetFramework) + false @@ -58,34 +59,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/IntegrationTests/BuildTests.DistributionStructure_windows.verified.txt b/test/IntegrationTests/BuildTests.DistributionStructure_windows.verified.txt index 4cec95c98b..b44dd7222f 100644 --- a/test/IntegrationTests/BuildTests.DistributionStructure_windows.verified.txt +++ b/test/IntegrationTests/BuildTests.DistributionStructure_windows.verified.txt @@ -56,7 +56,6 @@ \netfx\Microsoft.Extensions.Options.ConfigurationExtensions.dll, \netfx\Microsoft.Extensions.Options.dll, \netfx\Microsoft.Extensions.Primitives.dll, - \netfx\Microsoft.Win32.Primitives.dll, \netfx\OpenTelemetry.Api.ProviderBuilderExtensions.dll, \netfx\OpenTelemetry.Api.dll, \netfx\OpenTelemetry.AutoInstrumentation.dll, @@ -83,110 +82,220 @@ \netfx\OpenTelemetry.Shims.OpenTracing.dll, \netfx\OpenTelemetry.dll, \netfx\OpenTracing.dll, - \netfx\System.AppContext.dll, \netfx\System.Buffers.dll, - \netfx\System.Collections.Concurrent.dll, - \netfx\System.Collections.NonGeneric.dll, - \netfx\System.Collections.Specialized.dll, - \netfx\System.Collections.dll, - \netfx\System.ComponentModel.EventBasedAsync.dll, - \netfx\System.ComponentModel.Primitives.dll, - \netfx\System.ComponentModel.TypeConverter.dll, - \netfx\System.ComponentModel.dll, - \netfx\System.Console.dll, - \netfx\System.Data.Common.dll, - \netfx\System.Diagnostics.Contracts.dll, - \netfx\System.Diagnostics.Debug.dll, \netfx\System.Diagnostics.DiagnosticSource.dll, - \netfx\System.Diagnostics.FileVersionInfo.dll, - \netfx\System.Diagnostics.Process.dll, - \netfx\System.Diagnostics.StackTrace.dll, - \netfx\System.Diagnostics.TextWriterTraceListener.dll, - \netfx\System.Diagnostics.Tools.dll, - \netfx\System.Diagnostics.TraceSource.dll, - \netfx\System.Diagnostics.Tracing.dll, - \netfx\System.Drawing.Primitives.dll, - \netfx\System.Dynamic.Runtime.dll, - \netfx\System.Globalization.Calendars.dll, - \netfx\System.Globalization.Extensions.dll, - \netfx\System.Globalization.dll, - \netfx\System.IO.Compression.ZipFile.dll, - \netfx\System.IO.Compression.dll, - \netfx\System.IO.FileSystem.DriveInfo.dll, - \netfx\System.IO.FileSystem.Primitives.dll, - \netfx\System.IO.FileSystem.Watcher.dll, - \netfx\System.IO.FileSystem.dll, - \netfx\System.IO.IsolatedStorage.dll, - \netfx\System.IO.MemoryMappedFiles.dll, \netfx\System.IO.Pipelines.dll, - \netfx\System.IO.Pipes.dll, - \netfx\System.IO.UnmanagedMemoryStream.dll, - \netfx\System.IO.dll, - \netfx\System.Linq.Expressions.dll, - \netfx\System.Linq.Parallel.dll, - \netfx\System.Linq.Queryable.dll, - \netfx\System.Linq.dll, \netfx\System.Memory.dll, - \netfx\System.Net.Http.dll, - \netfx\System.Net.NameResolution.dll, - \netfx\System.Net.NetworkInformation.dll, - \netfx\System.Net.Ping.dll, - \netfx\System.Net.Primitives.dll, - \netfx\System.Net.Requests.dll, - \netfx\System.Net.Security.dll, - \netfx\System.Net.Sockets.dll, - \netfx\System.Net.WebHeaderCollection.dll, - \netfx\System.Net.WebSockets.Client.dll, - \netfx\System.Net.WebSockets.dll, \netfx\System.Numerics.Vectors.dll, - \netfx\System.ObjectModel.dll, - \netfx\System.Reflection.Extensions.dll, - \netfx\System.Reflection.Primitives.dll, - \netfx\System.Reflection.dll, - \netfx\System.Resources.Reader.dll, - \netfx\System.Resources.ResourceManager.dll, - \netfx\System.Resources.Writer.dll, \netfx\System.Runtime.CompilerServices.Unsafe.dll, - \netfx\System.Runtime.CompilerServices.VisualC.dll, - \netfx\System.Runtime.Extensions.dll, - \netfx\System.Runtime.Handles.dll, - \netfx\System.Runtime.InteropServices.RuntimeInformation.dll, - \netfx\System.Runtime.InteropServices.dll, - \netfx\System.Runtime.Numerics.dll, - \netfx\System.Runtime.Serialization.Formatters.dll, - \netfx\System.Runtime.Serialization.Json.dll, - \netfx\System.Runtime.Serialization.Primitives.dll, - \netfx\System.Runtime.Serialization.Xml.dll, - \netfx\System.Runtime.dll, - \netfx\System.Security.Claims.dll, - \netfx\System.Security.Cryptography.Algorithms.dll, - \netfx\System.Security.Cryptography.Csp.dll, - \netfx\System.Security.Cryptography.Encoding.dll, - \netfx\System.Security.Cryptography.Primitives.dll, - \netfx\System.Security.Cryptography.X509Certificates.dll, - \netfx\System.Security.Principal.dll, - \netfx\System.Security.SecureString.dll, - \netfx\System.Text.Encoding.Extensions.dll, - \netfx\System.Text.Encoding.dll, \netfx\System.Text.Encodings.Web.dll, \netfx\System.Text.Json.dll, - \netfx\System.Text.RegularExpressions.dll, - \netfx\System.Threading.Overlapped.dll, \netfx\System.Threading.Tasks.Extensions.dll, - \netfx\System.Threading.Tasks.Parallel.dll, - \netfx\System.Threading.Tasks.dll, - \netfx\System.Threading.Thread.dll, - \netfx\System.Threading.ThreadPool.dll, - \netfx\System.Threading.Timer.dll, - \netfx\System.Threading.dll, - \netfx\System.ValueTuple.dll, - \netfx\System.Xml.ReaderWriter.dll, - \netfx\System.Xml.XDocument.dll, - \netfx\System.Xml.XPath.XDocument.dll, - \netfx\System.Xml.XPath.dll, - \netfx\System.Xml.XmlDocument.dll, - \netfx\System.Xml.XmlSerializer.dll, - \netfx\netstandard.dll, + \netfx\net462\Microsoft.Win32.Primitives.dll, + \netfx\net462\System.AppContext.dll, + \netfx\net462\System.Collections.Concurrent.dll, + \netfx\net462\System.Collections.NonGeneric.dll, + \netfx\net462\System.Collections.Specialized.dll, + \netfx\net462\System.Collections.dll, + \netfx\net462\System.ComponentModel.EventBasedAsync.dll, + \netfx\net462\System.ComponentModel.Primitives.dll, + \netfx\net462\System.ComponentModel.TypeConverter.dll, + \netfx\net462\System.ComponentModel.dll, + \netfx\net462\System.Console.dll, + \netfx\net462\System.Data.Common.dll, + \netfx\net462\System.Diagnostics.Contracts.dll, + \netfx\net462\System.Diagnostics.Debug.dll, + \netfx\net462\System.Diagnostics.FileVersionInfo.dll, + \netfx\net462\System.Diagnostics.Process.dll, + \netfx\net462\System.Diagnostics.StackTrace.dll, + \netfx\net462\System.Diagnostics.TextWriterTraceListener.dll, + \netfx\net462\System.Diagnostics.Tools.dll, + \netfx\net462\System.Diagnostics.TraceSource.dll, + \netfx\net462\System.Diagnostics.Tracing.dll, + \netfx\net462\System.Drawing.Primitives.dll, + \netfx\net462\System.Dynamic.Runtime.dll, + \netfx\net462\System.Globalization.Calendars.dll, + \netfx\net462\System.Globalization.Extensions.dll, + \netfx\net462\System.Globalization.dll, + \netfx\net462\System.IO.Compression.ZipFile.dll, + \netfx\net462\System.IO.Compression.dll, + \netfx\net462\System.IO.FileSystem.DriveInfo.dll, + \netfx\net462\System.IO.FileSystem.Primitives.dll, + \netfx\net462\System.IO.FileSystem.Watcher.dll, + \netfx\net462\System.IO.FileSystem.dll, + \netfx\net462\System.IO.IsolatedStorage.dll, + \netfx\net462\System.IO.MemoryMappedFiles.dll, + \netfx\net462\System.IO.Pipes.dll, + \netfx\net462\System.IO.UnmanagedMemoryStream.dll, + \netfx\net462\System.IO.dll, + \netfx\net462\System.Linq.Expressions.dll, + \netfx\net462\System.Linq.Parallel.dll, + \netfx\net462\System.Linq.Queryable.dll, + \netfx\net462\System.Linq.dll, + \netfx\net462\System.Net.Http.dll, + \netfx\net462\System.Net.NameResolution.dll, + \netfx\net462\System.Net.NetworkInformation.dll, + \netfx\net462\System.Net.Ping.dll, + \netfx\net462\System.Net.Primitives.dll, + \netfx\net462\System.Net.Requests.dll, + \netfx\net462\System.Net.Security.dll, + \netfx\net462\System.Net.Sockets.dll, + \netfx\net462\System.Net.WebHeaderCollection.dll, + \netfx\net462\System.Net.WebSockets.Client.dll, + \netfx\net462\System.Net.WebSockets.dll, + \netfx\net462\System.ObjectModel.dll, + \netfx\net462\System.Reflection.Extensions.dll, + \netfx\net462\System.Reflection.Primitives.dll, + \netfx\net462\System.Reflection.dll, + \netfx\net462\System.Resources.Reader.dll, + \netfx\net462\System.Resources.ResourceManager.dll, + \netfx\net462\System.Resources.Writer.dll, + \netfx\net462\System.Runtime.CompilerServices.VisualC.dll, + \netfx\net462\System.Runtime.Extensions.dll, + \netfx\net462\System.Runtime.Handles.dll, + \netfx\net462\System.Runtime.InteropServices.RuntimeInformation.dll, + \netfx\net462\System.Runtime.InteropServices.dll, + \netfx\net462\System.Runtime.Numerics.dll, + \netfx\net462\System.Runtime.Serialization.Formatters.dll, + \netfx\net462\System.Runtime.Serialization.Json.dll, + \netfx\net462\System.Runtime.Serialization.Primitives.dll, + \netfx\net462\System.Runtime.Serialization.Xml.dll, + \netfx\net462\System.Runtime.dll, + \netfx\net462\System.Security.Claims.dll, + \netfx\net462\System.Security.Cryptography.Algorithms.dll, + \netfx\net462\System.Security.Cryptography.Csp.dll, + \netfx\net462\System.Security.Cryptography.Encoding.dll, + \netfx\net462\System.Security.Cryptography.Primitives.dll, + \netfx\net462\System.Security.Cryptography.X509Certificates.dll, + \netfx\net462\System.Security.Principal.dll, + \netfx\net462\System.Security.SecureString.dll, + \netfx\net462\System.Text.Encoding.Extensions.dll, + \netfx\net462\System.Text.Encoding.dll, + \netfx\net462\System.Text.RegularExpressions.dll, + \netfx\net462\System.Threading.Overlapped.dll, + \netfx\net462\System.Threading.Tasks.Parallel.dll, + \netfx\net462\System.Threading.Tasks.dll, + \netfx\net462\System.Threading.Thread.dll, + \netfx\net462\System.Threading.ThreadPool.dll, + \netfx\net462\System.Threading.Timer.dll, + \netfx\net462\System.Threading.dll, + \netfx\net462\System.ValueTuple.dll, + \netfx\net462\System.Xml.ReaderWriter.dll, + \netfx\net462\System.Xml.XDocument.dll, + \netfx\net462\System.Xml.XPath.XDocument.dll, + \netfx\net462\System.Xml.XPath.dll, + \netfx\net462\System.Xml.XmlDocument.dll, + \netfx\net462\System.Xml.XmlSerializer.dll, + \netfx\net462\netstandard.dll, + \netfx\net471\System.Data.Common.dll, + \netfx\net471\System.Diagnostics.StackTrace.dll, + \netfx\net471\System.Diagnostics.Tracing.dll, + \netfx\net471\System.Globalization.Extensions.dll, + \netfx\net471\System.IO.Compression.dll, + \netfx\net471\System.Net.Http.dll, + \netfx\net471\System.Net.Sockets.dll, + \netfx\net471\System.Runtime.Serialization.Primitives.dll, + \netfx\net471\System.Security.Cryptography.Algorithms.dll, + \netfx\net471\System.Security.SecureString.dll, + \netfx\net471\System.Threading.Overlapped.dll, + \netfx\net471\System.Xml.XPath.XDocument.dll, + \netfx\net472\_._, + \netfx\net47\Microsoft.Win32.Primitives.dll.link, + \netfx\net47\System.AppContext.dll.link, + \netfx\net47\System.Collections.Concurrent.dll.link, + \netfx\net47\System.Collections.NonGeneric.dll.link, + \netfx\net47\System.Collections.Specialized.dll.link, + \netfx\net47\System.Collections.dll.link, + \netfx\net47\System.ComponentModel.EventBasedAsync.dll.link, + \netfx\net47\System.ComponentModel.Primitives.dll.link, + \netfx\net47\System.ComponentModel.TypeConverter.dll.link, + \netfx\net47\System.ComponentModel.dll.link, + \netfx\net47\System.Console.dll.link, + \netfx\net47\System.Data.Common.dll.link, + \netfx\net47\System.Diagnostics.Contracts.dll.link, + \netfx\net47\System.Diagnostics.Debug.dll.link, + \netfx\net47\System.Diagnostics.FileVersionInfo.dll.link, + \netfx\net47\System.Diagnostics.Process.dll.link, + \netfx\net47\System.Diagnostics.StackTrace.dll.link, + \netfx\net47\System.Diagnostics.TextWriterTraceListener.dll.link, + \netfx\net47\System.Diagnostics.Tools.dll.link, + \netfx\net47\System.Diagnostics.TraceSource.dll.link, + \netfx\net47\System.Diagnostics.Tracing.dll.link, + \netfx\net47\System.Drawing.Primitives.dll.link, + \netfx\net47\System.Dynamic.Runtime.dll.link, + \netfx\net47\System.Globalization.Calendars.dll.link, + \netfx\net47\System.Globalization.Extensions.dll.link, + \netfx\net47\System.Globalization.dll.link, + \netfx\net47\System.IO.Compression.ZipFile.dll.link, + \netfx\net47\System.IO.Compression.dll.link, + \netfx\net47\System.IO.FileSystem.DriveInfo.dll.link, + \netfx\net47\System.IO.FileSystem.Primitives.dll.link, + \netfx\net47\System.IO.FileSystem.Watcher.dll.link, + \netfx\net47\System.IO.FileSystem.dll.link, + \netfx\net47\System.IO.IsolatedStorage.dll.link, + \netfx\net47\System.IO.MemoryMappedFiles.dll.link, + \netfx\net47\System.IO.Pipes.dll.link, + \netfx\net47\System.IO.UnmanagedMemoryStream.dll.link, + \netfx\net47\System.IO.dll.link, + \netfx\net47\System.Linq.Expressions.dll.link, + \netfx\net47\System.Linq.Parallel.dll.link, + \netfx\net47\System.Linq.Queryable.dll.link, + \netfx\net47\System.Linq.dll.link, + \netfx\net47\System.Net.Http.dll.link, + \netfx\net47\System.Net.NameResolution.dll.link, + \netfx\net47\System.Net.NetworkInformation.dll.link, + \netfx\net47\System.Net.Ping.dll.link, + \netfx\net47\System.Net.Primitives.dll.link, + \netfx\net47\System.Net.Requests.dll.link, + \netfx\net47\System.Net.Security.dll.link, + \netfx\net47\System.Net.Sockets.dll.link, + \netfx\net47\System.Net.WebHeaderCollection.dll.link, + \netfx\net47\System.Net.WebSockets.Client.dll.link, + \netfx\net47\System.Net.WebSockets.dll.link, + \netfx\net47\System.ObjectModel.dll.link, + \netfx\net47\System.Reflection.Extensions.dll.link, + \netfx\net47\System.Reflection.Primitives.dll.link, + \netfx\net47\System.Reflection.dll.link, + \netfx\net47\System.Resources.Reader.dll.link, + \netfx\net47\System.Resources.ResourceManager.dll.link, + \netfx\net47\System.Resources.Writer.dll.link, + \netfx\net47\System.Runtime.CompilerServices.VisualC.dll.link, + \netfx\net47\System.Runtime.Extensions.dll.link, + \netfx\net47\System.Runtime.Handles.dll.link, + \netfx\net47\System.Runtime.InteropServices.RuntimeInformation.dll, + \netfx\net47\System.Runtime.InteropServices.dll.link, + \netfx\net47\System.Runtime.Numerics.dll.link, + \netfx\net47\System.Runtime.Serialization.Formatters.dll.link, + \netfx\net47\System.Runtime.Serialization.Json.dll.link, + \netfx\net47\System.Runtime.Serialization.Primitives.dll.link, + \netfx\net47\System.Runtime.Serialization.Xml.dll.link, + \netfx\net47\System.Runtime.dll.link, + \netfx\net47\System.Security.Claims.dll.link, + \netfx\net47\System.Security.Cryptography.Algorithms.dll, + \netfx\net47\System.Security.Cryptography.Csp.dll.link, + \netfx\net47\System.Security.Cryptography.Encoding.dll.link, + \netfx\net47\System.Security.Cryptography.Primitives.dll.link, + \netfx\net47\System.Security.Cryptography.X509Certificates.dll.link, + \netfx\net47\System.Security.Principal.dll.link, + \netfx\net47\System.Security.SecureString.dll.link, + \netfx\net47\System.Text.Encoding.Extensions.dll.link, + \netfx\net47\System.Text.Encoding.dll.link, + \netfx\net47\System.Text.RegularExpressions.dll.link, + \netfx\net47\System.Threading.Overlapped.dll.link, + \netfx\net47\System.Threading.Tasks.Parallel.dll.link, + \netfx\net47\System.Threading.Tasks.dll.link, + \netfx\net47\System.Threading.Thread.dll.link, + \netfx\net47\System.Threading.ThreadPool.dll.link, + \netfx\net47\System.Threading.Timer.dll.link, + \netfx\net47\System.Threading.dll.link, + \netfx\net47\System.ValueTuple.dll, + \netfx\net47\System.Xml.ReaderWriter.dll.link, + \netfx\net47\System.Xml.XDocument.dll.link, + \netfx\net47\System.Xml.XPath.XDocument.dll.link, + \netfx\net47\System.Xml.XPath.dll.link, + \netfx\net47\System.Xml.XmlDocument.dll.link, + \netfx\net47\System.Xml.XmlSerializer.dll.link, + \netfx\net47\netstandard.dll.link, \store\x64\net8.0\microsoft.extensions.configuration.abstractions\9.0.0\lib\net9.0\Microsoft.Extensions.Configuration.Abstractions.dll, \store\x64\net8.0\microsoft.extensions.configuration.binder\9.0.0\lib\net9.0\Microsoft.Extensions.Configuration.Binder.dll, \store\x64\net8.0\microsoft.extensions.configuration\9.0.0\lib\net9.0\Microsoft.Extensions.Configuration.dll, diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/NetFrameworkDistroTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/NetFrameworkDistroTests.cs new file mode 100644 index 0000000000..83bb6d7ab9 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/NetFrameworkDistroTests.cs @@ -0,0 +1,106 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// This test is defined in NET 9.0 because the tool is written in .NET 9.0 +// The actual test is testing .NET Framework context. +#if NET9_0_OR_GREATER + +using System.Reflection; +using System.Runtime.InteropServices; +using DependencyListGenerator; +using NuGet.Configuration; +using Xunit; +using Xunit.Abstractions; + +namespace OpenTelemetry.AutoInstrumentation.Tests; + +public class NetFrameworkDistroTests +{ + private readonly ITestOutputHelper _output; + + public NetFrameworkDistroTests(ITestOutputHelper output) + { + _output = output; + } + + [SkippableFact] + public void GeneratorDiscoversTransientDependencies() + { + Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Supported only on Windows."); + + var currentTestLocation = Assembly.GetExecutingAssembly().Location; + var testDir = FindParentDir(currentTestLocation, "test"); + var srcDir = Path.Combine(Directory.GetParent(testDir)!.FullName, "src"); + var codeDir = Path.Combine(srcDir, "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework"); + var projectPath = Path.Combine(codeDir, "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj"); + + var dependencies = Generator.EnumerateDependencies(projectPath); + + // Check that every TFM has System.Memory reference. We just selected one transient dependency to test. + Assert.True(dependencies.All(tfm => tfm.Value.Any(dep => dep.Name == "System.Memory"))); + } + + [SkippableFact] + public void ReferencedPackagesNoUnsupportedTfm() + { + Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Supported only on Windows."); + + var currentTestLocation = Assembly.GetExecutingAssembly().Location; + var testDir = FindParentDir(currentTestLocation, "test"); + var srcDir = Path.Combine(Directory.GetParent(testDir)!.FullName, "src"); + var codeDir = Path.Combine(srcDir, "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework"); + var projectPath = Path.Combine(codeDir, "OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework.csproj"); + + var dependencies = Generator.EnumerateDependencies(projectPath).SelectMany(tfm => tfm.Value).ToHashSet(); + + var packagesFolder = + SettingsUtility.GetGlobalPackagesFolder( + Settings.LoadDefaultSettings(root: codeDir)); + + string[] knownOldPrefix = ["net40", "net45", "net46", "net47"]; + List unexpectedFrameworkFolders = []; + foreach (var dependency in dependencies) + { + var packageFolder = Path.Combine(packagesFolder, dependency.Name, dependency.Version); + foreach (var folder in Directory.EnumerateDirectories(packageFolder, "net4*", SearchOption.AllDirectories)) + { + var tfm = Path.GetFileName(folder); + if (tfm.Contains(".")) + { + // .NET 40.x + continue; + } + + if (knownOldPrefix.Any(prefix => tfm.StartsWith(prefix))) + { + continue; + } + + var path = Path.GetRelativePath(packagesFolder, folder); + unexpectedFrameworkFolders.Add(path); + _output.WriteLine($"Unexpected TFM: {path}"); + } + } + + // We may need add new TFM in OpenTelemetry.AutoInstrumentation.Assemblies.NetFramework + // (and build infrastructure, readme) if referenced dependencies has a custom build for that TFM. + Assert.Empty(unexpectedFrameworkFolders); + } + + private static string FindParentDir(string location, string parentName) + { + var parent = Directory.GetParent(location); + if (parent == null) + { + throw new InvalidOperationException("Could not find parent test directory"); + } + + if (parent.Name == parentName) + { + return parent.FullName; + } + + return FindParentDir(parent.FullName, parentName); + } +} +#endif diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/TransientDependenciesTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/TransientDependenciesTests.cs deleted file mode 100644 index d66d9c7496..0000000000 --- a/test/OpenTelemetry.AutoInstrumentation.Tests/TransientDependenciesTests.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// This test is defined in NET 9.0 because the tool is written in .NET 9.0 -// The actual test is testing .NET Framework 4.6.2 context. -#if NET9_0_OR_GREATER - -using System.Reflection; -using System.Runtime.InteropServices; -using System.Xml.Linq; -using DependencyListGenerator; -using Xunit; - -namespace OpenTelemetry.AutoInstrumentation.Tests; - -public class TransientDependenciesTests -{ - [SkippableFact] - public void DefinedTransientDeps_Are_MatchingGeneratedDeps() - { - Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Supported only on Windows."); - - var currentTestLocation = Assembly.GetExecutingAssembly().Location; - var testDir = FindParentDir(currentTestLocation, "test"); - var srcDir = Path.Combine(Directory.GetParent(testDir)!.FullName, "src"); - var codeDir = Path.Combine(srcDir, "OpenTelemetry.AutoInstrumentation"); - var projectPath = Path.Combine(codeDir, "OpenTelemetry.AutoInstrumentation.csproj"); - var projectGenPath = Path.Combine(codeDir, "OpenTelemetry.AutoInstrumentation.g.csproj"); - - File.Copy(projectPath, projectGenPath, overwrite: true); - - var deps = ReadTransientDeps(projectGenPath); - - CleanTransientDeps(projectGenPath); - - var generatedDeps = Generator - .EnumerateDependencies(projectGenPath) - .Select(x => x.Name) - .ToList(); - - // TODO automate detecting new transitive dependencies https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/3817 - generatedDeps.Add("System.IO.Pipelines"); - - File.Delete(projectGenPath); - - Assert.Equal(generatedDeps.Count, deps.Count); - Assert.Equivalent(generatedDeps, deps); - } - - private static XElement? GetTransientDepsGroup(XElement projXml) - { - const string label = "Transient dependencies auto-generated by GenerateNetFxTransientDependencies"; - - return projXml - .Elements("ItemGroup") - .FirstOrDefault(x => - x.HasAttributes && - x.Attribute("Label")?.Value == label); - } - - private static void CleanTransientDeps(string projPath) - { - var projXml = XElement.Load(projPath); - var depsGroup = GetTransientDepsGroup(projXml); - if (depsGroup != null) - { - depsGroup.Remove(); - } - - projXml.Save(projPath); - } - - private static ICollection ReadTransientDeps(string projPath) - { - var projXml = XElement.Load(projPath); - var depsGroup = GetTransientDepsGroup(projXml); - if (depsGroup == null) - { - return Array.Empty(); - } - - return depsGroup - .Descendants("PackageReference") - .Where(x => x.HasAttributes && x.Attribute("Include") != null) - .Select(x => x.Attribute("Include")!.Value) - .ToList(); - } - - private static string FindParentDir(string location, string parentName) - { - var parent = Directory.GetParent(location); - if (parent == null) - { - throw new InvalidOperationException("Could not find parent test directory"); - } - - if (parent.Name == parentName) - { - return parent.FullName; - } - - return FindParentDir(parent.FullName, parentName); - } -} - -#endif diff --git a/tools/DependencyListGenerator/DotNetOutdated/Exceptions/CommandValidationException.cs b/tools/DependencyListGenerator/DotNetOutdated/Exceptions/CommandValidationException.cs deleted file mode 100644 index 1cf1db7b36..0000000000 --- a/tools/DependencyListGenerator/DotNetOutdated/Exceptions/CommandValidationException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace DependencyListGenerator.DotNetOutdated.Exceptions; - -public class CommandValidationException : Exception -{ - public CommandValidationException(string message) - : base(message) - { - } - - public CommandValidationException(string message, Exception innerException) - : base(message, innerException) - { - } -} diff --git a/tools/DependencyListGenerator/DotNetOutdated/Models/Dependency.cs b/tools/DependencyListGenerator/DotNetOutdated/Models/Dependency.cs index 0ef1944a95..dfc85cafc6 100644 --- a/tools/DependencyListGenerator/DotNetOutdated/Models/Dependency.cs +++ b/tools/DependencyListGenerator/DotNetOutdated/Models/Dependency.cs @@ -1,31 +1,10 @@ -using NuGet.Versioning; - namespace DependencyListGenerator.DotNetOutdated.Models; -public class Dependency +public class Dependency(string name, string resolvedVersion, bool isDevelopmentDependency) { - public Dependency(string name, VersionRange versionRange, NuGetVersion resolvedVersion, bool isAutoReferenced, bool isTransitive, bool isDevelopmentDependency, bool isVersionCentrallyManaged) - { - Name = name; - VersionRange = versionRange; - ResolvedVersion = resolvedVersion; - IsAutoReferenced = isAutoReferenced; - IsTransitive = isTransitive; - IsDevelopmentDependency = isDevelopmentDependency; - IsVersionCentrallyManaged = isVersionCentrallyManaged; - } - - public bool IsAutoReferenced { get; } - - public bool IsDevelopmentDependency { get; } - - public bool IsTransitive { get; } - - public bool IsVersionCentrallyManaged { get; } - - public string Name { get; } + public bool IsDevelopmentDependency { get; } = isDevelopmentDependency; - public NuGetVersion ResolvedVersion { get; } + public string Name { get; } = name; - public VersionRange VersionRange { get; } + public string ResolvedVersion { get; } = resolvedVersion; } diff --git a/tools/DependencyListGenerator/DotNetOutdated/Models/PackageListModel.cs b/tools/DependencyListGenerator/DotNetOutdated/Models/PackageListModel.cs new file mode 100644 index 0000000000..1510762cbc --- /dev/null +++ b/tools/DependencyListGenerator/DotNetOutdated/Models/PackageListModel.cs @@ -0,0 +1,51 @@ +namespace DependencyListGenerator.DotNetOutdated.Models; + +using System.Text.Json.Serialization; + +public record PackageListModel +{ + [JsonPropertyName("version")] + public int Version { get; init; } + + [JsonPropertyName("parameters")] + public string Parameters { get; init; } = string.Empty; + + [JsonPropertyName("projects")] + public ProjectInfo[] Projects { get; init; } = []; + + public record ProjectInfo + { + [JsonPropertyName("path")] + public string Path { get; init; } = string.Empty; + + [JsonPropertyName("frameworks")] + public FrameworkInfo[] Frameworks { get; init; } = []; + } + + public record FrameworkInfo + { + [JsonPropertyName("framework")] + public string Framework { get; init; } = string.Empty; + + [JsonPropertyName("topLevelPackages")] + public PackageReference[] TopLevelPackages { get; init; } = []; + + [JsonPropertyName("transitivePackages")] + public PackageReference[] TransitivePackages { get; init; } = []; + } + + public record PackageReference + { + [JsonPropertyName("id")] + public string Id { get; init; } = string.Empty; + + [JsonPropertyName("requestedVersion")] + public string RequestedVersion { get; init; } + + [JsonPropertyName("resolvedVersion")] + public string ResolvedVersion { get; init; } = string.Empty; + + [JsonPropertyName("latestVersion")] + public string LatestVersion { get; init; } + } +} diff --git a/tools/DependencyListGenerator/DotNetOutdated/Models/Project.cs b/tools/DependencyListGenerator/DotNetOutdated/Models/Project.cs index a2153795c1..a56f539f90 100644 --- a/tools/DependencyListGenerator/DotNetOutdated/Models/Project.cs +++ b/tools/DependencyListGenerator/DotNetOutdated/Models/Project.cs @@ -2,23 +2,9 @@ namespace DependencyListGenerator.DotNetOutdated.Models; -public class Project +public class Project(string filePath, IList targets) { - public Project(string name, string filePath, IEnumerable sources, NuGetVersion version) - { - FilePath = filePath; - Name = name; - Sources = new List(sources); - Version = version; - } + public string FilePath { get; } = filePath; - public string FilePath { get; } - - public string Name { get; } - - public IList Sources { get; } - - public IList TargetFrameworks { get; } = new List(); - - public NuGetVersion Version { get; } + public IList TargetFrameworks { get; } = targets; } diff --git a/tools/DependencyListGenerator/DotNetOutdated/Models/TargetFramework.cs b/tools/DependencyListGenerator/DotNetOutdated/Models/TargetFramework.cs index 88f6a5079e..6a3c4ab629 100644 --- a/tools/DependencyListGenerator/DotNetOutdated/Models/TargetFramework.cs +++ b/tools/DependencyListGenerator/DotNetOutdated/Models/TargetFramework.cs @@ -2,14 +2,9 @@ namespace DependencyListGenerator.DotNetOutdated.Models; -public class TargetFramework +public class TargetFramework(string name, IList dependencies) { - public TargetFramework(NuGetFramework name) - { - Name = name; - } + public IList Dependencies { get; } = dependencies; - public IList Dependencies { get; } = new List(); - - public NuGetFramework Name { get; set; } + public string Name { get; set; } = name; } diff --git a/tools/DependencyListGenerator/DotNetOutdated/Services/DependencyGraphService.cs b/tools/DependencyListGenerator/DotNetOutdated/Services/DependencyGraphService.cs deleted file mode 100644 index 94d6841811..0000000000 --- a/tools/DependencyListGenerator/DotNetOutdated/Services/DependencyGraphService.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.IO.Abstractions; -using DependencyListGenerator.DotNetOutdated.Exceptions; -using NuGet.ProjectModel; - -namespace DependencyListGenerator.DotNetOutdated.Services; - -/// -/// Credit for the stuff happening in here goes to the https://github.com/jaredcnance/dotnet-status project -/// -public class DependencyGraphService -{ - private readonly DotNetRunner _dotNetRunner; - private readonly IFileSystem _fileSystem; - - public DependencyGraphService(DotNetRunner dotNetRunner, IFileSystem fileSystem) - { - _dotNetRunner = dotNetRunner; - _fileSystem = fileSystem; - } - - public DependencyGraphSpec GenerateDependencyGraph(string projectPath) - { - var dgOutput = _fileSystem.Path.Combine(_fileSystem.Path.GetTempPath(), _fileSystem.Path.GetRandomFileName()); - - string[] arguments = { "msbuild", $"\"{projectPath}\"", "/t:Restore,GenerateRestoreGraphFile", $"/p:RestoreGraphOutputPath=\"{dgOutput}\"" }; - - var runStatus = _dotNetRunner.Run(_fileSystem.Path.GetDirectoryName(projectPath), arguments); - - if (runStatus.IsSuccess) - { - /* - TempDirectory is a hacky workaround for DependencyGraphSpec(JObject) - being deprecated. Unfortunately it looks like the only alternative - is to load the file locally. Which is ok normally, but complicates - testing. - */ - using (var tempDirectory = new TempDirectory()) - { - var dependencyGraphFilename = Path.Combine(tempDirectory.DirectoryPath, "DependencyGraph.json"); - var dependencyGraphText = _fileSystem.File.ReadAllText(dgOutput); - File.WriteAllText(dependencyGraphFilename, dependencyGraphText); - return DependencyGraphSpec.Load(dependencyGraphFilename); - } - } - - throw new CommandValidationException($"Unable to process the project `{projectPath}. Are you sure this is a valid .NET Core or .NET Standard project type?" + - $"{Environment.NewLine}{Environment.NewLine}Here is the full error message returned from the Microsoft Build Engine:{Environment.NewLine}{Environment.NewLine}{runStatus.Output} - {runStatus.Errors} - exit code: {runStatus.ExitCode}"); - } -} diff --git a/tools/DependencyListGenerator/DotNetOutdated/Services/DotNetPackageListService.cs b/tools/DependencyListGenerator/DotNetOutdated/Services/DotNetPackageListService.cs new file mode 100644 index 0000000000..c9fd95a2ed --- /dev/null +++ b/tools/DependencyListGenerator/DotNetOutdated/Services/DotNetPackageListService.cs @@ -0,0 +1,26 @@ +using System.IO.Abstractions; + +namespace DependencyListGenerator.DotNetOutdated.Services; + +public class DotNetPackageListService +{ + private readonly DotNetRunner _dotNetRunner; + private readonly IFileSystem _fileSystem; + + public DotNetPackageListService(DotNetRunner dotNetRunner, IFileSystem fileSystem) + { + _dotNetRunner = dotNetRunner; + _fileSystem = fileSystem; + } + + public RunStatus ListPackages(string projectPath) + { + string[] arguments = new[] + { + "list", $"\"{projectPath}\"", "package", "--include-transitive", "--format", "json", "--output-version", + "1" + }; + + return _dotNetRunner.Run(_fileSystem.Path.GetDirectoryName(projectPath), arguments); + } +} diff --git a/tools/DependencyListGenerator/DotNetOutdated/Services/ProjectAnalysisService.cs b/tools/DependencyListGenerator/DotNetOutdated/Services/ProjectAnalysisService.cs index ed282a36a7..02180f8a40 100644 --- a/tools/DependencyListGenerator/DotNetOutdated/Services/ProjectAnalysisService.cs +++ b/tools/DependencyListGenerator/DotNetOutdated/Services/ProjectAnalysisService.cs @@ -1,121 +1,76 @@ using System.IO.Abstractions; +using System.Text.Json; using DependencyListGenerator.DotNetOutdated.Models; using NuGet.Common; +using NuGet.Configuration; using NuGet.Packaging.Core; -using NuGet.ProjectModel; using NuGet.Protocol; +using NuGet.Versioning; namespace DependencyListGenerator.DotNetOutdated.Services; public class ProjectAnalysisService { - private readonly DependencyGraphService _dependencyGraphService; private readonly DotNetRestoreService _dotNetRestoreService; + private readonly DotNetPackageListService _packageListService; private readonly IFileSystem _fileSystem; - public ProjectAnalysisService(DependencyGraphService dependencyGraphService, DotNetRestoreService dotNetRestoreService, IFileSystem fileSystem) + public ProjectAnalysisService(DotNetRestoreService dotNetRestoreService, DotNetPackageListService packageListService, IFileSystem fileSystem) { - _dependencyGraphService = dependencyGraphService; _dotNetRestoreService = dotNetRestoreService; + _packageListService = packageListService; _fileSystem = fileSystem; } - public List AnalyzeProject(string projectPath, bool runRestore, bool includeTransitiveDependencies, int transitiveDepth) + public List AnalyzeProject(string projectPath, bool runRestore) { - var dependencyGraph = _dependencyGraphService.GenerateDependencyGraph(projectPath); - if (dependencyGraph == null) + if (runRestore) { - return null; + _dotNetRestoreService.Restore(projectPath); } - var projects = new List(); - foreach (var packageSpec in dependencyGraph.Projects.Where(p => p.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference)) - { - // Restore the packages - if (runRestore) - { - _dotNetRestoreService.Restore(packageSpec.FilePath); - } + var packagesFolder = + SettingsUtility.GetGlobalPackagesFolder( + Settings.LoadDefaultSettings(root: _fileSystem.Path.GetDirectoryName(projectPath))); - // Load the lock file - string lockFilePath = _fileSystem.Path.Combine(packageSpec.RestoreMetadata.OutputPath, "project.assets.json"); - var lockFile = LockFileUtilities.GetLockFile(lockFilePath, NullLogger.Instance); + var result = _packageListService.ListPackages(projectPath); + if (!result.IsSuccess) + { + return null; + } - // Create a project - var project = new Project(packageSpec.Name, packageSpec.FilePath, packageSpec.RestoreMetadata.Sources.Select(s => s.SourceUri).ToList(), packageSpec.Version); - projects.Add(project); + var packageListModel = JsonSerializer.Deserialize(result.Output); + var projects = new List(); + foreach (var modelProject in packageListModel.Projects) + { + var targets = new List(); // Get the target frameworks with their dependencies - foreach (var targetFrameworkInformation in packageSpec.TargetFrameworks) + foreach (var targetFrameworkInformation in modelProject.Frameworks) { - var targetFramework = new TargetFramework(targetFrameworkInformation.FrameworkName); - project.TargetFrameworks.Add(targetFramework); - - var target = lockFile.Targets.FirstOrDefault(t => t.TargetFramework.Equals(targetFrameworkInformation.FrameworkName)); - - if (target != null) + var dependencies = new List(); + foreach (var projectDependency in targetFrameworkInformation.TopLevelPackages.Concat( + targetFrameworkInformation.TransitivePackages)) { - foreach (var projectDependency in targetFrameworkInformation.Dependencies) + // Determine whether this is a development dependency + var isDevelopmentDependency = false; + var packageIdentity = new PackageIdentity(projectDependency.Id, NuGetVersion.Parse(projectDependency.ResolvedVersion)); + var packageInfo = + LocalFolderUtility.GetPackageV3(packagesFolder, packageIdentity, NullLogger.Instance); + if (packageInfo != null) { - var projectLibrary = target.Libraries.FirstOrDefault(library => string.Equals(library.Name, projectDependency.Name, StringComparison.OrdinalIgnoreCase)); - - bool isDevelopmentDependency = false; - if (projectLibrary != null) - { - // Determine whether this is a development dependency - var packageIdentity = new PackageIdentity(projectLibrary.Name, projectLibrary.Version); - var packageInfo = LocalFolderUtility.GetPackageV3(packageSpec.RestoreMetadata.PackagesPath, packageIdentity, NullLogger.Instance); - if (packageInfo != null) - { - isDevelopmentDependency = packageInfo.GetReader().GetDevelopmentDependency(); - } - } - - var dependency = new Dependency( - projectDependency.Name, - projectDependency.LibraryRange.VersionRange, - projectLibrary?.Version, - projectDependency.AutoReferenced, - false, - isDevelopmentDependency, - projectDependency.VersionCentrallyManaged); - - targetFramework.Dependencies.Add(dependency); - - // Process transitive dependencies for the library - if (includeTransitiveDependencies) - { - AddDependencies(targetFramework, projectLibrary, target, 1, transitiveDepth, isDevelopmentDependency); - } + isDevelopmentDependency = packageInfo.GetReader().GetDevelopmentDependency(); } + + dependencies.Add(new Dependency(projectDependency.Id, projectDependency.ResolvedVersion, isDevelopmentDependency)); } + + targets.Add(new TargetFramework(targetFrameworkInformation.Framework, dependencies)); } + + projects.Add(new Project(modelProject.Path, targets)); } return projects; } - - private void AddDependencies(TargetFramework targetFramework, LockFileTargetLibrary parentLibrary, LockFileTarget target, int level, int transitiveDepth, bool isDevelopmentDependency) - { - if (parentLibrary?.Dependencies != null) - { - foreach (var packageDependency in parentLibrary.Dependencies) - { - var childLibrary = target.Libraries.FirstOrDefault(library => library.Name == packageDependency.Id); - - // Only add library and process child dependencies if we have not come across this dependency before - if (!targetFramework.Dependencies.Any(dependency => dependency.Name == packageDependency.Id)) - { - var childDependency = new Dependency(packageDependency.Id, packageDependency.VersionRange, childLibrary?.Version, false, true, isDevelopmentDependency, false); - targetFramework.Dependencies.Add(childDependency); - - // Process the dependency for this project dependency - if (level < transitiveDepth) - { - AddDependencies(targetFramework, childLibrary, target, level + 1, transitiveDepth, isDevelopmentDependency); - } - } - } - } - } } diff --git a/tools/DependencyListGenerator/Generator.cs b/tools/DependencyListGenerator/Generator.cs index 9308f51bf7..6a0b7463bb 100644 --- a/tools/DependencyListGenerator/Generator.cs +++ b/tools/DependencyListGenerator/Generator.cs @@ -8,26 +8,21 @@ namespace DependencyListGenerator; public static class Generator { - public static IEnumerable EnumerateDependencies(string projectPath) + public static Dictionary EnumerateDependencies(string projectPath) { var dotNetRunner = new DotNetRunner(); var fileSystem = new FileSystem(); var analysisService = new ProjectAnalysisService( - dependencyGraphService: new DependencyGraphService(dotNetRunner, fileSystem), dotNetRestoreService: new DotNetRestoreService(dotNetRunner, fileSystem), + packageListService: new DotNetPackageListService(dotNetRunner, fileSystem), fileSystem: fileSystem); - var result = analysisService.AnalyzeProject(projectPath, true, true, 1024)[0]; - var net462 = result.TargetFrameworks.First(x => x.Name.ToString() == ".NETFramework,Version=v4.6.2"); - - foreach (var dep in net462.Dependencies.OrderBy(x => x.Name)) - { - // OpenTelemetry and OpenTracing dependencies are managed directly. - if (dep.IsTransitive && !dep.IsDevelopmentDependency && !dep.Name.StartsWith("OpenTelemetry") && dep.Name != "OpenTracing") - { - yield return new TransientDependency(dep.Name, dep.ResolvedVersion.ToString()); - } - } + var result = analysisService.AnalyzeProject(projectPath, true)[0]; + return result.TargetFrameworks.ToDictionary( + it => it.Name, + it => it.Dependencies.OrderBy(x => x.Name) + .Where(dep => !dep.IsDevelopmentDependency) + .Select(dep => new TransientDependency(dep.Name, dep.ResolvedVersion)).ToArray()); } } diff --git a/tools/DependencyListGenerator/TransientDependency.cs b/tools/DependencyListGenerator/TransientDependency.cs index 4e7f20bf4a..35f53fa42f 100644 --- a/tools/DependencyListGenerator/TransientDependency.cs +++ b/tools/DependencyListGenerator/TransientDependency.cs @@ -3,15 +3,4 @@ namespace DependencyListGenerator; -public class TransientDependency -{ - public TransientDependency(string name, string version) - { - Name = name; - Version = version; - } - - public string Name { get; private set; } - - public string Version { get; private set; } -} +public record TransientDependency(string Name, string Version); diff --git a/tools/GacInstallTool/Program.cs b/tools/GacInstallTool/Program.cs index 99775fb73b..f9160e244d 100644 --- a/tools/GacInstallTool/Program.cs +++ b/tools/GacInstallTool/Program.cs @@ -30,7 +30,13 @@ public static void Main(string[] args) var install = flag == InstallFlag; var publisher = new System.EnterpriseServices.Internal.Publish(); - var files = Directory.GetFiles(dir, "*.dll"); + var files = Directory.GetFiles(dir, "*.dll").ToList(); + var links = Directory.GetFiles(dir, "*.link"); + foreach (var link in links) + { + var linkTarget = File.ReadAllText(link); + files.Add(Path.Combine(dir, "..", linkTarget, Path.GetFileNameWithoutExtension(link))); + } foreach (var file in files) { @@ -47,8 +53,8 @@ public static void Main(string[] args) } var resultText = install - ? $"Success: Installed {files.Length} libraries in the GAC." - : $"Success: Uninstalled {files.Length} libraries from the GAC."; + ? $"Success: Installed {files.Count} libraries in the GAC." + : $"Success: Uninstalled {files.Count} libraries from the GAC."; Console.WriteLine(resultText); } }