Fix bytecode instrumentation of strong named assemblies (#1153)
* Fix instrumentation of strong-named assemblies * Add strong name where required * Native changes for strong name only on .NET Framework * Doc that StrongNamedValidation is temporary * Add test application to sln * dotnet-format fixes for new cs code * Remove output log from test * Add CHANGELOG.md note
This commit is contained in:
parent
8bfb4ffcb9
commit
4d5167f5da
|
|
@ -10,6 +10,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
### Added
|
||||
|
||||
- Add support for Alpine.
|
||||
- Add strong name signature to the OpenTelemetry.AutoInstrumentation assembly used
|
||||
on the .NET Framework.
|
||||
|
||||
### Changed
|
||||
|
||||
## [0.3.0-beta.1](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/tag/v0.3.0-beta.1)
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.GrpcNetClie
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper", "src\OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper\OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper.csproj", "{C1AEDAE0-6629-4C88-AB35-AB5B81FD50F6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.StrongNamed", "test\test-applications\integrations\TestApplication.StrongNamed\TestApplication.StrongNamed.csproj", "{505A5B7B-930E-42D3-909F-E97C7C247FCF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -586,6 +588,18 @@ Global
|
|||
{C1AEDAE0-6629-4C88-AB35-AB5B81FD50F6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C1AEDAE0-6629-4C88-AB35-AB5B81FD50F6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C1AEDAE0-6629-4C88-AB35-AB5B81FD50F6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|x64.Build.0 = Debug|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Debug|x86.Build.0 = Debug|x86
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|Any CPU.Build.0 = Release|x64
|
||||
{505A5B7B-930E-42D3-909F-E97C7C247FCF}.Release|x64.ActiveCfg = Release|x64
|
||||
{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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -633,6 +647,7 @@ Global
|
|||
{671EB8F0-E164-4E9F-B423-27AF4B59D360} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
{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}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
#include "logger.h"
|
||||
#include "module_metadata.h"
|
||||
#include "otel_profiler_constants.h"
|
||||
#include "cor_profiler.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace trace
|
||||
{
|
||||
|
|
@ -163,7 +168,9 @@ HRESULT CallTargetTokens::EnsureBaseCalltargetTokens()
|
|||
// *** Ensure profiler assembly ref
|
||||
if (profilerAssemblyRef == mdAssemblyRefNil)
|
||||
{
|
||||
const AssemblyReference assemblyReference = *trace::AssemblyReference::GetFromCache(managed_profiler_full_assembly_version);
|
||||
const auto bytecode_instrumentation_name = trace::profiler->GetBytecodeInstrumentationAssembly();
|
||||
Logger::Debug("CallTargetTokens::EnsureBaseCalltargetTokens() Bytecode Instrumentation Assembly: ", bytecode_instrumentation_name);
|
||||
const AssemblyReference assemblyReference = *trace::AssemblyReference::GetFromCache(bytecode_instrumentation_name);
|
||||
ASSEMBLYMETADATA assembly_metadata{};
|
||||
|
||||
assembly_metadata.usMajorVersion = assemblyReference.version.major;
|
||||
|
|
|
|||
|
|
@ -102,6 +102,13 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
// code is ready to get runtime information
|
||||
runtime_information_ = GetRuntimeInformation(this->info_);
|
||||
if (process_name == WStr("w3wp.exe") || process_name == WStr("iisexpress.exe"))
|
||||
{
|
||||
is_desktop_iis = runtime_information_.is_desktop();
|
||||
}
|
||||
|
||||
// get ICorProfilerInfo6 for net46+
|
||||
ICorProfilerInfo6* info6;
|
||||
hr = cor_profiler_info_unknown->QueryInterface(__uuidof(ICorProfilerInfo6), (void**)&info6);
|
||||
|
|
@ -232,11 +239,6 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
runtime_information_ = GetRuntimeInformation(this->info_);
|
||||
if (process_name == WStr("w3wp.exe") || process_name == WStr("iisexpress.exe"))
|
||||
{
|
||||
is_desktop_iis = runtime_information_.is_desktop();
|
||||
}
|
||||
|
||||
// writing opcodes vector for the IL dumper
|
||||
#define OPDEF(c, s, pop, push, args, type, l, s1, s2, flow) opcodes_names.push_back(s);
|
||||
|
|
@ -262,10 +264,16 @@ HRESULT STDMETHODCALLTYPE CorProfiler::AssemblyLoadFinished(AssemblyID assembly_
|
|||
{
|
||||
// if assembly failed to load, skip it entirely,
|
||||
// otherwise we can crash the process if module is not valid
|
||||
Logger::Warn("AssemblyLoadFinished: ", assembly_id, " ", hr_status);
|
||||
CorProfilerBase::AssemblyLoadFinished(assembly_id, hr_status);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (Logger::IsDebugEnabled())
|
||||
{
|
||||
Logger::Debug("AssemblyLoadFinished: ", assembly_id, " ", hr_status);
|
||||
}
|
||||
|
||||
// keep this lock until we are done using the module,
|
||||
// to prevent it from unloading while in use
|
||||
std::lock_guard<std::mutex> guard(module_id_to_info_map_lock_);
|
||||
|
|
@ -279,89 +287,48 @@ HRESULT STDMETHODCALLTYPE CorProfiler::AssemblyLoadFinished(AssemblyID assembly_
|
|||
const auto assembly_info = GetAssemblyInfo(this->info_, assembly_id);
|
||||
if (!assembly_info.IsValid())
|
||||
{
|
||||
Logger::Debug("AssemblyLoadFinished: ", assembly_id, " ", hr_status);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const auto is_instrumentation_assembly = assembly_info.name == WStr("OpenTelemetry.AutoInstrumentation");
|
||||
|
||||
if (is_instrumentation_assembly)
|
||||
const auto is_instrumentation_assembly = assembly_info.name == managed_profiler_name;
|
||||
if (!is_instrumentation_assembly)
|
||||
{
|
||||
if (Logger::IsDebugEnabled())
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (Logger::IsDebugEnabled())
|
||||
{
|
||||
Logger::Debug("AssemblyLoadFinished: Bytecode Instrumentation Assembly: ", GetBytecodeInstrumentationAssembly());
|
||||
}
|
||||
|
||||
ComPtr<IUnknown> metadata_interfaces;
|
||||
auto hr = this->info_->GetModuleMetaData(assembly_info.manifest_module_id, ofRead | ofWrite,
|
||||
IID_IMetaDataImport2, metadata_interfaces.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Logger::Warn("AssemblyLoadFinished failed to get metadata interface for module id ",
|
||||
assembly_info.manifest_module_id, " from assembly ", assembly_info.name);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Get the IMetaDataAssemblyImport interface to get metadata from the managed assembly
|
||||
const auto assembly_import = metadata_interfaces.As<IMetaDataAssemblyImport>(IID_IMetaDataAssemblyImport);
|
||||
const auto assembly_metadata = GetAssemblyImportMetadata(assembly_import);
|
||||
|
||||
managed_profiler_loaded_app_domains.insert(assembly_info.app_domain_id);
|
||||
|
||||
if (runtime_information_.is_desktop() && corlib_module_loaded)
|
||||
{
|
||||
// Set the managed_profiler_loaded_domain_neutral flag whenever the
|
||||
// managed profiler is loaded shared
|
||||
if (assembly_info.app_domain_id == corlib_app_domain_id)
|
||||
{
|
||||
Logger::Debug("AssemblyLoadFinished: ", assembly_id, " ", hr_status);
|
||||
Logger::Info("AssemblyLoadFinished: ", assembly_info.name, " was loaded domain-neutral");
|
||||
managed_profiler_loaded_domain_neutral = true;
|
||||
}
|
||||
|
||||
ComPtr<IUnknown> metadata_interfaces;
|
||||
auto hr = this->info_->GetModuleMetaData(assembly_info.manifest_module_id, ofRead | ofWrite,
|
||||
IID_IMetaDataImport2, metadata_interfaces.GetAddressOf());
|
||||
|
||||
if (FAILED(hr))
|
||||
else
|
||||
{
|
||||
Logger::Warn("AssemblyLoadFinished failed to get metadata interface for module id ",
|
||||
assembly_info.manifest_module_id, " from assembly ", assembly_info.name);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Get the IMetaDataAssemblyImport interface to get metadata from the managed assembly
|
||||
const auto assembly_import = metadata_interfaces.As<IMetaDataAssemblyImport>(IID_IMetaDataAssemblyImport);
|
||||
const auto assembly_metadata = GetAssemblyImportMetadata(assembly_import);
|
||||
|
||||
// used multiple times for logging
|
||||
const auto assembly_version = assembly_metadata.version.str();
|
||||
|
||||
if (Logger::IsDebugEnabled())
|
||||
{
|
||||
Logger::Debug("AssemblyLoadFinished: AssemblyName=", assembly_info.name,
|
||||
" AssemblyVersion=", assembly_version);
|
||||
}
|
||||
|
||||
if (is_instrumentation_assembly)
|
||||
{
|
||||
const auto expected_assembly_reference = trace::AssemblyReference(managed_profiler_full_assembly_version);
|
||||
|
||||
// used multiple times for logging
|
||||
const auto expected_version = expected_assembly_reference.version.str();
|
||||
|
||||
bool is_viable_version;
|
||||
|
||||
if (runtime_information_.is_core())
|
||||
{
|
||||
is_viable_version = (assembly_metadata.version >= expected_assembly_reference.version);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_viable_version = (assembly_metadata.version == expected_assembly_reference.version);
|
||||
}
|
||||
|
||||
// Check that Major.Minor.Build matches the profiler version.
|
||||
// On .NET Core, allow managed library to be a higher version than the native library.
|
||||
if (is_viable_version)
|
||||
{
|
||||
Logger::Info("AssemblyLoadFinished: OpenTelemetry.AutoInstrumentation.dll v", assembly_version,
|
||||
" matched profiler version v", expected_version);
|
||||
managed_profiler_loaded_app_domains.insert(assembly_info.app_domain_id);
|
||||
|
||||
if (runtime_information_.is_desktop() && corlib_module_loaded)
|
||||
{
|
||||
// Set the managed_profiler_loaded_domain_neutral flag whenever the
|
||||
// managed profiler is loaded shared
|
||||
if (assembly_info.app_domain_id == corlib_app_domain_id)
|
||||
{
|
||||
Logger::Info("AssemblyLoadFinished: OpenTelemetry.AutoInstrumentation.dll was loaded domain-neutral");
|
||||
managed_profiler_loaded_domain_neutral = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Info("AssemblyLoadFinished: OpenTelemetry.AutoInstrumentation.dll was not loaded domain-neutral");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Warn("AssemblyLoadFinished: OpenTelemetry.AutoInstrumentation.dll v", assembly_version,
|
||||
" did not match profiler version v", expected_version);
|
||||
}
|
||||
Logger::Info("AssemblyLoadFinished: ", assembly_info.name, " was not loaded domain-neutral");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -928,6 +895,22 @@ bool CorProfiler::IsAttached() const
|
|||
return is_attached_;
|
||||
}
|
||||
|
||||
WSTRING CorProfiler::GetBytecodeInstrumentationAssembly() const
|
||||
{
|
||||
WSTRING bytecodeInstrumentationAssembly = managed_profiler_full_assembly_version;
|
||||
if (!runtime_information_.runtime_type)
|
||||
{
|
||||
Logger::Error("GetBytecodeInstrumentationAssembly: called before runtime_information was initialized.");
|
||||
}
|
||||
else if (!runtime_information_.is_core())
|
||||
{
|
||||
// When on .NET Framework use the signature with the public key so strong name works.
|
||||
bytecodeInstrumentationAssembly = managed_profiler_full_assembly_version_strong_name;
|
||||
}
|
||||
|
||||
return bytecodeInstrumentationAssembly;
|
||||
}
|
||||
|
||||
//
|
||||
// Helper methods
|
||||
//
|
||||
|
|
@ -985,15 +968,22 @@ bool CorProfiler::GetWrapperMethodRef(ModuleMetadata* module_metadata, ModuleID
|
|||
module_metadata->metadata_emit, module_metadata->assembly_import,
|
||||
module_metadata->assembly_emit);
|
||||
|
||||
const AssemblyReference* wrapper_assembly = &method_replacement.wrapper_method.assembly;
|
||||
if (wrapper_assembly->name == managed_profiler_name)
|
||||
{
|
||||
// Handle the typical case in which the wrapper is also the bytecode instrumentation assembly.
|
||||
wrapper_assembly = AssemblyReference::GetFromCache(GetBytecodeInstrumentationAssembly());
|
||||
}
|
||||
|
||||
// for each wrapper assembly, emit an assembly reference
|
||||
hr = metadata_builder.EmitAssemblyRef(method_replacement.wrapper_method.assembly);
|
||||
hr = metadata_builder.EmitAssemblyRef(*wrapper_assembly);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Logger::Warn("JITCompilationStarted failed to emit wrapper assembly ref for assembly=",
|
||||
method_replacement.wrapper_method.assembly.name,
|
||||
", Version=", method_replacement.wrapper_method.assembly.version.str(),
|
||||
", Culture=", method_replacement.wrapper_method.assembly.locale,
|
||||
" PublicKeyToken=", method_replacement.wrapper_method.assembly.public_key.str());
|
||||
wrapper_assembly->name,
|
||||
", Version=", wrapper_assembly->version.str(),
|
||||
", Culture=", wrapper_assembly->locale,
|
||||
" PublicKeyToken=", wrapper_assembly->public_key.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ public:
|
|||
|
||||
bool IsAttached() const;
|
||||
|
||||
WSTRING GetBytecodeInstrumentationAssembly() const;
|
||||
|
||||
void GetAssemblyAndSymbolsBytes(BYTE** pAssemblyArray, int* assemblySize, BYTE** pSymbolsArray,
|
||||
int* symbolsSize) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,10 +76,13 @@ const WSTRING mscorlib_assemblyName = WStr("mscorlib");
|
|||
const WSTRING system_private_corelib_assemblyName = WStr("System.Private.CoreLib");
|
||||
const WSTRING opentelemetry_autoinstrumentation_loader_assemblyName = WStr("OpenTelemetry.AutoInstrumentation.Loader");
|
||||
|
||||
const WSTRING managed_profiler_name = WStr("OpenTelemetry.AutoInstrumentation");
|
||||
|
||||
const WSTRING managed_profiler_full_assembly_version =
|
||||
WStr("OpenTelemetry.AutoInstrumentation, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
|
||||
const WSTRING managed_profiler_name = WStr("OpenTelemetry.AutoInstrumentation");
|
||||
const WSTRING managed_profiler_full_assembly_version_strong_name =
|
||||
WStr("OpenTelemetry.AutoInstrumentation, Version=0.3.0.0, Culture=neutral, PublicKeyToken=c0db600a13f60b51");
|
||||
|
||||
const WSTRING nonwindows_nativemethods_type = WStr("OpenTelemetry.AutoInstrumentation.NativeMethods+NonWindows");
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
// <copyright file="StrongNamedValidation.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using OpenTelemetry.AutoInstrumentation.CallTarget;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Validations
|
||||
{
|
||||
/// <summary>
|
||||
/// Instrumentation targeting the test application used to validate the strong name scenario.
|
||||
/// When an actual bytecode instrumentation targeting a strong named assembly on .NET Framework
|
||||
/// is added we can remove this instrumentation.
|
||||
/// </summary>
|
||||
[InstrumentMethod(
|
||||
AssemblyName = "TestApplication.StrongNamed",
|
||||
TypeName = "TestApplication.StrongNamed.Command",
|
||||
MethodName = "Execute",
|
||||
ReturnTypeName = ClrNames.Void,
|
||||
ParameterTypeNames = new string[0],
|
||||
MinimumVersion = "1.0.0",
|
||||
MaximumVersion = "1.65535.65535",
|
||||
IntegrationName = "StrongNamedValidation")]
|
||||
public class StrongNamedValidation
|
||||
{
|
||||
private static readonly ActivitySource ValidationActivitySource = new ActivitySource("TestApplication.StrongNamedValidation");
|
||||
|
||||
/// <summary>
|
||||
/// OnMethodBegin callback.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">Type of the target</typeparam>
|
||||
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
|
||||
/// <returns>Calltarget state value</returns>
|
||||
public static CallTargetState OnMethodBegin<TTarget>(TTarget instance)
|
||||
{
|
||||
using var activity = ValidationActivitySource.StartActivity(nameof(StrongNamedValidation));
|
||||
activity.AddTag("validation", nameof(StrongNamedValidation));
|
||||
|
||||
Console.WriteLine($"Validation: {nameof(StrongNamedValidation)}");
|
||||
|
||||
return CallTargetState.GetDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// <copyright file="AssemblyInfo.NetFramework.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyKeyFileAttribute("keypair.snk")]
|
||||
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.AutoInstrumentation.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001008db7c66f4ebdc6aac4196be5ce1ff4b59b020028e6dbd6e46f15aa40b3215975b92d0a8e45aba5f36114a8cb56241fbfa49f4c017e6c62197857e4e9f62451bc23d3a660e20861f95a57f23e20c77d413ad216ff1bb55f94104d4c501e32b03219d8603fb6fa73401c6ae6808c8daa61b9eaee5d2377d3c23c9ca6016c6582d8")]
|
||||
[assembly: InternalsVisibleTo("IntegrationTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001008db7c66f4ebdc6aac4196be5ce1ff4b59b020028e6dbd6e46f15aa40b3215975b92d0a8e45aba5f36114a8cb56241fbfa49f4c017e6c62197857e4e9f62451bc23d3a660e20861f95a57f23e20c77d413ad216ff1bb55f94104d4c501e32b03219d8603fb6fa73401c6ae6808c8daa61b9eaee5d2377d3c23c9ca6016c6582d8")]
|
||||
|
||||
#endif
|
||||
|
|
@ -14,8 +14,10 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper")]
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.AutoInstrumentation.Tests")]
|
||||
[assembly: InternalsVisibleTo("IntegrationTests")]
|
||||
#endif
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
|||
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyKeyFileAttribute("test-keypair.snk")]
|
||||
|
|
@ -30,4 +30,8 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)GlobalSuppressions.cs" Link="GlobalSuppressions.test.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Strong name conditional to limit it only to required projects -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net4')) and '$(AddTestStrongNameAssemblyKeyOnNetFramework)' == 'true'">
|
||||
<Compile Include="$(MSBuildThisFileDirectory)AssemblyInfo.cs" Link="AssemblyInfo.StrongName.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -207,9 +207,9 @@ public class EnvironmentHelper
|
|||
environmentVariables["OTEL_DOTNET_AUTO_INCLUDE_PROCESSES"] = Path.GetFileName(processToProfile);
|
||||
}
|
||||
|
||||
string integrations = GetIntegrationsPath();
|
||||
environmentVariables["OTEL_DOTNET_AUTO_HOME"] = GetNukeBuildOutput();
|
||||
environmentVariables["OTEL_DOTNET_AUTO_INTEGRATIONS_FILE"] = integrations;
|
||||
|
||||
environmentVariables["OTEL_DOTNET_AUTO_INTEGRATIONS_FILE"] = Environment.GetEnvironmentVariable("OTEL_DOTNET_AUTO_INTEGRATIONS_FILE") ?? GetIntegrationsPath();
|
||||
|
||||
if (testSettings.TracesSettings != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Containers;
|
||||
|
|
@ -47,6 +48,23 @@ public abstract class TestHelper
|
|||
|
||||
protected ITestOutputHelper Output { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path for the test assembly, not the shadow copy created by xunit.
|
||||
/// </summary>
|
||||
public string GetTestAssemblyPath()
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
// CodeBase is deprecated outside .NET Framework, instead of suppressing the error
|
||||
// build the code as per recommendation for each runtime.
|
||||
var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
|
||||
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
|
||||
var directory = Path.GetDirectoryName(codeBasePath);
|
||||
return Path.GetFullPath(directory);
|
||||
#else
|
||||
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
#endif
|
||||
}
|
||||
|
||||
public async Task<Container> StartContainerAsync(TestSettings testSettings, int webPort)
|
||||
{
|
||||
// get path to test application that the profiler will attach to
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<PropertyGroup>
|
||||
<AddTestStrongNameAssemblyKeyOnNetFramework>true</AddTestStrongNameAssemblyKeyOnNetFramework>
|
||||
<DisableStrongNamer Condition="!$(TargetFramework.StartsWith('net4'))">true</DisableStrongNamer>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.5" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.48.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="StrongNamer" Version="0.2.5" Condition="$(TargetFramework.StartsWith('net4'))" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
|
||||
<PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
|
||||
|
|
@ -21,4 +26,10 @@
|
|||
<!-- GrpcServices is 'none' so that we do not need to depend on the grpc nuget package, and we only need protobuf support. -->
|
||||
<Protobuf Include="opentelemetry\**\*.proto" GrpcServices="none" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="StrongNamedTestsIntegrations.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
// <copyright file="StrongNamedTests.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
using FluentAssertions.Execution;
|
||||
using IntegrationTests.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace IntegrationTests;
|
||||
|
||||
public class StrongNamedTests : TestHelper
|
||||
{
|
||||
public StrongNamedTests(ITestOutputHelper output)
|
||||
: base("StrongNamed", output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SubmitsTraces()
|
||||
{
|
||||
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 = agent.WaitForSpans(expectedSpansCount, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
spans.Count.Should().Be(expectedSpansCount);
|
||||
|
||||
spans.Count(s => s.Tags["validation"] == "StrongNamedValidation").Should().Be(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
[
|
||||
{
|
||||
"name": "StrongNamedTests",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
"target": {
|
||||
"assembly": "TestApplication.StrongNamed",
|
||||
"type": "TestApplication.StrongNamed.Command",
|
||||
"method": "Execute",
|
||||
"signature_types": [
|
||||
"System.Void"
|
||||
],
|
||||
"minimum_major": 1,
|
||||
"minimum_minor": 0,
|
||||
"minimum_patch": 0,
|
||||
"maximum_major": 1,
|
||||
"maximum_minor": 65535,
|
||||
"maximum_patch": 65535
|
||||
},
|
||||
"wrapper": {
|
||||
"assembly": "OpenTelemetry.AutoInstrumentation",
|
||||
"type": "OpenTelemetry.AutoInstrumentation.Instrumentations.Validations.StrongNamedValidation",
|
||||
"action": "CallTargetModification"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
|
|
@ -1,5 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AddTestStrongNameAssemblyKeyOnNetFramework>true</AddTestStrongNameAssemblyKeyOnNetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\OpenTelemetry.AutoInstrumentation\OpenTelemetry.AutoInstrumentation.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,28 @@
|
|||
// <copyright file="Command.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace TestApplication.StrongNamed;
|
||||
|
||||
public class Command
|
||||
{
|
||||
public void Execute()
|
||||
{
|
||||
Thread.Yield(); // Just to have some call to outside code.
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// <copyright file="Program.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyKeyFileAttribute("keypair.snk")]
|
||||
|
||||
namespace TestApplication.StrongNamed;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var command = new Command();
|
||||
command.Execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Binary file not shown.
Loading…
Reference in New Issue