diff --git a/OpenTelemetry.AutoInstrumentation.sln b/OpenTelemetry.AutoInstrumentation.sln index 049c6cb74c..b138a82029 100644 --- a/OpenTelemetry.AutoInstrumentation.sln +++ b/OpenTelemetry.AutoInstrumentation.sln @@ -145,6 +145,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Wcf.Shared" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Logs", "test\test-applications\integrations\TestApplication.Logs\TestApplication.Logs.csproj", "{8C52B9DD-880B-4CD5-AB18-A4C462C714E9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLibrary.InstrumentationTarget", "test\test-applications\integrations\dependency-libs\TestLibrary.InstrumentationTarget\TestLibrary.InstrumentationTarget.csproj", "{1DC12784-CD32-400D-AE13-A637BFA66B1B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.DomainNeutral", "test\test-applications\integrations\TestApplication.DomainNeutral\TestApplication.DomainNeutral.csproj", "{28879377-2043-4370-A8DB-B04464B6E552}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -605,6 +609,30 @@ Global {505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|x64.Build.0 = Release|x64 {505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|x86.ActiveCfg = Release|x86 {505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|x86.Build.0 = Release|x86 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|Any CPU.ActiveCfg = Debug|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|Any CPU.Build.0 = Debug|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|x64.ActiveCfg = Debug|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|x64.Build.0 = Debug|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|x86.ActiveCfg = Debug|x86 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Debug|x86.Build.0 = Debug|x86 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|Any CPU.ActiveCfg = Release|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|Any CPU.Build.0 = Release|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|x64.ActiveCfg = Release|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|x64.Build.0 = Release|x64 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|x86.ActiveCfg = Release|x86 + {1DC12784-CD32-400D-AE13-A637BFA66B1B}.Release|x86.Build.0 = Release|x86 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|Any CPU.ActiveCfg = Debug|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|Any CPU.Build.0 = Debug|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|x64.ActiveCfg = Debug|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|x64.Build.0 = Debug|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|x86.ActiveCfg = Debug|x86 + {28879377-2043-4370-A8DB-B04464B6E552}.Debug|x86.Build.0 = Debug|x86 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|Any CPU.ActiveCfg = Release|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|Any CPU.Build.0 = Release|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|x64.ActiveCfg = Release|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|x64.Build.0 = Release|x64 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|x86.ActiveCfg = Release|x86 + {28879377-2043-4370-A8DB-B04464B6E552}.Release|x86.Build.0 = Release|x86 {5BFB9A97-A83F-4719-A35B-6421364B9820}.Debug|Any CPU.ActiveCfg = Debug|x64 {5BFB9A97-A83F-4719-A35B-6421364B9820}.Debug|Any CPU.Build.0 = Debug|x64 {5BFB9A97-A83F-4719-A35B-6421364B9820}.Debug|x64.ActiveCfg = Debug|x64 @@ -712,6 +740,8 @@ Global {0605872C-AB2B-4167-9B00-A525090D10BE} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {C1AEDAE0-6629-4C88-AB35-AB5B81FD50F6} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} {505A5B7B-930E-42D3-909F-E97C7C247FCF} = {E409ADD3-9574-465C-AB09-4324D205CC7C} + {1DC12784-CD32-400D-AE13-A637BFA66B1B} = {82A3CE96-0935-45E5-A9AA-A93A5B63500B} + {28879377-2043-4370-A8DB-B04464B6E552} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {5BFB9A97-A83F-4719-A35B-6421364B9820} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {ACB51ACB-82E6-4CA8-B233-2C05A5CEDE01} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {F7ACC09E-899F-4D47-BA1D-4009FB76F6AA} = {E409ADD3-9574-465C-AB09-4324D205CC7C} diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp index 26eee858aa..0214aa1a37 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp +++ b/src/OpenTelemetry.AutoInstrumentation.Native/cor_profiler.cpp @@ -454,7 +454,7 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, HR if (Logger::IsDebugEnabled()) { Logger::Debug("ModuleLoadFinished: ", module_id, " ", module_info.assembly.name, " AppDomain ", - module_info.assembly.app_domain_id, " ", module_info.assembly.app_domain_name, + module_info.assembly.app_domain_id, " [", module_info.assembly.app_domain_name, "] ", std::boolalpha, " | IsNGEN = ", module_info.IsNGEN(), " | IsDynamic = ", module_info.IsDynamic(), @@ -511,8 +511,8 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, HR // In this case, do not insert another startup hook into that non-shared AppDomain if (module_info.assembly.name == opentelemetry_autoinstrumentation_loader_assemblyName) { - Logger::Info("ModuleLoadFinished: OpenTelemetry.AutoInstrumentation.Loader loaded into AppDomain ", app_domain_id, " ", - module_info.assembly.app_domain_name); + Logger::Info("ModuleLoadFinished: OpenTelemetry.AutoInstrumentation.Loader loaded into AppDomain ", app_domain_id, " [", + module_info.assembly.app_domain_name, "]"); first_jit_compilation_app_domains.insert(app_domain_id); return S_OK; } @@ -583,7 +583,7 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, HR CallTarget_RequestRejitForModule(module_id, module_metadata, integration_methods_); Logger::Debug("ModuleLoadFinished stored metadata for ", module_id, " ", module_info.assembly.name, " AppDomain ", - module_info.assembly.app_domain_id, " ", module_info.assembly.app_domain_name); + module_info.assembly.app_domain_id, " [", module_info.assembly.app_domain_name, "]"); #ifndef _WIN32 // Fix PInvokeMap (Non windows only) @@ -614,7 +614,7 @@ HRESULT STDMETHODCALLTYPE CorProfiler::ModuleUnloadStarted(ModuleID module_id) if (module_info.IsValid()) { Logger::Debug("ModuleUnloadStarted: ", module_id, " ", module_info.assembly.name, " AppDomain ", - module_info.assembly.app_domain_id, " ", module_info.assembly.app_domain_name); + module_info.assembly.app_domain_id, " [", module_info.assembly.app_domain_name, "]"); } else { diff --git a/src/OpenTelemetry.AutoInstrumentation/Instrumentations/StrongNamedValidation/StrongNamedValidation.cs b/src/OpenTelemetry.AutoInstrumentation/Instrumentations/StrongNamedValidation/StrongNamedValidation.cs index 9088a45ced..f527f3c192 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Instrumentations/StrongNamedValidation/StrongNamedValidation.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Instrumentations/StrongNamedValidation/StrongNamedValidation.cs @@ -26,8 +26,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Validations /// is added we can remove this instrumentation. /// [InstrumentMethod( - AssemblyName = "TestApplication.StrongNamed", - TypeName = "TestApplication.StrongNamed.Command", + AssemblyName = "TestLibrary.InstrumentationTarget", + TypeName = "TestLibrary.InstrumentationTarget.Command", MethodName = "Execute", ReturnTypeName = ClrNames.Void, ParameterTypeNames = new string[0], diff --git a/test/IntegrationTests/DomainNeutralTests.cs b/test/IntegrationTests/DomainNeutralTests.cs new file mode 100644 index 0000000000..521fe974d8 --- /dev/null +++ b/test/IntegrationTests/DomainNeutralTests.cs @@ -0,0 +1,76 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if NETFRAMEWORK +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using FluentAssertions.Execution; +using IntegrationTests.Helpers; +using Xunit; +using Xunit.Abstractions; + +namespace IntegrationTests; + +public class DomainNeutralTests : TestHelper +{ + public DomainNeutralTests(ITestOutputHelper output) + : base("DomainNeutral", output) + { + } + + [Fact] + [Trait("Category", "EndToEnd")] + public async Task SubmitsTraces() + { + EnvironmentTools.IsWindowsAdministrator().Should().BeTrue(); + + // Add the necessary assembly to the GAC so it can be loaded as domain-neutral. + var instrumentationAssembly = Path.Combine( + EnvironmentTools.GetSolutionDirectory(), + "bin", + "tracer-home", + "net462", + "OpenTelemetry.AutoInstrumentation.dll"); + File.Exists(instrumentationAssembly).Should().BeTrue(); + using var gacEntry = new GacEntry(instrumentationAssembly); + + // Domain-neutral depends on strong named assemblies to work, leverage some assets from + // strong name testing in the current test. + var assemblyPath = GetTestAssemblyPath(); + var integrationsFile = Path.Combine(assemblyPath, "StrongNamedTestsIntegrations.json"); + File.Exists(integrationsFile).Should().BeTrue(); + + SetEnvironmentVariable("OTEL_DOTNET_AUTO_INTEGRATIONS_FILE", integrationsFile); + + using var agent = new MockZipkinCollector(Output); + + RunTestApplication(agent.Port); + + const int expectedSpansCount = 1; + var spans = await agent.WaitForSpansAsync(expectedSpansCount, TimeSpan.FromSeconds(5)); + + using (new AssertionScope()) + { + spans.Count.Should().Be(expectedSpansCount); + + spans.Count(s => s.Tags["validation"] == "StrongNamedValidation").Should().Be(1); + } + } +} +#endif diff --git a/test/IntegrationTests/Helpers/GacEntry.cs b/test/IntegrationTests/Helpers/GacEntry.cs new file mode 100644 index 0000000000..1faaaad352 --- /dev/null +++ b/test/IntegrationTests/Helpers/GacEntry.cs @@ -0,0 +1,39 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if NETFRAMEWORK +using System; +using System.EnterpriseServices.Internal; + +namespace IntegrationTests.Helpers; + +public class GacEntry : IDisposable +{ + private readonly string _assemblyPath; + private readonly Publish _publish = new Publish(); + + public GacEntry(string assemblyPath) + { + _assemblyPath = assemblyPath; + _publish.GacInstall(assemblyPath); + } + + public void Dispose() + { + _publish.GacRemove(_assemblyPath); + } +} +#endif diff --git a/test/IntegrationTests/IntegrationTests.csproj b/test/IntegrationTests/IntegrationTests.csproj index ec1b31c7e4..86ff1a8011 100644 --- a/test/IntegrationTests/IntegrationTests.csproj +++ b/test/IntegrationTests/IntegrationTests.csproj @@ -2,13 +2,16 @@ true - true _WINDOWS + + + + diff --git a/test/IntegrationTests/StrongNamedTestsIntegrations.json b/test/IntegrationTests/StrongNamedTestsIntegrations.json index 5d945cbd4e..b2a25de7b7 100644 --- a/test/IntegrationTests/StrongNamedTestsIntegrations.json +++ b/test/IntegrationTests/StrongNamedTestsIntegrations.json @@ -5,8 +5,8 @@ { "caller": {}, "target": { - "assembly": "TestApplication.StrongNamed", - "type": "TestApplication.StrongNamed.Command", + "assembly": "TestLibrary.InstrumentationTarget", + "type": "TestLibrary.InstrumentationTarget.Command", "method": "Execute", "signature_types": [ "System.Void" diff --git a/test/test-applications/integrations/TestApplication.DomainNeutral/Program.cs b/test/test-applications/integrations/TestApplication.DomainNeutral/Program.cs new file mode 100644 index 0000000000..584fe7e10f --- /dev/null +++ b/test/test-applications/integrations/TestApplication.DomainNeutral/Program.cs @@ -0,0 +1,42 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Reflection; + +namespace TestApplication.DomainNeutral; + +using TestLibrary.InstrumentationTarget; + +public static class Program +{ + [LoaderOptimization(LoaderOptimization.MultiDomain)] + public static void Main(string[] args) + { + var command = new Command(); + command.Execute(); + + // Instrumentation assembly is expected to be already loaded from the GAC at this point. + var instrumentationAssembly = Assembly.Load("OpenTelemetry.AutoInstrumentation") ?? throw new Exception("Instrumentation assembly was not loaded."); + +#if NETFRAMEWORK + if (!instrumentationAssembly.GlobalAssemblyCache) + { + throw new Exception("Instrumentation assembly was not loaded from the GAC"); + } +#endif + } +} diff --git a/test/test-applications/integrations/TestApplication.DomainNeutral/TestApplication.DomainNeutral.csproj b/test/test-applications/integrations/TestApplication.DomainNeutral/TestApplication.DomainNeutral.csproj new file mode 100644 index 0000000000..1f61c69b8f --- /dev/null +++ b/test/test-applications/integrations/TestApplication.DomainNeutral/TestApplication.DomainNeutral.csproj @@ -0,0 +1,12 @@ + + + + Exe + true + + + + + + + diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/keypair.snk b/test/test-applications/integrations/TestApplication.DomainNeutral/test-keypair.snk similarity index 100% rename from test/test-applications/integrations/TestApplication.StrongNamed/keypair.snk rename to test/test-applications/integrations/TestApplication.DomainNeutral/test-keypair.snk diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/Program.cs b/test/test-applications/integrations/TestApplication.StrongNamed/Program.cs index c9eb90f457..10d4347537 100644 --- a/test/test-applications/integrations/TestApplication.StrongNamed/Program.cs +++ b/test/test-applications/integrations/TestApplication.StrongNamed/Program.cs @@ -14,10 +14,7 @@ // limitations under the License. // -using System; -using System.Reflection; - -[assembly: AssemblyKeyFileAttribute("keypair.snk")] +using TestLibrary.InstrumentationTarget; namespace TestApplication.StrongNamed; diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/TestApplication.StrongNamed.csproj b/test/test-applications/integrations/TestApplication.StrongNamed/TestApplication.StrongNamed.csproj index 52e6553de6..1f61c69b8f 100644 --- a/test/test-applications/integrations/TestApplication.StrongNamed/TestApplication.StrongNamed.csproj +++ b/test/test-applications/integrations/TestApplication.StrongNamed/TestApplication.StrongNamed.csproj @@ -2,6 +2,11 @@ Exe + true + + + + diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/test-keypair.snk b/test/test-applications/integrations/TestApplication.StrongNamed/test-keypair.snk new file mode 100644 index 0000000000..f15bcd3b28 Binary files /dev/null and b/test/test-applications/integrations/TestApplication.StrongNamed/test-keypair.snk differ diff --git a/test/test-applications/integrations/TestApplication.StrongNamed/Command.cs b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/Command.cs similarity index 94% rename from test/test-applications/integrations/TestApplication.StrongNamed/Command.cs rename to test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/Command.cs index 8b32128cc9..7cb4cbf708 100644 --- a/test/test-applications/integrations/TestApplication.StrongNamed/Command.cs +++ b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/Command.cs @@ -14,10 +14,9 @@ // limitations under the License. // -using System; using System.Threading; -namespace TestApplication.StrongNamed; +namespace TestLibrary.InstrumentationTarget; public class Command { diff --git a/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/TestLibrary.InstrumentationTarget.csproj b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/TestLibrary.InstrumentationTarget.csproj new file mode 100644 index 0000000000..37b95ae8cf --- /dev/null +++ b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/TestLibrary.InstrumentationTarget.csproj @@ -0,0 +1,8 @@ + + + + Library + true + + + diff --git a/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/test-keypair.snk b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/test-keypair.snk new file mode 100644 index 0000000000..f15bcd3b28 Binary files /dev/null and b/test/test-applications/integrations/dependency-libs/TestLibrary.InstrumentationTarget/test-keypair.snk differ