diff --git a/.cspell/dot-net.txt b/.cspell/dot-net.txt index 0c6eaf4994..6970f20a1e 100644 --- a/.cspell/dot-net.txt +++ b/.cspell/dot-net.txt @@ -31,3 +31,4 @@ corelib ASPNETCORE HOSTINGSTARTUPASSEMBLIES Bootstrapper +NETFX diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 614040e89b..2e68964d3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,6 +77,17 @@ jobs: with: name: bin-${{ matrix.machine }} path: bin/tracer-home + - name: Delete SQL Server MSI + if: ${{ runner.os == 'Windows' }} + shell: bash + run: | + rm SqlLocalDB.msi + - name: Generated files unchanged + shell: bash + run: | + git status + git diff + [[ -z "$(git status --porcelain)" ]] build-container: strategy: diff --git a/CHANGELOG.md b/CHANGELOG.md index c728d5649d..3709e0614a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ This beta release is built on top of [OpenTelemetry .NET](https://github.com/ope `ConfigureTracesOptions(StackExchangeRedisCallsInstrumentationOptions options)`. - Add plugin support for `ConfigureMetricsOptions(AspNetCoreMetricsInstrumentationOptions options)`. +- Add automatic assembly redirection for .NET Framework applications. The redirection + can be enabled or disabled via the + `OTEL_DOTNET_AUTO_NETFX_REDIRECT_ENABLED` environment variable. + See the [additional settings](./docs/config.md#additional-settings) table for details. ### Changed diff --git a/build/AssemblyRedirectionSourceGenerator.cs b/build/AssemblyRedirectionSourceGenerator.cs new file mode 100644 index 0000000000..4e0680094f --- /dev/null +++ b/build/AssemblyRedirectionSourceGenerator.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Mono.Cecil; +using Serilog; + +public class AssemblyRedirectionSourceGenerator +{ + public static void Generate(string assembliesFolderPath, string generatedFilePath) + { + Log.Debug("Generating assembly redirection file {0}", generatedFilePath); + var assemblies = new SortedDictionary<string, AssemblyNameDefinition>(); + foreach (var fileName in Directory.EnumerateFiles(assembliesFolderPath)) + { + try + { + using var moduleDef = ModuleDefinition.ReadModule(fileName); + var assemblyDef = moduleDef.Assembly.Name!; + if (assemblyDef.Name == "netstandard") + { + // Skip netstandard, since it doesn't need redirection. + continue; + } + + assemblies[assemblyDef.Name] = assemblyDef; + Log.Debug("Adding {0} assembly to the redirection map. Targeted version {1}", assemblyDef.Name, assemblyDef.Version); + } + catch (BadImageFormatException) + { + Log.Debug("Skipping \"{0}\" couldn't open it as a managed assembly", fileName); + } + } + + var sourceContents = GenerateSourceContents(assemblies); + + File.WriteAllText(generatedFilePath, sourceContents, Encoding.UTF8); + Log.Information("Assembly redirection source generated {0}", generatedFilePath); + } + + static string GenerateSourceContents(SortedDictionary<string, AssemblyNameDefinition> assemblies) + { + var sb = new StringBuilder(assemblies.Count * 256); + sb.AppendLine($"// Auto-generated file, do not change it - generated by the {nameof(AssemblyRedirectionSourceGenerator)} type"); + sb.Append(@" +#include ""cor_profiler.h"" + +#ifdef _WIN32 +namespace trace +{ +void CorProfiler::InitNetFxAssemblyRedirectsMap() +{ + assembly_version_redirect_map_.insert({ +"); + foreach (var kvp in assemblies) + { + var v = kvp.Value.Version!; + sb.AppendLine($" {{ L\"{kvp.Key}\", {{{v.Major}, {v.Minor}, {v.Build}, {v.Revision}}} }},"); + } + + sb.Append(@" }); +} +} +#endif +"); + + return sb.ToString(); + } +} diff --git a/build/Build.Steps.Windows.cs b/build/Build.Steps.Windows.cs index 6292b50b03..5214d09755 100644 --- a/build/Build.Steps.Windows.cs +++ b/build/Build.Steps.Windows.cs @@ -1,10 +1,8 @@ using System.IO; using Nuke.Common; using Nuke.Common.IO; -using Nuke.Common.ProjectModel; using Nuke.Common.Tooling; using Nuke.Common.Tools.Docker; -using Nuke.Common.Tools.DotNet; using Nuke.Common.Tools.MSBuild; using Serilog; using static Nuke.Common.EnvironmentInfo; @@ -17,6 +15,7 @@ partial class Build Target CompileNativeSrcWindows => _ => _ .Unlisted() .After(CompileManagedSrc) + .After(GenerateNetFxAssemblyRedirectionSource) .OnlyWhenStatic(() => IsWin) .Executes(() => { @@ -118,4 +117,16 @@ partial class Build .SetProcessWorkingDirectory(aspNetProject.Parent) ); }); + + Target GenerateNetFxAssemblyRedirectionSource => _ => _ + .Unlisted() + .After(PublishManagedProfiler) + .OnlyWhenStatic(() => IsWin) + .Executes(() => + { + var netFxAssembliesFolder = TracerHomeDirectory / MapToFolderOutput(TargetFramework.NET462); + var generatedSourceFile = SourceDirectory / Projects.AutoInstrumentationNative / "netfx_assembly_redirection.h"; + + AssemblyRedirectionSourceGenerator.Generate(netFxAssembliesFolder, generatedSourceFile); + }); } diff --git a/build/Build.Steps.cs b/build/Build.Steps.cs index 579a0d5637..4f68ac71c7 100644 --- a/build/Build.Steps.cs +++ b/build/Build.Steps.cs @@ -198,11 +198,6 @@ partial class Build .EnableNoRestore() .SetFramework(TargetFramework.NET6_0) .SetOutput(TracerHomeDirectory / MapToFolderOutput(TargetFramework.NET6_0))); - - string MapToFolderOutput(TargetFramework targetFramework) - { - return targetFramework.ToString().StartsWith("net4") ? "netfx" : "net"; - } }); Target PublishNativeProfiler => _ => _ @@ -565,4 +560,9 @@ private void RunBootstrappingTests() } } } + + private string MapToFolderOutput(TargetFramework targetFramework) + { + return targetFramework.ToString().StartsWith("net4") ? "netfx" : "net"; + } } diff --git a/build/Build.cs b/build/Build.cs index 0a28c32033..56188d617a 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -28,7 +28,7 @@ partial class Build : NukeBuild [Parameter("Test projects filter. Optional, default matches all test projects. The project will be selected if the string is part of its name.")] readonly string TestProject = ""; - [Parameter("Test name fitler. Optional")] + [Parameter("Test name filter. Optional")] readonly string TestName; [Parameter("Number of times each dotnet test is run. Default is '1'")] @@ -88,6 +88,7 @@ void DeleteReparsePoints(string path) .DependsOn(Restore) .DependsOn(CompileManagedSrc) .DependsOn(PublishManagedProfiler) + .DependsOn(GenerateNetFxAssemblyRedirectionSource) .DependsOn(CompileNativeSrc) .DependsOn(PublishNativeProfiler) .DependsOn(CopyIntegrationsJson) diff --git a/build/_build.csproj b/build/_build.csproj index f94e5f1b74..5b8462ce80 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -11,6 +11,7 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="Mono.Cecil" Version="0.11.4" /> <PackageReference Include="Nuke.Common" Version="6.3.0" /> <PackageReference Include="Nuget.CommandLine" Version="6.3.1" ExcludeAssets="all" /> </ItemGroup> diff --git a/docs/config.md b/docs/config.md index 93d964ea5d..cbf856bdd8 100644 --- a/docs/config.md +++ b/docs/config.md @@ -243,6 +243,7 @@ Important environment variables include: | `OTEL_DOTNET_AUTO_OPENTRACING_ENABLED` | Enables OpenTracing tracer. | `false` | | `OTEL_DOTNET_AUTO_LOGS_ENABLED` | Enables logs. | `true` | | `OTEL_DOTNET_AUTO_METRICS_ENABLED` | Enables metrics. | `true` | +| `OTEL_DOTNET_AUTO_NETFX_REDIRECT_ENABLED` | Enables automatic redirection of the assemblies used by the automatic instrumentation on the .NET Framework. | `true` | | `OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.ActivitySource` names to be added to the tracer at the startup. Use it to capture manually instrumented spans. | | | `OTEL_DOTNET_AUTO_LEGACY_SOURCES` | Comma-separated list of additional legacy source names to be added to the tracer at the startup. Use it to capture `System.Diagnostics.Activity` objects created without using the `System.Diagnostics.ActivitySource` API. | | | `OTEL_DOTNET_AUTO_FLUSH_ON_UNHANDLEDEXCEPTION` | Controls whether the telemetry data is flushed when an [AppDomain.UnhandledException](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception) event is raised. Set to `true` when you suspect that you are experiencing a problem with missing telemetry data and also experiencing unhandled exceptions. | `false` | diff --git a/src/OpenTelemetry.AutoInstrumentation.Loader/Startup.NetFramework.cs b/src/OpenTelemetry.AutoInstrumentation.Loader/Startup.NetFramework.cs index b99bc3dc09..86974accb3 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Loader/Startup.NetFramework.cs +++ b/src/OpenTelemetry.AutoInstrumentation.Loader/Startup.NetFramework.cs @@ -48,11 +48,20 @@ private static string ResolveManagedProfilerDirectory() return null; } + StartupLogger.Debug("Requester [{0}] requested [{1}]", args?.RequestingAssembly?.FullName ?? "<null>", args?.Name ?? "<null>"); var path = Path.Combine(ManagedProfilerDirectory, $"{assemblyName}.dll"); if (File.Exists(path)) { - StartupLogger.Debug("Loading {0}", path); - return Assembly.LoadFrom(path); + try + { + var loadedAssembly = Assembly.LoadFrom(path); + StartupLogger.Debug("Assembly.LoadFrom(\"{0}\") succeeded={1}", path, loadedAssembly != null); + return loadedAssembly; + } + catch (Exception ex) + { + StartupLogger.Debug("Assembly.LoadFrom(\"{0}\") Exception: {1}", path, ex); + } } return null; diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h b/src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h index 50edd35716..74d4e17d8e 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h @@ -486,6 +486,52 @@ struct FunctionInfo } }; +struct AssemblyVersionRedirection +{ + // This struct is used to check and track version against ASSEMBLYMETADATA structs + // so it uses the same naming conventions, keeping fields with the same names in both + // structs. + USHORT usMajorVersion; // Major Version. + USHORT usMinorVersion; // Minor Version. + USHORT usBuildNumber; // Build Number. + USHORT usRevisionNumber; // Revision Number. + + // Redirection related fields + ULONG ulRedirectionCount; // Tracks the number of times that the redirection was applied. + + AssemblyVersionRedirection() : + usMajorVersion(0), usMinorVersion(0), usBuildNumber(0), usRevisionNumber(0), ulRedirectionCount(0) + { + } + + AssemblyVersionRedirection(USHORT major, USHORT minor, USHORT build, USHORT revision) : ulRedirectionCount(0) + { + usMajorVersion = major; + usMinorVersion = minor; + usBuildNumber = build; + usRevisionNumber = revision; + } + + int CompareToAssemblyVersion(const ASSEMBLYMETADATA& assembly) + { + return + usMajorVersion != assembly.usMajorVersion + ? (usMajorVersion > assembly.usMajorVersion ? 1 : -1) : + usMinorVersion != assembly.usMinorVersion + ? (usMinorVersion > assembly.usMinorVersion ? 1 : -1) : + usBuildNumber != assembly.usBuildNumber + ? (usBuildNumber > assembly.usBuildNumber ? 1 : -1) : + usRevisionNumber != assembly.usRevisionNumber + ? (usRevisionNumber > assembly.usRevisionNumber ? 1 : -1) : + 0; + } + + WSTRING VersionStr() + { + return trace::VersionStr(usMajorVersion, usMinorVersion, usBuildNumber, usRevisionNumber); + } +}; + RuntimeInformation GetRuntimeInformation(ICorProfilerInfo7* info); AssemblyInfo GetAssemblyInfo(ICorProfilerInfo7* info, const AssemblyID& assembly_id); diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp index 579ae95357..826d57c59b 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp +++ b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp @@ -27,6 +27,10 @@ #include <mach-o/getsect.h> #endif +#ifdef _WIN32 +#include "netfx_assembly_redirection.h" +#endif + namespace trace { @@ -91,6 +95,13 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un return E_FAIL; } +#ifdef _WIN32 + if (runtime_information_.is_desktop() && IsNetFxAssemblyRedirectionEnabled()) + { + InitNetFxAssemblyRedirectsMap(); + } +#endif + const auto process_name = GetCurrentProcessName(); const auto exclude_process_names = GetEnvironmentValues(environment::exclude_process_names); @@ -303,6 +314,140 @@ HRESULT STDMETHODCALLTYPE CorProfiler::AssemblyLoadFinished(AssemblyID assembly_ return S_OK; } +#ifdef _WIN32 +void CorProfiler::RedirectAssemblyReferences( + const ComPtr<IMetaDataAssemblyImport>& assembly_import, + const ComPtr<IMetaDataAssemblyEmit>& assembly_emit) +{ + HRESULT hr = S_FALSE; + HCORENUM core_enum_handle = NULL; + const ULONG assembly_refs_sz = 16; + mdAssemblyRef assembly_refs[assembly_refs_sz]; + ULONG assembly_refs_count; + + // Inspect all assembly references and make any necessary redirects. + while (true) + { + hr = assembly_import.Get()->EnumAssemblyRefs(&core_enum_handle, assembly_refs, assembly_refs_sz, &assembly_refs_count); + if (hr == S_FALSE) + { + // This is expected when the enumeration finished. + Logger::Debug("RedirectAssemblyReferences: EnumAssemblyRefs returned S_FALSE assembly_refs_count=", assembly_refs_count); + break; + } + + // Loop and process each AssemblyRef + for (ULONG i = 0; i < assembly_refs_count; i++) + { + const void* public_key_or_token; + ULONG public_key_or_token_sz; + WCHAR name[kNameMaxSize]; + ULONG name_len = 0; + ASSEMBLYMETADATA assembly_metadata{}; + const void* hash_value; + ULONG hash_value_sz; + DWORD assembly_flags = 0; + + hr = assembly_import->GetAssemblyRefProps( + assembly_refs[i], + &public_key_or_token, + &public_key_or_token_sz, + name, + kNameMaxSize, + &name_len, + &assembly_metadata, + &hash_value, + &hash_value_sz, + &assembly_flags); + if (FAILED(hr) || name_len == 0) + { + Logger::Warn("RedirectAssemblyReferences: GetAssemblyRefProps failed HRESULT=", HResultStr(hr)); + continue; + } + + const auto wsz_name = WSTRING(name); + if (Logger::IsDebugEnabled()) + { + Logger::Debug("RedirectAssemblyReferences: AssemblyRef for [", wsz_name, "] version=", AssemblyVersionStr(assembly_metadata)); + } + + const auto found_redirect = assembly_version_redirect_map_.find(wsz_name); + if (found_redirect == assembly_version_redirect_map_.end()) + { + // No redirection to be applied here. + continue; + } + + AssemblyVersionRedirection& redirect = found_redirect->second; + auto version_comparison = redirect.CompareToAssemblyVersion(assembly_metadata); + if (version_comparison > 0) + { + // Redirection was a higher version, let's proceed with the redirection + Logger::Info("RedirectAssemblyReferences: redirecting [", wsz_name, "] from_version=", AssemblyVersionStr(assembly_metadata), + " to_version=", redirect.VersionStr(), + " previous_redirects=", redirect.ulRedirectionCount); + assembly_metadata.usMajorVersion = redirect.usMajorVersion; + assembly_metadata.usMinorVersion = redirect.usMinorVersion; + assembly_metadata.usBuildNumber = redirect.usBuildNumber; + assembly_metadata.usRevisionNumber = redirect.usRevisionNumber; + hr = assembly_emit.Get()->SetAssemblyRefProps( + assembly_refs[i], + public_key_or_token, + public_key_or_token_sz, + name, + &assembly_metadata, + hash_value, + hash_value_sz, + assembly_flags); + if (hr != S_OK) + { + Logger::Warn("RedirectAssemblyReferences: redirection error: SetAssemblyRefProps HRESULT=", HResultStr(hr)); + } + else + { + redirect.ulRedirectionCount++; + } + } + else if (version_comparison == 0) + { + // No need to redirect since it is the same assembly version on the ref and on the map + if (Logger::IsDebugEnabled()) + { + Logger::Debug("RedirectAssemblyReferences: same version for [", wsz_name, "] version=", redirect.VersionStr(), " previous_redirects=", redirect.ulRedirectionCount); + } + } + else + { + // Redirection points to a lower version. If no redirection was done yet modify the map to + // point to the higher version. If redirection was already applied do not redirect and let + // the runtime handle it. + if (redirect.ulRedirectionCount == 0) + { + // Redirection was not applied yet use the higher version. Also increment the redirection + // count to indicate that this version was already used. + Logger::Info("RedirectAssemblyReferences: redirection update for [", wsz_name, "] to_version=", AssemblyVersionStr(assembly_metadata), + " previous_version_redirection=", redirect.VersionStr()); + redirect.usMajorVersion = assembly_metadata.usMajorVersion; + redirect.usMinorVersion = assembly_metadata.usMinorVersion; + redirect.usBuildNumber = assembly_metadata.usBuildNumber; + redirect.usRevisionNumber = assembly_metadata.usRevisionNumber; + redirect.ulRedirectionCount++; + } + else + { + // This is risky: we aren't sure if the reference will be actually be used during the runtime. + // So it is possible that nothing will happen but we can't be sure. Using higher versions on + // the OpenTelemetry.AutoInstrumentation dependencies minimizes the chances of hitting this code + // path. + Logger::Error("RedirectAssemblyReferences: AssemblyRef [", wsz_name, "] version=", AssemblyVersionStr(assembly_metadata), + " has a higher version than an earlier applied redirection to version=", redirect.VersionStr()); + } + } + } + } +} +#endif + void CorProfiler::RewritingPInvokeMaps(ComPtr<IUnknown> metadata_interfaces, ModuleMetadata* module_metadata, WSTRING nativemethods_type_name) { HRESULT hr; @@ -500,34 +645,32 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, HR return S_OK; } - for (auto&& skip_assembly : skip_assemblies) + // It is not safe to skip assemblies if applying redirection on .NET Framework + if (!runtime_information_.is_desktop() || !IsNetFxAssemblyRedirectionEnabled()) { - if (module_info.assembly.name == skip_assembly) + // Not .NET Framework or assembly redirection is disabled, check if the + // assembly can be skipped. + for (auto&& skip_assembly : skip_assemblies) { - Logger::Debug("ModuleLoadFinished skipping known module: ", module_id, " ", module_info.assembly.name); - return S_OK; + if (module_info.assembly.name == skip_assembly) + { + Logger::Debug("ModuleLoadFinished skipping known module: ", module_id, " ", module_info.assembly.name); + return S_OK; + } } - } - for (auto&& skip_assembly_pattern : skip_assembly_prefixes) - { - if (module_info.assembly.name.rfind(skip_assembly_pattern, 0) == 0) + for (auto&& skip_assembly_pattern : skip_assembly_prefixes) { - Logger::Debug("ModuleLoadFinished skipping module by pattern: ", module_id, " ", module_info.assembly.name); - return S_OK; + if (module_info.assembly.name.rfind(skip_assembly_pattern, 0) == 0) + { + Logger::Debug("ModuleLoadFinished skipping module by pattern: ", module_id, " ", module_info.assembly.name); + return S_OK; + } } } ComPtr<IUnknown> metadata_interfaces; ModuleMetadata* module_metadata = nullptr; - - if (module_info.IsDynamic()) - { - // For CallTarget we don't need to load metadata on dynamic modules. - Logger::Debug("ModuleLoadFinished skipping Dynamic module: ", module_id, " ", module_info.assembly.name); - return S_OK; - } - auto hr = this->info_->GetModuleMetaData(module_id, ofRead | ofWrite, IID_IMetaDataImport2, metadata_interfaces.GetAddressOf()); if (FAILED(hr)) @@ -541,10 +684,25 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, HR const auto assembly_import = metadata_interfaces.As<IMetaDataAssemblyImport>(IID_IMetaDataAssemblyImport); const auto assembly_emit = metadata_interfaces.As<IMetaDataAssemblyEmit>(IID_IMetaDataAssemblyEmit); - module_metadata = new ModuleMetadata(metadata_import, metadata_emit, assembly_import, assembly_emit, - module_info.assembly.name, app_domain_id, &corAssemblyProperty); +#ifdef _WIN32 + if (runtime_information_.is_desktop() && IsNetFxAssemblyRedirectionEnabled()) + { + // On the .NET Framework redirect any assembly reference to the versions required by + // OpenTelemetry.AutoInstrumentation assembly, the ones under netfx/ folder. + RedirectAssemblyReferences(assembly_import, assembly_emit); + } +#endif + + if (module_info.IsDynamic()) + { + // For CallTarget we don't need to load metadata on dynamic modules. + Logger::Debug("ModuleLoadFinished skipping Dynamic module: ", module_id, " ", module_info.assembly.name); + return S_OK; + } // store module info for later lookup + module_metadata = new ModuleMetadata(metadata_import, metadata_emit, assembly_import, assembly_emit, + module_info.assembly.name, app_domain_id, &corAssemblyProperty); module_id_to_info_map_[module_id] = module_metadata; if (module_info.assembly.name == managed_profiler_name) diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h index 6804233ab8..854c7e936c 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.h @@ -58,6 +58,17 @@ class CorProfiler : public CorProfilerBase std::unordered_map<ModuleID, ModuleMetadata*> module_id_to_info_map_; ModuleID managed_profiler_module_id_ = 0; + // + // Assembly redirect private members + // +#ifdef _WIN32 + std::unordered_map<WSTRING, AssemblyVersionRedirection> assembly_version_redirect_map_; + void InitNetFxAssemblyRedirectsMap(); + void RedirectAssemblyReferences( + const ComPtr<IMetaDataAssemblyImport>& assembly_import, + const ComPtr<IMetaDataAssemblyEmit>& assembly_emit); +#endif + // // Helper methods // diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables.h b/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables.h index e925b2bb2b..8120fa141b 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables.h @@ -93,6 +93,9 @@ const WSTRING clr_enable_inlining = WStr("OTEL_DOTNET_AUTO_CLR_ENABLE_INLINING") // Sets whether to enable NGEN images. const WSTRING clr_enable_ngen = WStr("OTEL_DOTNET_AUTO_CLR_ENABLE_NGEN"); +// Enable the assembly version redirection when running on the .NET Framework. +const WSTRING netfx_assembly_redirection_enabled = WStr("OTEL_DOTNET_AUTO_NETFX_REDIRECT_ENABLED"); + // Additional dependencies that are to be lighted up at runtime. // See https://github.com/dotnet/runtime/blob/main/docs/design/features/additional-deps.md const WSTRING dotnet_additional_deps = WStr("DOTNET_ADDITIONAL_DEPS"); diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables_util.h b/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables_util.h index d6fad279ac..552c7b0d83 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables_util.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/environment_variables_util.h @@ -70,6 +70,10 @@ bool AreLogsEnabled() { ToBooleanWithDefault(GetEnvironmentValue(environment::logs_enabled), true); } +bool IsNetFxAssemblyRedirectionEnabled() { + ToBooleanWithDefault(GetEnvironmentValue(environment::netfx_assembly_redirection_enabled), true); +} + } // namespace trace #endif // OTEL_CLR_PROFILER_ENVIRONMENT_VARIABLES_UTIL_H_ \ No newline at end of file diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h b/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h new file mode 100644 index 0000000000..1ff0e234e3 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation.Native/netfx_assembly_redirection.h @@ -0,0 +1,153 @@ +// Auto-generated file, do not change it - generated by the AssemblyRedirectionSourceGenerator type + +#include "cor_profiler.h" + +#ifdef _WIN32 +namespace trace +{ +void CorProfiler::InitNetFxAssemblyRedirectsMap() +{ + assembly_version_redirect_map_.insert({ + { L"Google.Protobuf", {3, 19, 4, 0} }, + { L"Grpc.Core", {2, 0, 0, 0} }, + { L"Grpc.Core.Api", {2, 0, 0, 0} }, + { L"Microsoft.Bcl.AsyncInterfaces", {1, 0, 0, 0} }, + { L"Microsoft.Extensions.Configuration", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Configuration.Abstractions", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Configuration.Binder", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Configuration.EnvironmentVariables", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.DependencyInjection", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.DependencyInjection.Abstractions", {5, 0, 0, 0} }, + { L"Microsoft.Extensions.Logging", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Logging.Abstractions", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Logging.Configuration", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Options", {5, 0, 0, 0} }, + { L"Microsoft.Extensions.Options.ConfigurationExtensions", {3, 1, 0, 0} }, + { L"Microsoft.Extensions.Primitives", {5, 0, 0, 0} }, + { L"Microsoft.Win32.Primitives", {4, 0, 3, 0} }, + { L"OpenTelemetry", {1, 0, 0, 0} }, + { L"OpenTelemetry.Api", {1, 0, 0, 0} }, + { L"OpenTelemetry.AutoInstrumentation", {0, 5, 1, 0} }, + { L"OpenTelemetry.Exporter.Console", {1, 0, 0, 0} }, + { L"OpenTelemetry.Exporter.Jaeger", {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.DependencyInjection", {1, 0, 0, 0} }, + { L"OpenTelemetry.Extensions.Propagators", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.AspNet", {1, 0, 0, 7} }, + { L"OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule", {1, 0, 0, 7} }, + { L"OpenTelemetry.Instrumentation.GrpcNetClient", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.Http", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.Process", {1, 0, 0, 3} }, + { L"OpenTelemetry.Instrumentation.Runtime", {1, 1, 0, 2} }, + { L"OpenTelemetry.Instrumentation.SqlClient", {1, 0, 0, 0} }, + { L"OpenTelemetry.Instrumentation.Wcf", {1, 0, 0, 7} }, + { 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, 3, 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", {7, 0, 0, 0} }, + { 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.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, 1, 2} }, + { 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, 4, 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, 0, 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", {4, 0, 5, 0} }, + { L"System.Text.Json", {4, 0, 1, 2} }, + { 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, 0, 1} }, + { 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, 3, 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} }, + }); +} +} +#endif diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/util.cpp b/src/OpenTelemetry.AutoInstrumentation.Native/util.cpp index 194f4097b5..cde66bb293 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/util.cpp +++ b/src/OpenTelemetry.AutoInstrumentation.Native/util.cpp @@ -189,4 +189,16 @@ WSTRING HResultStr(const HRESULT hr) return ToWSTRING(ss.str()); } +WSTRING VersionStr(const USHORT major, const USHORT minor, const USHORT build, const USHORT revision) +{ + std::stringstream ss; + ss << major << "." << minor << "." << build << "." << revision; + return ToWSTRING(ss.str()); +} + +WSTRING AssemblyVersionStr(const ASSEMBLYMETADATA& assembly_metadata) +{ + return VersionStr(assembly_metadata.usMajorVersion, assembly_metadata.usMinorVersion, assembly_metadata.usBuildNumber, assembly_metadata.usRevisionNumber); +} + } // namespace trace diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/util.h b/src/OpenTelemetry.AutoInstrumentation.Native/util.h index 8735b31e2e..193702ac5e 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/util.h +++ b/src/OpenTelemetry.AutoInstrumentation.Native/util.h @@ -44,6 +44,10 @@ WSTRING TokenStr(const mdToken* token); // Convert HRESULT to a friendly string, e.g.: "0x80000002" WSTRING HResultStr(const HRESULT hr); +WSTRING VersionStr(const USHORT major, const USHORT minor, const USHORT build, const USHORT revision); + +WSTRING AssemblyVersionStr(const ASSEMBLYMETADATA& assembly_metadata); + template <class Container> bool Contains(const Container& items, const typename Container::value_type& value) { diff --git a/test/IntegrationTests/GraphQLTests.cs b/test/IntegrationTests/GraphQLTests.cs index 7104b173cb..9269442cb9 100644 --- a/test/IntegrationTests/GraphQLTests.cs +++ b/test/IntegrationTests/GraphQLTests.cs @@ -68,6 +68,7 @@ public async Task SubmitsTraces(bool setDocument) SetEnvironmentVariable("OTEL_DOTNET_AUTO_GRAPHQL_SET_DOCUMENT", setDocument.ToString()); SetEnvironmentVariable("OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS", "GraphQL"); SetEnvironmentVariable("OTEL_TRACES_SAMPLER", "always_on"); + SetEnvironmentVariable("OTEL_DOTNET_AUTO_NETFX_REDIRECT_ENABLED", "false"); int aspNetCorePort = TcpPortProvider.GetOpenPort(); SetEnvironmentVariable("ASPNETCORE_URLS", $"http://127.0.0.1:{aspNetCorePort}/"); diff --git a/test/IntegrationTests/HttpNetFrameworkTests.cs b/test/IntegrationTests/HttpNetFrameworkTests.cs index 957c4b06f9..def3be48d9 100644 --- a/test/IntegrationTests/HttpNetFrameworkTests.cs +++ b/test/IntegrationTests/HttpNetFrameworkTests.cs @@ -36,7 +36,6 @@ public void SubmitTraces() SetExporter(collector); collector.Expect("OpenTelemetry.Instrumentation.Http.HttpWebRequest"); - collector.Expect("TestApplication.Http.NetFramework"); RunTestApplication(); diff --git a/test/OpenTelemetry.AutoInstrumentation.Loader.Tests/StartupTests.cs b/test/OpenTelemetry.AutoInstrumentation.Loader.Tests/StartupTests.cs index 91fa41fabb..b621d9b7ac 100644 --- a/test/OpenTelemetry.AutoInstrumentation.Loader.Tests/StartupTests.cs +++ b/test/OpenTelemetry.AutoInstrumentation.Loader.Tests/StartupTests.cs @@ -18,21 +18,32 @@ using System.IO; using System.Linq; using Xunit; +using Xunit.Abstractions; namespace OpenTelemetry.AutoInstrumentation.Loader.Tests; public class StartupTests { + private ITestOutputHelper _testOutput; + + public StartupTests(ITestOutputHelper testOutput) + { + _testOutput = testOutput; + } + [Fact] public void Ctor_LoadsManagedAssembly() { var directory = Directory.GetCurrentDirectory(); var profilerDirectory = Path.Combine(directory, "..", "Profiler"); + _testOutput.WriteLine($"profilerDirectory={profilerDirectory}"); #if NETFRAMEWORK - if (Directory.Exists(Path.Combine(profilerDirectory, "net462"))) + var srcDir = Path.Combine(profilerDirectory, "net462"); + var dstDir = Path.Combine(profilerDirectory, "netfx"); + if (Directory.Exists(srcDir) && !Directory.Exists(dstDir)) { - Directory.Move(Path.Combine(profilerDirectory, "net462"), Path.Combine(profilerDirectory, "netfx")); + Directory.Move(srcDir, dstDir); } #else if (Directory.Exists(Path.Combine(profilerDirectory, "net6.0"))) @@ -41,6 +52,7 @@ public void Ctor_LoadsManagedAssembly() } #endif + Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_DEBUG", "1"); Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_HOME", profilerDirectory); var exception = Record.Exception(() => new AutoInstrumentation.Loader.Startup()); diff --git a/test/OpenTelemetry.AutoInstrumentation.Native.Tests/OpenTelemetry.AutoInstrumentation.Native.Tests.vcxproj b/test/OpenTelemetry.AutoInstrumentation.Native.Tests/OpenTelemetry.AutoInstrumentation.Native.Tests.vcxproj index 289bef809d..4dde0a4712 100644 --- a/test/OpenTelemetry.AutoInstrumentation.Native.Tests/OpenTelemetry.AutoInstrumentation.Native.Tests.vcxproj +++ b/test/OpenTelemetry.AutoInstrumentation.Native.Tests/OpenTelemetry.AutoInstrumentation.Native.Tests.vcxproj @@ -70,6 +70,7 @@ <ClInclude Include="test_helpers.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="assembly_version_redirection_test.cpp" /> <ClCompile Include="integration_loader_test.cpp" /> <ClCompile Include="integration_test.cpp" /> <ClCompile Include="clr_helper_test.cpp" /> diff --git a/test/OpenTelemetry.AutoInstrumentation.Native.Tests/assembly_version_redirection_test.cpp b/test/OpenTelemetry.AutoInstrumentation.Native.Tests/assembly_version_redirection_test.cpp new file mode 100644 index 0000000000..cc6e8ba857 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Native.Tests/assembly_version_redirection_test.cpp @@ -0,0 +1,25 @@ +#ifdef _WIN32 +#include "pch.h" + +#include "../../src/OpenTelemetry.AutoInstrumentation.Native/clr_helpers.h" + +using namespace trace; + +TEST(AssemblyVersionRedirectionTest, CompareToAssemblyVersion_Equal) { + ASSERT_TRUE(AssemblyVersionRedirection(1, 2, 3, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) == 0); +} + +TEST(AssemblyVersionRedirectionTest, CompareToAssemblyVersion_Lower) { + ASSERT_TRUE(AssemblyVersionRedirection(0, 2, 3, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) < 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 1, 3, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) < 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 2, 2, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) < 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 2, 3, 3).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) < 0); +} + +TEST(AssemblyVersionRedirectionTest, CompareToAssemblyVersion_Higher) { + ASSERT_TRUE(AssemblyVersionRedirection(2, 2, 3, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) > 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 3, 3, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) > 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 2, 4, 4).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) > 0); + ASSERT_TRUE(AssemblyVersionRedirection(1, 2, 3, 5).CompareToAssemblyVersion(ASSEMBLYMETADATA{1, 2, 3, 4}) > 0); +} +#endif diff --git a/test/test-applications/integrations/Directory.Build.props b/test/test-applications/integrations/Directory.Build.props index bbc68c41a9..7b4c218eed 100644 --- a/test/test-applications/integrations/Directory.Build.props +++ b/test/test-applications/integrations/Directory.Build.props @@ -8,8 +8,4 @@ <Compile Include="$(MSBuildThisFileDirectory)GlobalSuppressions.cs" Link="GlobalSuppressions.integrations.cs" /> </ItemGroup> - <!-- .NET Framework apps do not have shared store to bump these libraries --> - <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))"> - <PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" /> - </ItemGroup> </Project> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.DomainNeutral/App.config b/test/test-applications/integrations/TestApplication.DomainNeutral/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.DomainNeutral/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.GraphQL/TestApplication.GraphQL.csproj b/test/test-applications/integrations/TestApplication.GraphQL/TestApplication.GraphQL.csproj index 427816d6af..89dd9d24ce 100644 --- a/test/test-applications/integrations/TestApplication.GraphQL/TestApplication.GraphQL.csproj +++ b/test/test-applications/integrations/TestApplication.GraphQL/TestApplication.GraphQL.csproj @@ -12,4 +12,10 @@ <ProjectReference Include="..\dependency-libs\TestApplication.Shared\TestApplication.Shared.csproj" /> </ItemGroup> + <!-- "Microsoft.AspNetCore" is incompatible with the .NET Fx automatic redirection. --> + <!-- The element below injects the necesary dependencies during build time, for more info --> + <!-- https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1727 --> + <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))"> + <PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" /> + </ItemGroup> </Project> diff --git a/test/test-applications/integrations/TestApplication.Http.NetFramework/App.config b/test/test-applications/integrations/TestApplication.Http.NetFramework/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.Http.NetFramework/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.Http.NetFramework/TestApplication.Http.NetFramework.csproj b/test/test-applications/integrations/TestApplication.Http.NetFramework/TestApplication.Http.NetFramework.csproj index 3770780cba..c9f82c2bd5 100644 --- a/test/test-applications/integrations/TestApplication.Http.NetFramework/TestApplication.Http.NetFramework.csproj +++ b/test/test-applications/integrations/TestApplication.Http.NetFramework/TestApplication.Http.NetFramework.csproj @@ -2,12 +2,4 @@ <PropertyGroup> <TargetFrameworks>net462</TargetFrameworks> </PropertyGroup> - - <ItemGroup> - <Content Remove="App.config" /> - </ItemGroup> - - <ItemGroup> - <None Include="App.config" /> - </ItemGroup> </Project> diff --git a/test/test-applications/integrations/TestApplication.Http.NetFramework/TestServer.cs b/test/test-applications/integrations/TestApplication.Http.NetFramework/TestServer.cs index 6b4d858e56..6afcc2f49b 100644 --- a/test/test-applications/integrations/TestApplication.Http.NetFramework/TestServer.cs +++ b/test/test-applications/integrations/TestApplication.Http.NetFramework/TestServer.cs @@ -15,7 +15,6 @@ // </copyright> using System; -using System.Diagnostics; using System.IO; using System.Net; using System.Text; @@ -26,8 +25,6 @@ namespace TestApplication.Http.NetFramework; public class TestServer : IDisposable { - private static readonly ActivitySource MyActivitySource = new ActivitySource("TestApplication.Http.NetFramework", "1.0.0"); - private readonly HttpListener _listener; private readonly Thread _listenerThread; @@ -70,11 +67,6 @@ private void HandleHttpRequests() Console.WriteLine("[SERVER] Received: {0}", request); - using (var activity = MyActivitySource.StartActivity("manual span")) - { - activity?.SetTag("test_tag", "test_value"); - } - // NOTE: HttpStreamRequest doesn't support Transfer-Encoding: Chunked // (Setting content-length avoids that) ctx.Response.ContentType = "text/plain"; diff --git a/test/test-applications/integrations/TestApplication.MongoDB/Program.cs b/test/test-applications/integrations/TestApplication.MongoDB/Program.cs index d9272af59e..aacc61715d 100644 --- a/test/test-applications/integrations/TestApplication.MongoDB/Program.cs +++ b/test/test-applications/integrations/TestApplication.MongoDB/Program.cs @@ -16,7 +16,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; #if !MONGODB_2_15 using System.Threading; @@ -32,8 +31,6 @@ namespace TestApplication.MongoDB; public static class Program { - internal static readonly ActivitySource ActivitySource = new("TestApplication.MongoDB", "1.0.0"); - public static void Main(string[] args) { ConsoleHelper.WriteSplashScreen(args); @@ -53,7 +50,6 @@ public static void Main(string[] args) } }; - using var mainScope = ActivitySource.StartActivity("Main()"); var connectionString = $"mongodb://{Host()}:{mongoPort}"; var client = new MongoClient(connectionString); @@ -72,7 +68,6 @@ public static void Run(IMongoCollection<BsonDocument> collection, BsonDocument n { var allFilter = new BsonDocument(); - using var syncScope = ActivitySource.StartActivity("sync-calls"); collection.DeleteMany(allFilter); collection.InsertOne(newDocument); @@ -108,7 +103,6 @@ public static async Task RunAsync(IMongoCollection<BsonDocument> collection, Bso { var allFilter = new BsonDocument(); - using var asyncScope = ActivitySource.StartActivity("async-calls"); await collection.DeleteManyAsync(allFilter); await collection.InsertOneAsync(newDocument); @@ -124,19 +118,13 @@ public static async Task RunAsync(IMongoCollection<BsonDocument> collection, Bso #if !MONGODB_2_15 public static void WireProtocolExecuteIntegrationTest(MongoClient client) { - using (var syncScope = ActivitySource.StartActivity("sync-calls-execute")) - { - var server = client.Cluster.SelectServer(new ServerSelector(), CancellationToken.None); - var channel = server.GetChannel(CancellationToken.None); - channel.KillCursors(new long[] { 0, 1, 2 }, new global::MongoDB.Driver.Core.WireProtocol.Messages.Encoders.MessageEncoderSettings(), CancellationToken.None); - } + var server = client.Cluster.SelectServer(new ServerSelector(), CancellationToken.None); + var channel = server.GetChannel(CancellationToken.None); + channel.KillCursors(new long[] { 0, 1, 2 }, new global::MongoDB.Driver.Core.WireProtocol.Messages.Encoders.MessageEncoderSettings(), CancellationToken.None); - using (var asyncScope = ActivitySource.StartActivity("async-calls-execute")) - { - var server = client.Cluster.SelectServer(new ServerSelector(), CancellationToken.None); - var channel = server.GetChannel(CancellationToken.None); - channel.KillCursorsAsync(new long[] { 0, 1, 2 }, new global::MongoDB.Driver.Core.WireProtocol.Messages.Encoders.MessageEncoderSettings(), CancellationToken.None).Wait(); - } + server = client.Cluster.SelectServer(new ServerSelector(), CancellationToken.None); + channel = server.GetChannel(CancellationToken.None); + channel.KillCursorsAsync(new long[] { 0, 1, 2 }, new global::MongoDB.Driver.Core.WireProtocol.Messages.Encoders.MessageEncoderSettings(), CancellationToken.None).Wait(); } #endif diff --git a/test/test-applications/integrations/TestApplication.Npgsql/App.config b/test/test-applications/integrations/TestApplication.Npgsql/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.Npgsql/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.Smoke/App.config b/test/test-applications/integrations/TestApplication.Smoke/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.Smoke/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.Smoke/TestApplication.Smoke.csproj b/test/test-applications/integrations/TestApplication.Smoke/TestApplication.Smoke.csproj index c6f8b26e46..c56c5c6eae 100644 --- a/test/test-applications/integrations/TestApplication.Smoke/TestApplication.Smoke.csproj +++ b/test/test-applications/integrations/TestApplication.Smoke/TestApplication.Smoke.csproj @@ -4,10 +4,11 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" /> + <ProjectReference Include="..\dependency-libs\TestApplication.Shared\TestApplication.Shared.csproj" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\dependency-libs\TestApplication.Shared\TestApplication.Shared.csproj" /> + <PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" /> </ItemGroup> + </Project> diff --git a/test/test-applications/integrations/TestApplication.SqlClient.NetFramework/App.config b/test/test-applications/integrations/TestApplication.SqlClient.NetFramework/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.SqlClient.NetFramework/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.SqlClient/App.config b/test/test-applications/integrations/TestApplication.SqlClient/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.SqlClient/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/App.config b/test/test-applications/integrations/TestApplication.StrongNamed/App.config deleted file mode 100644 index 63f272fd9a..0000000000 --- a/test/test-applications/integrations/TestApplication.StrongNamed/App.config +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- To be removed when https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1646 is fixed --> -<configuration> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/> - </startup> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration> \ No newline at end of file diff --git a/test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework/App.config b/test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework/App.config index 8d69d4b4b9..79d935d360 100644 --- a/test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework/App.config +++ b/test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework/App.config @@ -30,16 +30,4 @@ <endpoint address="net.tcp://127.0.0.1:9090/Telemetry" binding="netTcpBinding" bindingConfiguration="netTCPConfig" behaviorConfiguration="telemetry" contract="TestApplication.Wcf.Client.NetFramework.IStatusServiceContract" name="StatusService_Tcp" /> </client> </system.serviceModel> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - <dependentAssembly> - <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> </configuration> diff --git a/test/test-applications/integrations/TestApplication.Wcf.Server.NetFramework/App.config b/test/test-applications/integrations/TestApplication.Wcf.Server.NetFramework/App.config index e0cf1a1a92..7b85082332 100644 --- a/test/test-applications/integrations/TestApplication.Wcf.Server.NetFramework/App.config +++ b/test/test-applications/integrations/TestApplication.Wcf.Server.NetFramework/App.config @@ -38,16 +38,4 @@ </service> </services> </system.serviceModel> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" /> - </dependentAssembly> - <dependentAssembly> - <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> </configuration> \ No newline at end of file