Automatic LoaderOptimization.SingleDomain (#4187)
* All non-default app domains use LoaderOptimization.SingleDomain Solves "Loading this assembly would produce a different grant set from other instances" for IIS .Net Framework applications. __DDVoidMethodType__ injected to mscorlib. __DDVoidMethodType__.__DDPatchAppDomainSetup__ use reflection-created delegate that calls OpenTelemetry.AutoInstrumentation.Loader.AppConfigUpdater.ModifyConfig to modify AppDomainSetup by setting LoaderOptimization.SingleDomain. That method called from AppDomain.CreateDomain and AppDomainManager.CreateDomainHelper. OpenTelemetry.AutoInstrumentation.Loader.AppConfigUpdater loader assembly loaded from __DDVoidMethodType__ static ctor. Added helpers: SignatureBuilder and MemberResolver. * Added installer parameter to skip GAC registration Added Asp.Net tests without registration assemblies in GAC. Removed LoaderOptimization=SingleDomain through registry change for ASP.Net tests. * Removed LoaderOptimization workaround from test dockerfiles * Code format applied * Updated test build to produce no-GAC docker images * Extended SignatureBuilder by providing semi-safe wrappers Moved it to be header-only. Added unit tests for SignatureBuilder. * Updated change log and documentation * Removed Troubleshooting link from IIS instrumentation docs * Fixed accident docker file changes * Added comment about callers of AppConfigUpdater.ModifyConfig * Update CHANGELOG.md typo based on review Co-authored-by: Chris Ventura <45495992+nrcventura@users.noreply.github.com> * Smaller cleanups * Minor names/comments changes based on @zacharycmontoya review * Fixed formatting * Make AppConfigUpdater internal --------- Co-authored-by: Chris Ventura <45495992+nrcventura@users.noreply.github.com>
This commit is contained in:
parent
35976eafc7
commit
6e307db05b
|
@ -11,11 +11,16 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|||
|
||||
- Support for [`Npgsql`](https://www.nuget.org/packages/Npgsql/)
|
||||
metrics instrumentation for versions `6.0.0`+.
|
||||
- In install script, Install-OpenTelemetryCore accepts optional argument RegisterAssembliesInGAC,
|
||||
which is true by default. When set to false, assemblies would not be installed in GAC.
|
||||
- In install script, new function added: Register-AssembliesInGAC. It installs OpenTelemetry assemblies
|
||||
and dependencies in GAC.
|
||||
|
||||
### Changed
|
||||
|
||||
- `otel-dotnet-auto-install.sh` now optionally uses `wget` instead of `curl`,
|
||||
improving compatibility with `mcr.microsoft.com/dotnet/runtime` Alpine images.
|
||||
- Non-default application domains will be forced to load with LoaderOptimization.SingleDomain
|
||||
|
||||
#### Dependency updates
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ partial class Build
|
|||
.Executes(() =>
|
||||
{
|
||||
var aspNetProject = Solution.GetProjectByName(Projects.Tests.Applications.AspNet);
|
||||
BuildDockerImage(aspNetProject, "integrated", "classic");
|
||||
BuildDockerImage(aspNetProject, "integrated-nogac", "classic-nogac", "integrated", "classic");
|
||||
|
||||
var wcfProject = Solution.GetProjectByName(Projects.Tests.Applications.WcfIis);
|
||||
BuildDockerImage(wcfProject);
|
||||
|
|
|
@ -99,7 +99,3 @@ application pool.
|
|||
1. Close all external windows and press 'Apply' in the main
|
||||
'Configuration Editor' view.
|
||||
1. Restart your application.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [`troubleshooting.md`](troubleshooting.md#iis---loading-this-assembly-would-produce-a-different-grant-set-from-other-instances).
|
||||
|
|
|
@ -232,23 +232,3 @@ Sample Diagnostic Output:
|
|||
For resolving runtime store assembly version conflicts, follow the same solution
|
||||
as outlined for [Assembly version conflicts](#assembly-version-conflicts) in
|
||||
this document.
|
||||
|
||||
### IIS - Loading this assembly would produce a different grant set from other instances
|
||||
|
||||
#### Symptoms
|
||||
|
||||
.NET Framework, IIS hosted application crashes and you get an event similar to
|
||||
the following:
|
||||
|
||||
```log
|
||||
Exception: System.IO.FileLoadException
|
||||
|
||||
Message: Loading this assembly would produce a different grant set from other instances.
|
||||
```
|
||||
|
||||
#### Solution
|
||||
|
||||
Create a new `DWORD` value called `LoaderOptimization` and give it the value `1`
|
||||
under the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework`.
|
||||
It will allows to load different versions of the same application to different domains.
|
||||
It might increase CPU and memory usage.
|
||||
|
|
|
@ -295,6 +295,36 @@ function Is-Greater-Version($v1, $v2) {
|
|||
return $false;
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs OpenTelemetry .NET Assemblies in GAC.
|
||||
.PARAMETER InstallDir
|
||||
Default: <auto> - the default path is Program Files dir.
|
||||
Install path of the OpenTelemetry .NET Automatic Instrumentation
|
||||
Possible values: <auto>, (Custom path)
|
||||
#>
|
||||
function Register-AssembliesInGAC() {
|
||||
$installDir = Get-Current-InstallDir
|
||||
|
||||
# Register .NET Framework dlls in GAC
|
||||
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null
|
||||
$publish = New-Object System.EnterpriseServices.Internal.Publish
|
||||
$dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File
|
||||
for ($i = 0; $i -lt $dlls.Count; $i++) {
|
||||
$percentageComplete = $i / $dlls.Count * 100
|
||||
Write-Progress -Activity "Registering .NET Framework dlls in GAC" `
|
||||
-Status "Module $($i+1) out of $($dlls.Count). Installing $($dlls[$i].Name):" `
|
||||
-PercentComplete $percentageComplete
|
||||
|
||||
if (Test-AssemblyNotForGAC $dlls[$i].Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
$publish.GacInstall($dlls[$i].FullName)
|
||||
}
|
||||
Write-Progress -Activity "Registering .NET Framework dlls in GAC" -Status "Ready" -Completed
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs OpenTelemetry .NET Automatic Instrumentation.
|
||||
|
@ -308,7 +338,9 @@ function Install-OpenTelemetryCore() {
|
|||
[Parameter(Mandatory = $false)]
|
||||
[string]$InstallDir = "<auto>",
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$LocalPath
|
||||
[string]$LocalPath,
|
||||
[Parameter(Mandatory = $false)]
|
||||
[bool]$RegisterAssembliesInGAC = $true
|
||||
)
|
||||
|
||||
$version = "v{{VERSION}}"
|
||||
|
@ -332,23 +364,9 @@ function Install-OpenTelemetryCore() {
|
|||
# OpenTelemetry service locator
|
||||
[System.Environment]::SetEnvironmentVariable($ServiceLocatorVariable, $installDir, [System.EnvironmentVariableTarget]::Machine)
|
||||
|
||||
# Register .NET Framework dlls in GAC
|
||||
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null
|
||||
$publish = New-Object System.EnterpriseServices.Internal.Publish
|
||||
$dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File
|
||||
for ($i = 0; $i -lt $dlls.Count; $i++) {
|
||||
$percentageComplete = $i / $dlls.Count * 100
|
||||
Write-Progress -Activity "Registering .NET Framework dlls in GAC" `
|
||||
-Status "Module $($i+1) out of $($dlls.Count). Installing $($dlls[$i].Name):" `
|
||||
-PercentComplete $percentageComplete
|
||||
|
||||
if (Test-AssemblyNotForGAC $dlls[$i].Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
$publish.GacInstall($dlls[$i].FullName)
|
||||
if ($RegisterAssembliesInGAC){
|
||||
Register-AssembliesInGAC $installDir
|
||||
}
|
||||
Write-Progress -Activity "Registering .NET Framework dlls in GAC" -Status "Ready" -Completed
|
||||
}
|
||||
catch {
|
||||
$message = $_
|
||||
|
@ -406,7 +424,9 @@ function Uninstall-OpenTelemetryCore() {
|
|||
function Update-OpenTelemetryCore() {
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[bool]$RegisterIIS = $false
|
||||
[bool]$RegisterIIS = $false,
|
||||
[Parameter(Mandatory = $false)]
|
||||
[bool]$RegisterAssembliesInGAC = $true
|
||||
)
|
||||
|
||||
$currentInstallVersion = Get-OpenTelemetryInstallVersion
|
||||
|
@ -436,7 +456,7 @@ function Update-OpenTelemetryCore() {
|
|||
Remove-Module OpenTelemetry.Dotnet.Auto
|
||||
Import-Module $modulePath
|
||||
|
||||
Install-OpenTelemetryCore -InstallDir $installDir
|
||||
Install-OpenTelemetryCore -InstallDir $installDir -RegisterAssembliesInGAC $$RegisterAssembliesInGAC
|
||||
if ($RegisterIIS) {
|
||||
Register-OpenTelemetryForIIS
|
||||
}
|
||||
|
@ -660,3 +680,4 @@ Export-ModuleMember -Function Get-OpenTelemetryInstallDirectory
|
|||
Export-ModuleMember -Function Get-OpenTelemetryInstallVersion
|
||||
Export-ModuleMember -Function Enable-OpenTelemetryForIISAppPool
|
||||
Export-ModuleMember -Function Disable-OpenTelemetryForIISAppPool
|
||||
Export-ModuleMember -Function Register-AssembliesInGAC
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#if NETFRAMEWORK
|
||||
namespace OpenTelemetry.AutoInstrumentation.Loader;
|
||||
|
||||
/// <summary>
|
||||
/// Handles update of config files for non-default AppDomain
|
||||
/// </summary>
|
||||
internal static class AppConfigUpdater
|
||||
{
|
||||
/// <summary>
|
||||
/// Modify assembly bindings in appDomainSetup.
|
||||
/// Will be called through reflection when new <see cref="System.AppDomain"/> created.
|
||||
/// Call done using bytecode modifications for <see cref="AppDomain.CreateDomain(string,System.Security.Policy.Evidence,System.AppDomainSetup)"/>
|
||||
/// and <see cref="AppDomainManager.CreateDomainHelper(string,System.Security.Policy.Evidence,System.AppDomainSetup)"/>.
|
||||
/// </summary>
|
||||
/// <param name="appDomainSetup">appDomainSetup to be updated</param>
|
||||
public static void ModifyConfig(AppDomainSetup appDomainSetup)
|
||||
{
|
||||
appDomainSetup.LoaderOptimization = LoaderOptimization.SingleDomain;
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -177,6 +177,7 @@ add_library("OpenTelemetry.AutoInstrumentation.Native.static" STATIC
|
|||
il_rewriter_wrapper.cpp
|
||||
il_rewriter.cpp
|
||||
integration.cpp
|
||||
member_resolver.cpp
|
||||
metadata_builder.cpp
|
||||
miniutf.cpp
|
||||
string.cpp
|
||||
|
|
|
@ -200,6 +200,7 @@
|
|||
<ClInclude Include="logger.h" />
|
||||
<ClInclude Include="logger_impl.h" />
|
||||
<ClInclude Include="macros.h" />
|
||||
<ClInclude Include="member_resolver.h" />
|
||||
<ClInclude Include="metadata_builder.h" />
|
||||
<ClInclude Include="method_rewriter.h" />
|
||||
<ClInclude Include="miniutf.hpp" />
|
||||
|
@ -211,6 +212,7 @@
|
|||
<ClInclude Include="rejit_handler.h" />
|
||||
<ClInclude Include="rejit_preprocessor.h" />
|
||||
<ClInclude Include="rejit_work_offloader.h" />
|
||||
<ClInclude Include="signature_builder.h" />
|
||||
<ClInclude Include="startup_hook.h" />
|
||||
<ClInclude Include="stats.h" />
|
||||
<ClInclude Include="string.h" />
|
||||
|
@ -230,6 +232,7 @@
|
|||
<ClCompile Include="il_rewriter.cpp" />
|
||||
<ClCompile Include="il_rewriter_wrapper.cpp" />
|
||||
<ClCompile Include="integration.cpp" />
|
||||
<ClCompile Include="member_resolver.cpp" />
|
||||
<ClCompile Include="metadata_builder.cpp" />
|
||||
<ClCompile Include="method_rewriter.cpp" />
|
||||
<ClCompile Include="miniutf.cpp" />
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -106,6 +106,11 @@ private:
|
|||
//
|
||||
HRESULT RunAutoInstrumentationLoader(const ComPtr<IMetaDataEmit2>&, const ModuleID module_id, const mdToken function_token, const FunctionInfo& caller, const ModuleMetadata& module_metadata);
|
||||
HRESULT GenerateLoaderMethod(const ModuleID module_id, mdMethodDef* ret_method_token);
|
||||
HRESULT GenerateLoaderType(const ModuleID module_id,
|
||||
mdTypeDef* loader_type,
|
||||
mdMethodDef* init_method,
|
||||
mdMethodDef* patch_app_domain_setup_method);
|
||||
HRESULT ModifyAppDomainCreate(const ModuleID module_id, mdMethodDef patch_app_domain_setup_method);
|
||||
HRESULT AddIISPreStartInitFlags(const ModuleID module_id, const mdToken function_token);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "member_resolver.h"
|
||||
|
||||
namespace trace
|
||||
{
|
||||
|
||||
MemberResolver::MemberResolver(const ComPtr<IMetaDataImport2>& import, const ComPtr<IMetaDataEmit2>& emit)
|
||||
: metadaImport_(import), metadaEmit_(emit)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT MemberResolver::GetTypeRefOrDefByName(mdToken tkResolutionScope, LPCWSTR szName, mdToken* token)
|
||||
{
|
||||
if (TypeFromToken(tkResolutionScope) == mdtAssembly)
|
||||
{
|
||||
tkResolutionScope = mdTokenNil;
|
||||
}
|
||||
|
||||
if (tkResolutionScope == mdTokenNil || TypeFromToken(tkResolutionScope) == mdtTypeDef)
|
||||
{
|
||||
return metadaImport_->FindTypeDefByName(szName, tkResolutionScope, token);
|
||||
}
|
||||
|
||||
return metadaEmit_->DefineTypeRefByName(tkResolutionScope, szName, token);
|
||||
}
|
||||
|
||||
HRESULT MemberResolver::GetMemberRefOrDef(
|
||||
mdToken tkScope, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdToken* token)
|
||||
|
||||
{
|
||||
if (TypeFromToken(tkScope) == mdtTypeDef)
|
||||
{
|
||||
return metadaImport_->FindMember(tkScope, szName, pvSigBlob, cbSigBlob, token);
|
||||
}
|
||||
|
||||
return metadaEmit_->DefineMemberRef(tkScope, szName, pvSigBlob, cbSigBlob, token);
|
||||
}
|
||||
} // namespace trace
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OTEL_CLR_PROFILER_MEMBER_RESOLVER_H_
|
||||
#define OTEL_CLR_PROFILER_MEMBER_RESOLVER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <corhlpr.h>
|
||||
|
||||
#include "com_ptr.h"
|
||||
#include "module_metadata.h"
|
||||
|
||||
namespace trace
|
||||
{
|
||||
|
||||
class MemberResolver
|
||||
{
|
||||
private:
|
||||
ComPtr<IMetaDataImport2> metadaImport_;
|
||||
ComPtr<IMetaDataEmit2> metadaEmit_;
|
||||
|
||||
public:
|
||||
MemberResolver(const ComPtr<IMetaDataImport2>& import, const ComPtr<IMetaDataEmit2>& emit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Uses IMetaDataImport::FindTypeDefByName if tkResolutionScope is mdTokenNill, TypeDef or Assembly
|
||||
/// Uses IMetaDataEmit::DefineTypeRefByName otherwise (if tkResolutionScope is AssemblyRef or TypeRef)
|
||||
/// </summary>
|
||||
HRESULT GetTypeRefOrDefByName(mdToken tkResolutionScope, LPCWSTR szName, mdToken* token);
|
||||
|
||||
/// <summary>
|
||||
/// Uses IMetaDataImport::FindMember if tkScope is TypeDef
|
||||
/// Uses IMetaDataEmit::DefineMemberRef otherwise (if tkScope is TypeRef or TypeSpec)
|
||||
/// </summary>
|
||||
HRESULT GetMemberRefOrDef(mdToken tkScope, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdToken* token);
|
||||
};
|
||||
|
||||
} // namespace trace
|
||||
|
||||
#endif // OTEL_CLR_PROFILER_MEMBER_RESOLVER_H_
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OTEL_CLR_PROFILER_SIGNATURE_BUILDER_H_
|
||||
#define OTEL_CLR_PROFILER_SIGNATURE_BUILDER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <corhlpr.h>
|
||||
|
||||
namespace trace
|
||||
{
|
||||
|
||||
class SignatureData
|
||||
{
|
||||
protected:
|
||||
std::vector<COR_SIGNATURE> blob_;
|
||||
|
||||
public:
|
||||
SignatureData() = default;
|
||||
SignatureData(std::initializer_list<COR_SIGNATURE> bytes) : blob_(bytes) {}
|
||||
SignatureData(std::initializer_list<SignatureData> elements)
|
||||
{
|
||||
for (auto& inner : elements)
|
||||
{
|
||||
blob_.insert(blob_.end(), inner.blob_.begin(), inner.blob_.end());
|
||||
}
|
||||
}
|
||||
|
||||
PCCOR_SIGNATURE Head() const
|
||||
{
|
||||
return blob_.data();
|
||||
}
|
||||
|
||||
ULONG Size() const
|
||||
{
|
||||
return static_cast<ULONG>(blob_.size());
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder : public virtual SignatureData
|
||||
{
|
||||
public:
|
||||
SignatureBuilder() = default;
|
||||
SignatureBuilder(std::initializer_list<COR_SIGNATURE> bytes) : SignatureData(bytes) {}
|
||||
SignatureBuilder(std::initializer_list<SignatureData> elements) : SignatureData(elements) {}
|
||||
|
||||
SignatureBuilder& PushRawByte(COR_SIGNATURE byte)
|
||||
{
|
||||
blob_.push_back(byte);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
SignatureBuilder& PushRawBytes(InputIt first, InputIt last)
|
||||
{
|
||||
blob_.insert(blob_.end(), first, last);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SignatureBuilder& PushRawBytes(std::initializer_list<COR_SIGNATURE> bytes)
|
||||
{
|
||||
blob_.insert(blob_.end(), bytes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SignatureBuilder& PushCompressedData(ULONG data)
|
||||
{
|
||||
COR_SIGNATURE compressed[sizeof(ULONG)];
|
||||
ULONG compressedSize = CorSigCompressData(data, compressed);
|
||||
for (ULONG i = 0; i < compressedSize; i++)
|
||||
{
|
||||
PushRawByte(compressed[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SignatureBuilder& PushToken(mdToken token)
|
||||
{
|
||||
COR_SIGNATURE compressed[sizeof(mdToken)];
|
||||
ULONG compressedSize = CorSigCompressToken(token, compressed);
|
||||
for (ULONG i = 0; i < compressedSize; i++)
|
||||
{
|
||||
PushRawByte(compressed[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SignatureBuilder& Push(const SignatureData& inner)
|
||||
{
|
||||
blob_.insert(blob_.end(), inner.Head(), inner.Head()+inner.Size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum class MethodCallingConvection : COR_SIGNATURE
|
||||
{
|
||||
Static = IMAGE_CEE_CS_CALLCONV_DEFAULT,
|
||||
Instance = IMAGE_CEE_CS_CALLCONV_HASTHIS
|
||||
};
|
||||
|
||||
enum class TokenTypeMode : COR_SIGNATURE
|
||||
{
|
||||
ValueType = ELEMENT_TYPE_VALUETYPE,
|
||||
Class = ELEMENT_TYPE_CLASS
|
||||
};
|
||||
|
||||
enum class GenericArgMode : COR_SIGNATURE
|
||||
{
|
||||
Type = ELEMENT_TYPE_VAR,
|
||||
Method = ELEMENT_TYPE_MVAR
|
||||
};
|
||||
|
||||
enum class BuiltIn : COR_SIGNATURE
|
||||
{
|
||||
Void = ELEMENT_TYPE_VOID,
|
||||
Boolean = ELEMENT_TYPE_BOOLEAN,
|
||||
Char = ELEMENT_TYPE_CHAR,
|
||||
SByte = ELEMENT_TYPE_I1,
|
||||
Byte = ELEMENT_TYPE_U1,
|
||||
Int16 = ELEMENT_TYPE_I2,
|
||||
UInt16 = ELEMENT_TYPE_U2,
|
||||
Int32 = ELEMENT_TYPE_I4,
|
||||
UInt32 = ELEMENT_TYPE_U4,
|
||||
Int64 = ELEMENT_TYPE_I8,
|
||||
UInt64 = ELEMENT_TYPE_U8,
|
||||
Float = ELEMENT_TYPE_R4,
|
||||
Double = ELEMENT_TYPE_R8,
|
||||
String = ELEMENT_TYPE_STRING,
|
||||
IntPtr = ELEMENT_TYPE_I,
|
||||
UintPtr = ELEMENT_TYPE_U,
|
||||
Object = ELEMENT_TYPE_OBJECT
|
||||
};
|
||||
|
||||
class Type;
|
||||
class TokenType;
|
||||
class ValueType;
|
||||
class Class;
|
||||
class Array;
|
||||
class ByRef;
|
||||
class GenericArgument;
|
||||
class GenericArgumentOfMethod;
|
||||
class GenericArgumentOfType;
|
||||
class GenericInstance;
|
||||
class Field;
|
||||
class Method;
|
||||
class InstanceMethod;
|
||||
class StaticMethod;
|
||||
};
|
||||
|
||||
class SignatureBuilder::Type : public virtual SignatureData, protected SignatureBuilder
|
||||
{
|
||||
public:
|
||||
Type(BuiltIn builtin)
|
||||
: SignatureData{static_cast<COR_SIGNATURE>(builtin)}
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
Type() = default;
|
||||
};
|
||||
|
||||
class SignatureBuilder::TokenType : public Type
|
||||
{
|
||||
public:
|
||||
TokenType(TokenTypeMode type, mdToken token)
|
||||
{
|
||||
this->PushRawByte(static_cast<COR_SIGNATURE>(type));
|
||||
this->PushToken(token);
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::ValueType : public TokenType
|
||||
{
|
||||
public:
|
||||
explicit ValueType(mdToken token) : TokenType(TokenTypeMode::ValueType, token) {}
|
||||
};
|
||||
|
||||
class SignatureBuilder::Class : public TokenType
|
||||
{
|
||||
public:
|
||||
explicit Class(mdToken token) : TokenType(TokenTypeMode::Class, token) {}
|
||||
};
|
||||
|
||||
class SignatureBuilder::Array : public Type
|
||||
{
|
||||
public:
|
||||
explicit Array(const Type& type)
|
||||
{
|
||||
this->PushRawByte(ELEMENT_TYPE_SZARRAY);
|
||||
this->Push(type);
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::ByRef : public Type
|
||||
{
|
||||
public:
|
||||
explicit ByRef(const Type& type)
|
||||
{
|
||||
this->PushRawByte(ELEMENT_TYPE_BYREF);
|
||||
this->Push(type);
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::GenericArgument : public Type
|
||||
{
|
||||
public:
|
||||
GenericArgument(GenericArgMode type, UINT num)
|
||||
{
|
||||
this->PushRawByte(static_cast<COR_SIGNATURE>(type));
|
||||
this->PushCompressedData(num);
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::GenericArgumentOfMethod : public GenericArgument
|
||||
{
|
||||
public:
|
||||
explicit GenericArgumentOfMethod(UINT num) : GenericArgument(GenericArgMode::Method, num) {}
|
||||
};
|
||||
|
||||
class SignatureBuilder::GenericArgumentOfType : public GenericArgument
|
||||
{
|
||||
public:
|
||||
explicit GenericArgumentOfType(UINT num) : GenericArgument(GenericArgMode::Type, num) {}
|
||||
};
|
||||
|
||||
class SignatureBuilder::GenericInstance : public Type
|
||||
{
|
||||
public:
|
||||
GenericInstance(const TokenType& open_generic, const std::vector<Type>& generic_args)
|
||||
{
|
||||
this->PushRawByte(ELEMENT_TYPE_GENERICINST);
|
||||
this->Push(open_generic);
|
||||
this->PushCompressedData(static_cast<ULONG>(generic_args.size()));
|
||||
for (const auto& arg : generic_args)
|
||||
{
|
||||
this->Push(arg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::Field : public virtual SignatureData, protected SignatureBuilder
|
||||
{
|
||||
public:
|
||||
explicit Field(const Type& field_type)
|
||||
{
|
||||
this->PushRawByte(IMAGE_CEE_CS_CALLCONV_FIELD);
|
||||
this->Push(field_type);
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::Method : public virtual SignatureData, protected SignatureBuilder
|
||||
{
|
||||
public:
|
||||
Method(MethodCallingConvection calling_convection, const Type& return_type, const std::vector<Type>& args)
|
||||
{
|
||||
this->PushRawByte(static_cast<COR_SIGNATURE>(calling_convection));
|
||||
this->PushCompressedData(static_cast<ULONG>(args.size()));
|
||||
this->Push(return_type);
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
this->Push(arg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::InstanceMethod : public Method
|
||||
{
|
||||
public:
|
||||
InstanceMethod(const Type& return_type, const std::vector<Type>& args)
|
||||
: Method(MethodCallingConvection::Instance, return_type, args)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SignatureBuilder::StaticMethod : public Method
|
||||
{
|
||||
public:
|
||||
StaticMethod(const Type& return_type, const std::vector<Type>& args)
|
||||
: Method(MethodCallingConvection::Static, return_type, args)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace trace
|
||||
|
||||
#endif // OTEL_CLR_PROFILER_SIGNATURE_BUILDER_H_
|
|
@ -17,14 +17,42 @@ public class AspNetTests
|
|||
Output = output;
|
||||
}
|
||||
|
||||
public enum Gac
|
||||
{
|
||||
/// <summary>
|
||||
/// Use image with OTEL assemblies registered in GAC
|
||||
/// </summary>
|
||||
UseGac,
|
||||
|
||||
/// <summary>
|
||||
/// Use image with OTEL assemblies not registered in GAC
|
||||
/// </summary>
|
||||
UseLocal
|
||||
}
|
||||
|
||||
public enum AppPoolMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Use image with Classic AppPoolMode
|
||||
/// </summary>
|
||||
Classic,
|
||||
|
||||
/// <summary>
|
||||
/// Use image with Integrated AppPoolMode
|
||||
/// </summary>
|
||||
Integrated
|
||||
}
|
||||
|
||||
private ITestOutputHelper Output { get; }
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", "EndToEnd")]
|
||||
[Trait("Containers", "Windows")]
|
||||
[InlineData("Classic")]
|
||||
[InlineData("Integrated")]
|
||||
public async Task SubmitsTraces(string appPoolMode)
|
||||
[InlineData(AppPoolMode.Classic, Gac.UseGac)]
|
||||
[InlineData(AppPoolMode.Classic, Gac.UseLocal)]
|
||||
[InlineData(AppPoolMode.Integrated, Gac.UseGac)]
|
||||
[InlineData(AppPoolMode.Integrated, Gac.UseLocal)]
|
||||
public async Task SubmitsTraces(AppPoolMode appPoolMode, Gac useGac)
|
||||
{
|
||||
Assert.True(EnvironmentTools.IsWindowsAdministrator(), "This test requires Windows Administrator privileges.");
|
||||
|
||||
|
@ -43,7 +71,7 @@ public class AspNetTests
|
|||
["OTEL_EXPORTER_OTLP_ENDPOINT"] = collectorUrl
|
||||
};
|
||||
var webPort = TcpPortProvider.GetOpenPort();
|
||||
var imageName = GetTestImageName(appPoolMode);
|
||||
var imageName = GetTestImageName(appPoolMode, useGac);
|
||||
await using var container = await IISContainerTestHelper.StartContainerAsync(imageName, webPort, environmentVariables, Output);
|
||||
await CallTestApplicationEndpoint(webPort);
|
||||
|
||||
|
@ -53,9 +81,11 @@ public class AspNetTests
|
|||
[Theory]
|
||||
[Trait("Category", "EndToEnd")]
|
||||
[Trait("Containers", "Windows")]
|
||||
[InlineData("Classic")]
|
||||
[InlineData("Integrated")]
|
||||
public async Task SubmitTracesCapturesHttpHeaders(string appPoolMode)
|
||||
[InlineData(AppPoolMode.Classic, Gac.UseGac)]
|
||||
[InlineData(AppPoolMode.Classic, Gac.UseLocal)]
|
||||
[InlineData(AppPoolMode.Integrated, Gac.UseGac)]
|
||||
[InlineData(AppPoolMode.Integrated, Gac.UseLocal)]
|
||||
public async Task SubmitTracesCapturesHttpHeaders(AppPoolMode appPoolMode, Gac useGac)
|
||||
{
|
||||
Assert.True(EnvironmentTools.IsWindowsAdministrator(), "This test requires Windows Administrator privileges.");
|
||||
|
||||
|
@ -67,7 +97,7 @@ public class AspNetTests
|
|||
using var fwPort = FirewallHelper.OpenWinPort(collector.Port, Output);
|
||||
collector.Expect("OpenTelemetry.Instrumentation.AspNet.Telemetry", span => // Expect Mvc span
|
||||
{
|
||||
if (appPoolMode == "Classic")
|
||||
if (appPoolMode == AppPoolMode.Classic)
|
||||
{
|
||||
return span.Attributes.Any(x => x.Key == "http.request.header.custom-request-test-header2" && x.Value.StringValue == "Test-Value2")
|
||||
&& span.Attributes.All(x => x.Key != "http.request.header.custom-request-test-header1")
|
||||
|
@ -87,7 +117,7 @@ public class AspNetTests
|
|||
|
||||
collector.Expect("OpenTelemetry.Instrumentation.AspNet.Telemetry", span => // Expect WebApi span
|
||||
{
|
||||
if (appPoolMode == "Classic")
|
||||
if (appPoolMode == AppPoolMode.Classic)
|
||||
{
|
||||
return span.Attributes.Any(x => x.Key == "http.request.header.custom-request-test-header2" && x.Value.StringValue == "Test-Value2")
|
||||
&& span.Attributes.All(x => x.Key != "http.request.header.custom-request-test-header1")
|
||||
|
@ -113,7 +143,7 @@ public class AspNetTests
|
|||
["OTEL_DOTNET_AUTO_TRACES_ASPNET_INSTRUMENTATION_CAPTURE_RESPONSE_HEADERS"] = "Custom-Response-Test-Header1,Custom-Response-Test-Header3"
|
||||
};
|
||||
var webPort = TcpPortProvider.GetOpenPort();
|
||||
var imageName = GetTestImageName(appPoolMode);
|
||||
var imageName = GetTestImageName(appPoolMode, useGac);
|
||||
await using var container = await IISContainerTestHelper.StartContainerAsync(imageName, webPort, environmentVariables, Output);
|
||||
await CallTestApplicationEndpoint(webPort);
|
||||
|
||||
|
@ -181,9 +211,16 @@ public class AspNetTests
|
|||
collector.AssertExpectations();
|
||||
}
|
||||
|
||||
private static string GetTestImageName(string appPoolMode)
|
||||
private static string GetTestImageName(AppPoolMode appPoolMode, Gac useGac)
|
||||
{
|
||||
return appPoolMode == "Classic" ? "testapplication-aspnet-netframework-classic" : "testapplication-aspnet-netframework-integrated";
|
||||
return (appPoolMode, useGac) switch
|
||||
{
|
||||
(AppPoolMode.Classic, Gac.UseGac) => "testapplication-aspnet-netframework-classic",
|
||||
(AppPoolMode.Classic, Gac.UseLocal) => "testapplication-aspnet-netframework-classic-nogac",
|
||||
(AppPoolMode.Integrated, Gac.UseGac) => "testapplication-aspnet-netframework-integrated",
|
||||
(AppPoolMode.Integrated, Gac.UseLocal) => "testapplication-aspnet-netframework-integrated-nogac",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task CallTestApplicationEndpoint(int webPort)
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include "../../src/OpenTelemetry.AutoInstrumentation.Native/signature_builder.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace trace;
|
||||
|
||||
class SignatureBuilderTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(SignatureBuilderTest, SignatureBuilderDefaultCtor)
|
||||
{
|
||||
SignatureBuilder empty;
|
||||
EXPECT_EQ(empty.Size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, CorSignatureCtor)
|
||||
{
|
||||
SignatureBuilder for_test{1, 2, 3, 99};
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({1, 2, 3, 99}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, PushRawByte)
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushRawByte(64).PushRawByte(50);
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({64, 50}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, PushRawBytes)
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushRawBytes({64, 98}).PushRawBytes({70, 54});
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({64, 98, 70, 54}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, PushRawBytesBeginEnd)
|
||||
{
|
||||
std::vector<COR_SIGNATURE> source1{23, 98, 37};
|
||||
std::vector<COR_SIGNATURE> source2{35, 42};
|
||||
|
||||
SignatureBuilder for_test =
|
||||
SignatureBuilder{}.PushRawBytes(source1.begin(), source1.end()).PushRawBytes(source2.begin(), source2.end());
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({23, 98, 37, 35, 42}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, PushCompressedData)
|
||||
{
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(1);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({1}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x7F);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0x7F}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x80);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0x80, 0x80}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x2E57);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0xAE, 0x57}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x3FFF);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0xBF, 0xFF}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x4000);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0xC0, 0x00, 0x40, 0x00}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushCompressedData(0x1FFFFFFF);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0xDF, 0xFF, 0xFF, 0xFF}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, PushToken)
|
||||
{
|
||||
SignatureBuilder for_test = SignatureBuilder{}.PushToken(TokenFromRid(0x12, mdtTypeRef));
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({0x49}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, Push)
|
||||
{
|
||||
SignatureBuilder source1{23, 98, 37};
|
||||
SignatureBuilder source2{35, 42};
|
||||
|
||||
SignatureBuilder for_test = SignatureBuilder{}.Push(source1).Push(source2);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({23, 98, 37, 35, 42}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, SignatureBuilderCtor)
|
||||
{
|
||||
SignatureBuilder source1{23, 98, 37};
|
||||
SignatureBuilder source2{35, 42};
|
||||
|
||||
SignatureBuilder for_test{source1, source2};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({23, 98, 37, 35, 42}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, CombinationOfApi)
|
||||
{
|
||||
SignatureBuilder source1{23, 98, 37};
|
||||
SignatureBuilder source2{35, 42};
|
||||
|
||||
SignatureBuilder for_test = SignatureBuilder{source1, source2}
|
||||
.PushRawByte(33)
|
||||
.PushRawBytes({34, 51})
|
||||
.PushToken(TokenFromRid(0x12, mdtTypeRef))
|
||||
.PushCompressedData(0x4000);
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({23, 98, 37, 35, 42, 33, 34, 51, 0x49, 0xC0, 0x00, 0x40, 0x00}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, Type)
|
||||
{
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Void};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_VOID}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Boolean};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_BOOLEAN}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Char};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_CHAR}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::SByte};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_I1}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Byte};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_U1}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Int16};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_I2}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::UInt16};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_U2}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Int32};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_I4}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::UInt32};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_U4}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Int64};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_I8}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::UInt64};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_U8}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Float};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_R4}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Double};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_R8}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::String};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_STRING}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::IntPtr};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_I}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::UintPtr};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_U}));
|
||||
}
|
||||
{
|
||||
SignatureBuilder::Type for_test{SignatureBuilder::BuiltIn::Object};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_OBJECT}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, ValueType)
|
||||
{
|
||||
SignatureBuilder::ValueType for_test{TokenFromRid(0x12, mdtTypeRef)};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_VALUETYPE, 0x49}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, Class)
|
||||
{
|
||||
SignatureBuilder::Class for_test{TokenFromRid(0x12, mdtTypeRef)};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_CLASS, 0x49}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, Array)
|
||||
{
|
||||
SignatureBuilder::Array for_test{SignatureBuilder::BuiltIn::String};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_SZARRAY, ELEMENT_TYPE_STRING}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, ByRef)
|
||||
{
|
||||
SignatureBuilder::ByRef for_test{SignatureBuilder::BuiltIn::String};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_BYREF, ELEMENT_TYPE_STRING}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, GenericArgumentOfMethod)
|
||||
{
|
||||
SignatureBuilder::GenericArgumentOfMethod for_test{0x80};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_MVAR, 0x80, 0x80}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, GenericArgumentOfType)
|
||||
{
|
||||
SignatureBuilder::GenericArgumentOfType for_test{0x0};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({ELEMENT_TYPE_VAR, 0x00}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, GenericInstance)
|
||||
{
|
||||
SignatureBuilder::GenericInstance for_test{SignatureBuilder::Class{TokenFromRid(0x12, mdtTypeRef)},
|
||||
{SignatureBuilder::BuiltIn::String, SignatureBuilder::BuiltIn::Double}};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>(
|
||||
{ELEMENT_TYPE_GENERICINST, ELEMENT_TYPE_CLASS, 0x49, 2, ELEMENT_TYPE_STRING, ELEMENT_TYPE_R8}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, Field)
|
||||
{
|
||||
SignatureBuilder::Field for_test{SignatureBuilder::Class{TokenFromRid(0x12, mdtTypeRef)}};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>({IMAGE_CEE_CS_CALLCONV_FIELD, ELEMENT_TYPE_CLASS, 0x49}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, InstanceMethod)
|
||||
{
|
||||
SignatureBuilder::InstanceMethod for_test{SignatureBuilder::Class{TokenFromRid(0x12, mdtTypeRef)},
|
||||
{SignatureBuilder::BuiltIn::String, SignatureBuilder::BuiltIn::Double}};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>(
|
||||
{IMAGE_CEE_CS_CALLCONV_HASTHIS, 2, ELEMENT_TYPE_CLASS, 0x49, ELEMENT_TYPE_STRING, ELEMENT_TYPE_R8}));
|
||||
}
|
||||
|
||||
TEST_F(SignatureBuilderTest, StaticMethod)
|
||||
{
|
||||
SignatureBuilder::StaticMethod for_test{SignatureBuilder::Class{TokenFromRid(0x12, mdtTypeRef)},
|
||||
{SignatureBuilder::BuiltIn::String, SignatureBuilder::BuiltIn::Double}};
|
||||
|
||||
EXPECT_EQ(std::vector<COR_SIGNATURE>(for_test.Head(), for_test.Head() + for_test.Size()),
|
||||
std::vector<COR_SIGNATURE>(
|
||||
{IMAGE_CEE_CS_CALLCONV_DEFAULT, 2, ELEMENT_TYPE_CLASS, 0x49, ELEMENT_TYPE_STRING, ELEMENT_TYPE_R8}));
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# escape=`
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022@sha256:84079c734ab5aec702409ef7967ec47af9468c56ff4046882239cabacda78097 AS integrated
|
||||
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022@sha256:84079c734ab5aec702409ef7967ec47af9468c56ff4046882239cabacda78097 AS integrated-base
|
||||
ARG configuration=Debug
|
||||
ARG platform=x64
|
||||
WORKDIR /opentelemetry
|
||||
|
@ -8,15 +8,27 @@ COPY bin/tracer.zip .
|
|||
COPY bin/OpenTelemetry.DotNet.Auto.psm1 .
|
||||
ENV OTEL_DOTNET_AUTO_INSTALL_DIR=C:\opentelemetry
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
RUN Set-ItemProperty -Path "HKLM:\\SOFTWARE\\Microsoft\\.NETFramework" -Name "LoaderOptimization" -Value 1
|
||||
RUN Import-Module .\OpenTelemetry.DotNet.Auto.psm1 -Verbose; `
|
||||
Install-OpenTelemetryCore -LocalPath .\tracer.zip; `
|
||||
Install-OpenTelemetryCore -LocalPath .\tracer.zip -RegisterAssembliesInGAC $false; `
|
||||
Register-OpenTelemetryForIIS;
|
||||
ENV OTEL_DOTNET_AUTO_LOG_DIRECTORY=C:\inetpub\wwwroot\logs `
|
||||
OTEL_LOG_LEVEL=debug
|
||||
WORKDIR /inetpub/wwwroot
|
||||
COPY bin/${configuration}/app.publish .
|
||||
|
||||
FROM integrated-base AS integrated-nogac
|
||||
|
||||
FROM integrated-nogac AS classic-nogac
|
||||
RUN Start-IISCommitDelay;`
|
||||
(Get-IISAppPool -Name DefaultAppPool).ManagedPipelineMode = 'Classic';`
|
||||
Stop-IISCommitDelay -Commit $True
|
||||
|
||||
FROM integrated-base AS integrated
|
||||
WORKDIR /opentelemetry
|
||||
RUN Import-Module .\OpenTelemetry.DotNet.Auto.psm1 -Verbose; `
|
||||
Register-AssembliesInGAC -InstallDir C:\inetpub\wwwroot\otel;
|
||||
WORKDIR /inetpub/wwwroot
|
||||
|
||||
FROM integrated AS classic
|
||||
RUN Start-IISCommitDelay;`
|
||||
(Get-IISAppPool -Name DefaultAppPool).ManagedPipelineMode = 'Classic';`
|
||||
|
|
|
@ -8,7 +8,6 @@ COPY bin/tracer.zip .
|
|||
COPY bin/OpenTelemetry.DotNet.Auto.psm1 .
|
||||
ENV OTEL_DOTNET_AUTO_INSTALL_DIR=C:\opentelemetry
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
RUN Set-ItemProperty -Path "HKLM:\\SOFTWARE\\Microsoft\\.NETFramework" -Name "LoaderOptimization" -Value 1
|
||||
RUN Import-Module .\OpenTelemetry.DotNet.Auto.psm1 -Verbose; `
|
||||
Install-OpenTelemetryCore -LocalPath .\tracer.zip; `
|
||||
Register-OpenTelemetryForIIS;
|
||||
|
|
|
@ -8,7 +8,6 @@ COPY bin/tracer.zip .
|
|||
COPY bin/OpenTelemetry.DotNet.Auto.psm1 .
|
||||
ENV OTEL_DOTNET_AUTO_INSTALL_DIR=C:\opentelemetry
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
RUN Set-ItemProperty -Path "HKLM:\\SOFTWARE\\Microsoft\\.NETFramework" -Name "LoaderOptimization" -Value 1
|
||||
RUN Import-Module .\OpenTelemetry.DotNet.Auto.psm1 -Verbose; `
|
||||
Install-OpenTelemetryCore -LocalPath .\tracer.zip; `
|
||||
Register-OpenTelemetryForIIS;
|
||||
|
|
Loading…
Reference in New Issue