[WCF] use wcf client instrumentation from contrib (#2876)
This commit is contained in:
parent
c0d389fbe2
commit
afd8a8b4cd
|
|
@ -10,6 +10,7 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|||
### Added
|
||||
|
||||
- Added support for Azure SDK traces instrumentation on .NET Framework.
|
||||
- Added support for `WCFCLIENT` instrumentation on .NET.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@
|
|||
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.5.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.5.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.5.1-beta.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Wcf" Version="1.0.0-rc.10" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Wcf" Version="1.0.0-rc.11" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -201,6 +201,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.OpenTracing
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Azure", "test\test-applications\integrations\TestApplication.Azure\TestApplication.Azure.csproj", "{3A125210-A784-4982-ACDB-C3442E414E44}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Wcf.Client.DotNet", "test\test-applications\integrations\TestApplication.Wcf.Client.DotNet\TestApplication.Wcf.Client.DotNet.csproj", "{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -949,6 +951,18 @@ Global
|
|||
{3A125210-A784-4982-ACDB-C3442E414E44}.Release|x64.Build.0 = Release|x64
|
||||
{3A125210-A784-4982-ACDB-C3442E414E44}.Release|x86.ActiveCfg = Release|x86
|
||||
{3A125210-A784-4982-ACDB-C3442E414E44}.Release|x86.Build.0 = Release|x86
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|x64.Build.0 = Debug|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Debug|x86.Build.0 = Debug|x86
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|Any CPU.Build.0 = Release|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x64.ActiveCfg = Release|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x64.Build.0 = Release|x64
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x86.ActiveCfg = Release|x86
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -1021,6 +1035,7 @@ Global
|
|||
{BB720565-B83C-497F-ACF9-B0D13642DA19} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
{C66927FD-ED1F-4079-8733-51AB7463060D} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
{3A125210-A784-4982-ACDB-C3442E414E44} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
|
||||
|
|
|
|||
|
|
@ -141,5 +141,13 @@ public static class LibraryVersion
|
|||
new("2.6.122"),
|
||||
}
|
||||
},
|
||||
{
|
||||
"TestApplication.Wcf.Client.DotNet",
|
||||
new List<PackageBuildInfo>
|
||||
{
|
||||
new("4.10.2"),
|
||||
new("6.0.0"),
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,27 +124,27 @@ for example `TRACES`, and `{0}` is the case-sensitive name of the instrumentatio
|
|||
Traces are stable, but particular instrumentation are in Experimental status
|
||||
due to lack of stable semantic convention.
|
||||
|
||||
| ID | Instrumented library | Supported versions | Instrumentation type | Status |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `ASPNET` | ASP.NET (.NET Framework) MVC / WebApi \[1\] **Not supported on .NET** | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ASPNETCORE` | ASP.NET Core **Not supported on .NET Framework** | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `AZURE` | [Azure SDK](https://azure.github.io/azure-sdk/releases/latest/index.html) | \[2\] | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ELASTICSEARCH` | [Elastic.Clients.Elasticsearch](https://www.nuget.org/packages/Elastic.Clients.Elasticsearch) | ≥8.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ENTITYFRAMEWORKCORE` | [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/) **Not supported on .NET Framework** | ≥6.0.12 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `GRAPHQL` | [GraphQL](https://www.nuget.org/packages/GraphQL) **Not supported on .NET Framework** | ≥7.5.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `GRPCNETCLIENT` | [Grpc.Net.Client](https://www.nuget.org/packages/Grpc.Net.Client) | ≥2.52.0 & < 3.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `HTTPCLIENT` | [System.Net.Http.HttpClient](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) and [System.Net.HttpWebRequest](https://docs.microsoft.com/dotnet/api/system.net.httpwebrequest) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `QUARTZ` | [Quartz](https://www.nuget.org/packages/Quartz) **Not supported on .NET Framework 4.7.1 and older** | ≥3.4.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MASSTRANSIT` | [MassTransit](https://www.nuget.org/packages/MassTransit) **Not supported on .NET Framework** | ≥8.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MONGODB` | [MongoDB.Driver.Core](https://www.nuget.org/packages/MongoDB.Driver.Core) | ≥2.13.3 & < 3.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MYSQLCONNECTOR` | [MySqlConnector](https://www.nuget.org/packages/MySqlConnector) | ≥2.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MYSQLDATA` | [MySql.Data](https://www.nuget.org/packages/MySql.Data) **Not supported on .NET Framework** | ≥8.1.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `NPGSQL` | [Npgsql](https://www.nuget.org/packages/Npgsql) | ≥6.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `NSERVICEBUS` | [NServiceBus](https://www.nuget.org/packages/NServiceBus) | ≥8.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `SQLCLIENT` | [Microsoft.Data.SqlClient](https://www.nuget.org/packages/Microsoft.Data.SqlClient) and [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient) | * \[3\] | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `STACKEXCHANGEREDIS` | [StackExchange.Redis](https://www.nuget.org/packages/StackExchange.Redis) **Not supported on .NET Framework** | ≥2.0.405 < 3.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `WCFCLIENT` | [System.ServiceModel](https://www.nuget.org/packages/System.ServiceModel) **Not supported on .NET**. | ≥4.0.0.0 < 5.0.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `WCFSERVICE` | [System.ServiceModel](https://www.nuget.org/packages/System.ServiceModel) **Not supported on .NET**. | ≥4.0.0.0 < 5.0.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| ID | Instrumented library | Supported versions | Instrumentation type | Status |
|
||||
|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `ASPNET` | ASP.NET (.NET Framework) MVC / WebApi \[1\] **Not supported on .NET** | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ASPNETCORE` | ASP.NET Core **Not supported on .NET Framework** | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `AZURE` | [Azure SDK](https://azure.github.io/azure-sdk/releases/latest/index.html) | \[2\] | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ELASTICSEARCH` | [Elastic.Clients.Elasticsearch](https://www.nuget.org/packages/Elastic.Clients.Elasticsearch) | ≥8.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `ENTITYFRAMEWORKCORE` | [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/) **Not supported on .NET Framework** | ≥6.0.12 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `GRAPHQL` | [GraphQL](https://www.nuget.org/packages/GraphQL) **Not supported on .NET Framework** | ≥7.5.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `GRPCNETCLIENT` | [Grpc.Net.Client](https://www.nuget.org/packages/Grpc.Net.Client) | ≥2.52.0 & < 3.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `HTTPCLIENT` | [System.Net.Http.HttpClient](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) and [System.Net.HttpWebRequest](https://docs.microsoft.com/dotnet/api/system.net.httpwebrequest) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `QUARTZ` | [Quartz](https://www.nuget.org/packages/Quartz) **Not supported on .NET Framework 4.7.1 and older** | ≥3.4.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MASSTRANSIT` | [MassTransit](https://www.nuget.org/packages/MassTransit) **Not supported on .NET Framework** | ≥8.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MONGODB` | [MongoDB.Driver.Core](https://www.nuget.org/packages/MongoDB.Driver.Core) | ≥2.13.3 & < 3.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MYSQLCONNECTOR` | [MySqlConnector](https://www.nuget.org/packages/MySqlConnector) | ≥2.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `MYSQLDATA` | [MySql.Data](https://www.nuget.org/packages/MySql.Data) **Not supported on .NET Framework** | ≥8.1.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `NPGSQL` | [Npgsql](https://www.nuget.org/packages/Npgsql) | ≥6.0.0 | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `NSERVICEBUS` | [NServiceBus](https://www.nuget.org/packages/NServiceBus) | ≥8.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `SQLCLIENT` | [Microsoft.Data.SqlClient](https://www.nuget.org/packages/Microsoft.Data.SqlClient) and [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient) | * \[3\] | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `STACKEXCHANGEREDIS` | [StackExchange.Redis](https://www.nuget.org/packages/StackExchange.Redis) **Not supported on .NET Framework** | ≥2.0.405 < 3.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `WCFCLIENT` | WCF **Limited support on .NET, see [wcf-config.md](./wcf-config.md)** | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `WCFSERVICE` | WCF **Not supported on .NET**. | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
|
||||
\[1\]: Only integrated pipeline mode is supported.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,11 @@ Example project available in
|
|||
[test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework](../test/test-applications/integrations/TestApplication.Wcf.Client.NetFramework/)
|
||||
folder.
|
||||
|
||||
⚠️ **NOTICE:** Instrumentation of
|
||||
[APM-style](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/asynchronous-programming-model-apm)
|
||||
calls is supported, but have known limitations.
|
||||
It is recommended to convert them to
|
||||
[TAP-style](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap)
|
||||
calls.
|
||||
|
||||
## WCF Client Configuration (.NET)
|
||||
|
||||
Instrumentation for WCF Client on .NET is not supported.
|
||||
Example project available in
|
||||
[test/test-applications/integrations/TestApplication.Wcf.Client.DotNet](../test/test-applications/integrations/TestApplication.Wcf.Client.DotNet/)
|
||||
folder.
|
||||
|
||||
## WCF Server Configuration (.NET Framework)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ void CorProfiler::InitNetFxAssemblyRedirectsMap()
|
|||
{ L"OpenTelemetry.Instrumentation.Quartz", {1, 0, 0, 3} },
|
||||
{ L"OpenTelemetry.Instrumentation.Runtime", {1, 5, 0, 0} },
|
||||
{ L"OpenTelemetry.Instrumentation.SqlClient", {1, 0, 0, 0} },
|
||||
{ L"OpenTelemetry.Instrumentation.Wcf", {1, 0, 0, 10} },
|
||||
{ L"OpenTelemetry.Instrumentation.Wcf", {1, 0, 0, 11} },
|
||||
{ L"OpenTelemetry.ResourceDetectors.Azure", {1, 0, 0, 2} },
|
||||
{ L"OpenTelemetry.ResourceDetectors.Container", {1, 0, 0, 4} },
|
||||
{ L"OpenTelemetry.Shims.OpenTracing", {1, 0, 0, 0} },
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ OpenTelemetry.AutoInstrumentation.Instrumentations.AspNet.HttpModuleIntegration
|
|||
OpenTelemetry.AutoInstrumentation.Instrumentations.MongoDB.MongoClientIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.NServiceBus.EndpointConfigurationIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Service.ServiceHostIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.InvokeServiceChannelProxyIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration
|
||||
override OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetReturn<T>.ToString() -> string!
|
||||
override OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetState.ToString() -> string!
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ OpenTelemetry.AutoInstrumentation.Instrumentations.MongoDB.MongoClientIntegratio
|
|||
OpenTelemetry.AutoInstrumentation.Instrumentations.NServiceBus.EndpointConfigurationIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis.StackExchangeRedisIntegration
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis.StackExchangeRedisIntegrationAsync
|
||||
OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration
|
||||
override OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetReturn<T>.ToString() -> string!
|
||||
override OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetState.ToString() -> string!
|
||||
static OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetInvoker.BeginMethod<TIntegration, TTarget, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8>(TTarget instance, ref TArg1 arg1, ref TArg2 arg2, ref TArg3 arg3, ref TArg4 arg4, ref TArg5 arg5, ref TArg6 arg6, ref TArg7 arg7, ref TArg8 arg8) -> OpenTelemetry.AutoInstrumentation.CallTarget.CallTargetState
|
||||
|
|
|
|||
|
|
@ -74,13 +74,11 @@ internal static class DelayedInitialization
|
|||
}
|
||||
#endif
|
||||
|
||||
#if NETFRAMEWORK
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void AddWcf(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
|
||||
{
|
||||
lazyInstrumentationLoader.Add(new WcfInitializer(pluginManager));
|
||||
}
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void AddQuartz(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
|
||||
|
|
|
|||
|
|
@ -29,13 +29,17 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
TracerSettings settings,
|
||||
PluginManager pluginManager)
|
||||
{
|
||||
// ensure WcfInitializer is added only once,
|
||||
// it is needed when either WcfClient or WcfService instrumentations are enabled
|
||||
// to initialize WcfInstrumentationOptions
|
||||
var wcfInstrumentationAdded = false;
|
||||
foreach (var enabledInstrumentation in settings.EnabledInstrumentations)
|
||||
{
|
||||
_ = enabledInstrumentation switch
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
TracerInstrumentation.AspNet => Wrappers.AddAspNetInstrumentation(builder, pluginManager, lazyInstrumentationLoader),
|
||||
TracerInstrumentation.WcfService => Wrappers.AddWcfInstrumentation(builder, pluginManager, lazyInstrumentationLoader),
|
||||
TracerInstrumentation.WcfService => AddWcfIfNeeded(builder, pluginManager, lazyInstrumentationLoader, ref wcfInstrumentationAdded),
|
||||
#endif
|
||||
TracerInstrumentation.GrpcNetClient => Wrappers.AddGrpcClientInstrumentation(builder, pluginManager, lazyInstrumentationLoader),
|
||||
TracerInstrumentation.HttpClient => Wrappers.AddHttpClientInstrumentation(builder, pluginManager, lazyInstrumentationLoader),
|
||||
|
|
@ -47,6 +51,7 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
TracerInstrumentation.MongoDB => builder.AddSource("MongoDB.Driver.Core.Extensions.DiagnosticSources"),
|
||||
TracerInstrumentation.MySqlConnector => builder.AddSource("MySqlConnector"),
|
||||
TracerInstrumentation.Azure => Wrappers.AddAzureInstrumentation(builder),
|
||||
TracerInstrumentation.WcfClient => AddWcfIfNeeded(builder, pluginManager, lazyInstrumentationLoader, ref wcfInstrumentationAdded),
|
||||
#if NET6_0_OR_GREATER
|
||||
TracerInstrumentation.AspNetCore => Wrappers.AddAspNetCoreInstrumentation(builder, pluginManager, lazyInstrumentationLoader),
|
||||
TracerInstrumentation.MassTransit => builder.AddSource("MassTransit"),
|
||||
|
|
@ -74,6 +79,23 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
return builder;
|
||||
}
|
||||
|
||||
private static TracerProviderBuilder AddWcfIfNeeded(
|
||||
TracerProviderBuilder tracerProviderBuilder,
|
||||
PluginManager pluginManager,
|
||||
LazyInstrumentationLoader lazyInstrumentationLoader,
|
||||
ref bool wcfInstrumentationAdded)
|
||||
{
|
||||
if (wcfInstrumentationAdded)
|
||||
{
|
||||
return tracerProviderBuilder;
|
||||
}
|
||||
|
||||
Wrappers.AddWcfInstrumentation(tracerProviderBuilder, pluginManager, lazyInstrumentationLoader);
|
||||
wcfInstrumentationAdded = true;
|
||||
|
||||
return tracerProviderBuilder;
|
||||
}
|
||||
|
||||
private static TracerProviderBuilder SetSampler(this TracerProviderBuilder builder, TracerSettings settings)
|
||||
{
|
||||
if (settings.TracesSampler == null)
|
||||
|
|
@ -115,7 +137,6 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
{
|
||||
// Instrumentations
|
||||
|
||||
#if NETFRAMEWORK
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddWcfInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager, LazyInstrumentationLoader lazyInstrumentationLoader)
|
||||
{
|
||||
|
|
@ -123,7 +144,6 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
|
||||
return builder.AddSource("OpenTelemetry.Instrumentation.Wcf");
|
||||
}
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddHttpClientInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager, LazyInstrumentationLoader lazyInstrumentationLoader)
|
||||
|
|
|
|||
|
|
@ -111,12 +111,11 @@ internal enum TracerInstrumentation
|
|||
/// </summary>
|
||||
AspNetCore = 15,
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
|
||||
/// <summary>
|
||||
/// WcfClient instrumentation.
|
||||
/// </summary>
|
||||
WcfClient = 16,
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// MySqlConnector instrumentation.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ internal static partial class InstrumentationDefinitions
|
|||
|
||||
private static NativeCallTargetDefinition[] GetDefinitionsArray()
|
||||
{
|
||||
var nativeCallTargetDefinitions = new List<NativeCallTargetDefinition>(10);
|
||||
var nativeCallTargetDefinitions = new List<NativeCallTargetDefinition>(9);
|
||||
// Traces
|
||||
var tracerSettings = Instrumentation.TracerSettings.Value;
|
||||
if (tracerSettings.TracesEnabled)
|
||||
|
|
@ -45,11 +45,10 @@ internal static partial class InstrumentationDefinitions
|
|||
// WcfClient
|
||||
if (tracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.WcfClient))
|
||||
{
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.Channels.ServiceChannelProxy", "Invoke", new[] {"System.Runtime.Remoting.Messaging.IMessage", "System.Runtime.Remoting.Messaging.IMessage"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.InvokeServiceChannelProxyIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.String", "System.ServiceModel.EndpointAddress"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.String", "System.ServiceModel.EndpointAddress", "System.Configuration.Configuration"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Description.ServiceEndpoint"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Channels.Binding", "System.ServiceModel.EndpointAddress"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.String", "System.ServiceModel.EndpointAddress", "System.Configuration.Configuration"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
}
|
||||
|
||||
// WcfService
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ internal static partial class InstrumentationDefinitions
|
|||
|
||||
private static NativeCallTargetDefinition[] GetDefinitionsArray()
|
||||
{
|
||||
var nativeCallTargetDefinitions = new List<NativeCallTargetDefinition>(11);
|
||||
var nativeCallTargetDefinitions = new List<NativeCallTargetDefinition>(17);
|
||||
// Traces
|
||||
var tracerSettings = Instrumentation.TracerSettings.Value;
|
||||
if (tracerSettings.TracesEnabled)
|
||||
|
|
@ -47,6 +47,17 @@ internal static partial class InstrumentationDefinitions
|
|||
nativeCallTargetDefinitions.Add(new("StackExchange.Redis", "StackExchange.Redis.ConnectionMultiplexer", "ConnectImplAsync", new[] {"System.Threading.Tasks.Task`1[StackExchange.Redis.ConnectionMultiplexer]", "StackExchange.Redis.ConfigurationOptions", "System.IO.TextWriter"}, 2, 0, 0, 2, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis.StackExchangeRedisIntegrationAsync"));
|
||||
nativeCallTargetDefinitions.Add(new("StackExchange.Redis", "StackExchange.Redis.ConnectionMultiplexer", "ConnectImplAsync", new[] {"System.Threading.Tasks.Task`1[StackExchange.Redis.ConnectionMultiplexer]", "StackExchange.Redis.ConfigurationOptions", "System.IO.TextWriter", "System.Nullable`1[StackExchange.Redis.ServerType]"}, 2, 0, 0, 2, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis.StackExchangeRedisIntegrationAsync"));
|
||||
}
|
||||
|
||||
// WcfClient
|
||||
if (tracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.WcfClient))
|
||||
{
|
||||
nativeCallTargetDefinitions.Add(new("System.Private.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.String", "System.ServiceModel.EndpointAddress"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.Private.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Description.ServiceEndpoint"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.Private.ServiceModel", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Channels.Binding", "System.ServiceModel.EndpointAddress"}, 4, 0, 0, 4, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel.Primitives", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.String", "System.ServiceModel.EndpointAddress"}, 6, 0, 0, 6, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel.Primitives", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Description.ServiceEndpoint"}, 6, 0, 0, 6, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
nativeCallTargetDefinitions.Add(new("System.ServiceModel.Primitives", "System.ServiceModel.ChannelFactory", "InitializeEndpoint", new[] {"System.Void", "System.ServiceModel.Channels.Binding", "System.ServiceModel.EndpointAddress"}, 6, 0, 0, 6, 65535, 65535, AssemblyFullName, "OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client.WcfClientIntegration"));
|
||||
}
|
||||
}
|
||||
|
||||
// Logs
|
||||
|
|
|
|||
|
|
@ -262,6 +262,10 @@ internal static class Instrumentation
|
|||
|
||||
private static void AddLazilyLoadedTraceInstrumentations(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
|
||||
{
|
||||
// ensure WcfInitializer is added only once,
|
||||
// it is needed when either WcfClient or WcfService instrumentations are enabled
|
||||
// to initialize WcfInstrumentationOptions
|
||||
var wcfInstrumentationAdded = false;
|
||||
foreach (var instrumentation in tracerSettings.EnabledInstrumentations)
|
||||
{
|
||||
switch (instrumentation)
|
||||
|
|
@ -271,7 +275,7 @@ internal static class Instrumentation
|
|||
DelayedInitialization.Traces.AddAspNet(lazyInstrumentationLoader, pluginManager);
|
||||
break;
|
||||
case TracerInstrumentation.WcfService:
|
||||
DelayedInitialization.Traces.AddWcf(lazyInstrumentationLoader, pluginManager);
|
||||
AddWcfIfNeeded(lazyInstrumentationLoader, pluginManager, ref wcfInstrumentationAdded);
|
||||
break;
|
||||
#endif
|
||||
case TracerInstrumentation.HttpClient:
|
||||
|
|
@ -286,6 +290,9 @@ internal static class Instrumentation
|
|||
case TracerInstrumentation.Quartz:
|
||||
DelayedInitialization.Traces.AddQuartz(lazyInstrumentationLoader, pluginManager);
|
||||
break;
|
||||
case TracerInstrumentation.WcfClient:
|
||||
AddWcfIfNeeded(lazyInstrumentationLoader, pluginManager, ref wcfInstrumentationAdded);
|
||||
break;
|
||||
#if NET6_0_OR_GREATER
|
||||
case TracerInstrumentation.AspNetCore:
|
||||
DelayedInitialization.Traces.AddAspNetCore(lazyInstrumentationLoader, pluginManager);
|
||||
|
|
@ -327,6 +334,20 @@ internal static class Instrumentation
|
|||
}
|
||||
}
|
||||
|
||||
private static void AddWcfIfNeeded(
|
||||
LazyInstrumentationLoader lazyInstrumentationLoader,
|
||||
PluginManager pluginManager,
|
||||
ref bool wcfInstrumentationAdded)
|
||||
{
|
||||
if (wcfInstrumentationAdded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DelayedInitialization.Traces.AddWcf(lazyInstrumentationLoader, pluginManager);
|
||||
wcfInstrumentationAdded = true;
|
||||
}
|
||||
|
||||
private static void OnExit(object? sender, EventArgs e)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _isExiting, value: 1) != 0)
|
||||
|
|
|
|||
|
|
@ -1,237 +0,0 @@
|
|||
// <copyright file="InvokeServiceChannelProxyIntegration.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.Diagnostics;
|
||||
using OpenTelemetry.AutoInstrumentation.CallTarget;
|
||||
using OpenTelemetry.AutoInstrumentation.DuckTyping;
|
||||
using OpenTelemetry.AutoInstrumentation.Util;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
|
||||
/// <summary>
|
||||
/// InvokeService integration.
|
||||
/// </summary>
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelAssemblyName,
|
||||
typeName: WcfClientConstants.ServiceChannelProxyTypeName,
|
||||
methodName: WcfClientConstants.InvokeMethodName,
|
||||
returnTypeName: WcfClientConstants.MessageTypeName,
|
||||
parameterTypeNames: new[] { WcfClientConstants.MessageTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
public static class InvokeServiceChannelProxyIntegration
|
||||
{
|
||||
private static object? _serviceEnum;
|
||||
private static object? _beginServiceEnum;
|
||||
private static object? _taskServiceEnum;
|
||||
|
||||
internal interface IServiceProxyChannel
|
||||
{
|
||||
IMethodData GetMethodData(object message);
|
||||
}
|
||||
|
||||
internal interface IMethodData
|
||||
{
|
||||
object MethodType { get; }
|
||||
}
|
||||
|
||||
private interface IExceptionReturnMessage
|
||||
{
|
||||
Exception? Exception { get; }
|
||||
}
|
||||
|
||||
private interface IReturnMessage
|
||||
{
|
||||
object ReturnValue { get; }
|
||||
}
|
||||
|
||||
private interface ISendAsyncResult
|
||||
{
|
||||
[DuckField(Name = "exception")]
|
||||
Exception? Exception { get; }
|
||||
|
||||
[DuckField(Name = "callback")]
|
||||
AsyncCallback? Callback { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnMethodBegin callback
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">Type of the target</typeparam>
|
||||
/// <typeparam name="TMessage">Type of the message</typeparam>
|
||||
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
|
||||
/// <param name="message">Message instance</param>
|
||||
/// <returns>CallTarget state value</returns>
|
||||
internal static CallTargetState OnMethodBegin<TTarget, TMessage>(TTarget instance, TMessage message)
|
||||
where TTarget : IServiceProxyChannel
|
||||
{
|
||||
var methodData = instance.GetMethodData(message!);
|
||||
var methodType = methodData.MethodType;
|
||||
|
||||
if (_serviceEnum == null || _beginServiceEnum == null || _taskServiceEnum == null)
|
||||
{
|
||||
InitializeServiceEnums(methodType);
|
||||
}
|
||||
|
||||
if (IsOfSupportedType(methodType))
|
||||
{
|
||||
var activity = WcfClientCommon.StartActivity();
|
||||
return new CallTargetState(activity: activity, methodType);
|
||||
}
|
||||
|
||||
return CallTargetState.GetDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnMethodEnd callback
|
||||
/// </summary>
|
||||
/// <param name="returnValue">Return value</param>
|
||||
/// <param name="exception">Exception value</param>
|
||||
/// <param name="callTargetState">CallTarget state</param>
|
||||
/// <typeparam name="TTarget">Type of the target</typeparam>
|
||||
/// <typeparam name="TReturn">Return type</typeparam>
|
||||
/// <returns>A response value, in an async scenario will be T of Task of T</returns>
|
||||
internal static CallTargetReturn<TReturn> OnMethodEnd<TTarget, TReturn>(TReturn returnValue, Exception? exception, in CallTargetState callTargetState)
|
||||
{
|
||||
var activity = callTargetState.Activity;
|
||||
|
||||
if (activity is null)
|
||||
{
|
||||
return new CallTargetReturn<TReturn>(returnValue);
|
||||
}
|
||||
|
||||
if (exception is not null)
|
||||
{
|
||||
StopWithException(exception, activity);
|
||||
return new CallTargetReturn<TReturn>(returnValue);
|
||||
}
|
||||
|
||||
var methodType = callTargetState.State;
|
||||
if (methodType is null)
|
||||
{
|
||||
return new CallTargetReturn<TReturn>(returnValue);
|
||||
}
|
||||
|
||||
if (methodType.Equals(_serviceEnum))
|
||||
{
|
||||
if (returnValue.TryDuckCast<IExceptionReturnMessage>(out var returnMessage))
|
||||
{
|
||||
CompleteSync(returnMessage.Exception, activity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!returnValue.TryDuckCast<IReturnMessage>(out var returnMessage))
|
||||
{
|
||||
return new CallTargetReturn<TReturn>(returnValue);
|
||||
}
|
||||
|
||||
if (methodType.Equals(_taskServiceEnum))
|
||||
{
|
||||
AttachActivityCompletionContinuation(returnMessage, activity);
|
||||
}
|
||||
else if (methodType.Equals(_beginServiceEnum))
|
||||
{
|
||||
OverrideCallback(returnMessage.ReturnValue, activity);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Activity.Current = activity.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
return new CallTargetReturn<TReturn>(returnValue);
|
||||
}
|
||||
|
||||
private static void OverrideCallback(object sendAsyncResult, Activity activity)
|
||||
{
|
||||
var duckCastedAsyncResult = DuckCast(sendAsyncResult);
|
||||
|
||||
var initialCallback = duckCastedAsyncResult.Callback;
|
||||
duckCastedAsyncResult.Callback = NewCallback;
|
||||
void NewCallback(IAsyncResult asyncResult)
|
||||
{
|
||||
var e = duckCastedAsyncResult.Exception;
|
||||
if (e != null)
|
||||
{
|
||||
activity.SetException(e);
|
||||
activity.Stop();
|
||||
}
|
||||
|
||||
initialCallback?.Invoke(asyncResult);
|
||||
}
|
||||
}
|
||||
|
||||
private static ISendAsyncResult DuckCast(object sendAsyncResult)
|
||||
{
|
||||
// we are interested in private fields of grandparent type
|
||||
var targetType = sendAsyncResult.GetType().BaseType.BaseType;
|
||||
var createTypeResult = DuckType.CreateCache<ISendAsyncResult>.GetProxy(targetType);
|
||||
return createTypeResult.CreateInstance<ISendAsyncResult>(sendAsyncResult);
|
||||
}
|
||||
|
||||
private static void StopWithException(Exception exception, Activity activity)
|
||||
{
|
||||
activity.SetException(exception);
|
||||
activity.Stop();
|
||||
}
|
||||
|
||||
private static bool IsOfSupportedType(object methodType)
|
||||
{
|
||||
return methodType.Equals(_serviceEnum) || methodType.Equals(_beginServiceEnum) || methodType.Equals(_taskServiceEnum);
|
||||
}
|
||||
|
||||
private static void InitializeServiceEnums(object methodType)
|
||||
{
|
||||
var type = methodType.GetType();
|
||||
_serviceEnum = Enum.Parse(type, "Service");
|
||||
_beginServiceEnum = Enum.Parse(type, "BeginService");
|
||||
_taskServiceEnum = Enum.Parse(type, "TaskService");
|
||||
}
|
||||
|
||||
private static void AttachActivityCompletionContinuation(IReturnMessage returnValue, Activity activity)
|
||||
{
|
||||
var task = returnValue.ReturnValue as Task;
|
||||
task?.ContinueWith(
|
||||
(t, a) =>
|
||||
{
|
||||
var localActivity = a as Activity;
|
||||
if (t.Exception is not null)
|
||||
{
|
||||
localActivity.SetException(t.Exception.InnerException);
|
||||
localActivity?.Stop();
|
||||
}
|
||||
},
|
||||
activity,
|
||||
continuationOptions: TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.HideScheduler);
|
||||
}
|
||||
|
||||
private static void CompleteSync(Exception? ex, Activity activity)
|
||||
{
|
||||
if (ex != null)
|
||||
{
|
||||
activity.SetException(ex);
|
||||
activity.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
using OpenTelemetry.AutoInstrumentation.Configurations;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
|
|
@ -21,28 +20,10 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
|||
internal static class WcfClientConstants
|
||||
{
|
||||
public const string ChannelFactoryTypeName = "System.ServiceModel.ChannelFactory";
|
||||
public const string ServiceChannelProxyTypeName = "System.ServiceModel.Channels.ServiceChannelProxy";
|
||||
public const string MessageTypeName = "System.Runtime.Remoting.Messaging.IMessage";
|
||||
public const string InitializeEndpointMethodName = "InitializeEndpoint";
|
||||
public const string InvokeMethodName = "Invoke";
|
||||
public const string IntegrationName = nameof(TracerInstrumentation.WcfClient);
|
||||
public const string EndpointAddressTypeName = "System.ServiceModel.EndpointAddress";
|
||||
public const string ServiceEndpointTypeName = "System.ServiceModel.Description.ServiceEndpoint";
|
||||
public const string BindingTypeName = "System.ServiceModel.Channels.Binding";
|
||||
public const string ConfigurationTypeName = "System.Configuration.Configuration";
|
||||
|
||||
// source originated from: https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/06b9a286a6ab2af5257ce26b5dcb6fac56112f96/src/OpenTelemetry.Instrumentation.Wcf
|
||||
public const string RpcSystemTag = "rpc.system";
|
||||
public const string RpcServiceTag = "rpc.service";
|
||||
public const string RpcMethodTag = "rpc.method";
|
||||
public const string NetPeerNameTag = "net.peer.name";
|
||||
public const string NetPeerPortTag = "net.peer.port";
|
||||
public const string SoapMessageVersionTag = "soap.message_version";
|
||||
public const string SoapReplyActionTag = "soap.reply_action";
|
||||
public const string SoapViaTag = "soap.via";
|
||||
public const string WcfChannelSchemeTag = "wcf.channel.scheme";
|
||||
public const string WcfChannelPathTag = "wcf.channel.path";
|
||||
|
||||
public const string WcfSystemValue = "dotnet_wcf";
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
// <copyright file="WcfClientEndpointBehavior.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.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
// source originated from: https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/06b9a286a6ab2af5257ce26b5dcb6fac56112f96/src/OpenTelemetry.Instrumentation.Wcf
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
|
||||
/// <inheritdoc />
|
||||
internal class WcfClientEndpointBehavior : IEndpointBehavior
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void Validate(ServiceEndpoint endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
var actionMappings = new Dictionary<string, ActionMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var clientOperation in clientRuntime.ClientOperations)
|
||||
{
|
||||
actionMappings[clientOperation.Action] = new ActionMetadata($"{clientRuntime.ContractNamespace}{clientRuntime.ContractName}", clientOperation.Name);
|
||||
}
|
||||
|
||||
clientRuntime.ClientMessageInspectors.Add(new WcfClientMessageInspector(actionMappings));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using OpenTelemetry.Instrumentation.Wcf;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
|
||||
|
|
@ -33,10 +33,9 @@ internal static class WcfClientInitializer
|
|||
public static void Initialize(IChannelFactory channelFactory)
|
||||
{
|
||||
var behaviors = channelFactory.Endpoint.Behaviors;
|
||||
if (!behaviors.Contains(typeof(WcfClientEndpointBehavior)))
|
||||
if (!behaviors.Contains(typeof(TelemetryEndpointBehavior)))
|
||||
{
|
||||
behaviors.Add(new WcfClientEndpointBehavior());
|
||||
behaviors.Add(new TelemetryEndpointBehavior());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
|
||||
using OpenTelemetry.AutoInstrumentation.CallTarget;
|
||||
|
||||
|
|
@ -28,18 +27,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
|||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { ClrNames.String, WcfClientConstants.EndpointAddressTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelAssemblyName,
|
||||
typeName: WcfClientConstants.ChannelFactoryTypeName,
|
||||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { ClrNames.String, WcfClientConstants.EndpointAddressTypeName, WcfClientConstants.ConfigurationTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
minimumVersion: WcfCommonConstants.Min4Version,
|
||||
maximumVersion: WcfCommonConstants.Max4Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
[InstrumentMethod(
|
||||
|
|
@ -48,8 +37,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
|||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { WcfClientConstants.ServiceEndpointTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
minimumVersion: WcfCommonConstants.Min4Version,
|
||||
maximumVersion: WcfCommonConstants.Max4Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
[InstrumentMethod(
|
||||
|
|
@ -58,10 +47,54 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
|||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { WcfClientConstants.BindingTypeName, WcfClientConstants.EndpointAddressTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
minimumVersion: WcfCommonConstants.Min4Version,
|
||||
maximumVersion: WcfCommonConstants.Max4Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
#if NET6_0_OR_GREATER
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelPrimitivesAssemblyName,
|
||||
typeName: WcfClientConstants.ChannelFactoryTypeName,
|
||||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { ClrNames.String, WcfClientConstants.EndpointAddressTypeName },
|
||||
minimumVersion: WcfCommonConstants.Min6Version,
|
||||
maximumVersion: WcfCommonConstants.Max6Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelPrimitivesAssemblyName,
|
||||
typeName: WcfClientConstants.ChannelFactoryTypeName,
|
||||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { WcfClientConstants.ServiceEndpointTypeName },
|
||||
minimumVersion: WcfCommonConstants.Min6Version,
|
||||
maximumVersion: WcfCommonConstants.Max6Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelPrimitivesAssemblyName,
|
||||
typeName: WcfClientConstants.ChannelFactoryTypeName,
|
||||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { WcfClientConstants.BindingTypeName, WcfClientConstants.EndpointAddressTypeName },
|
||||
minimumVersion: WcfCommonConstants.Min6Version,
|
||||
maximumVersion: WcfCommonConstants.Max6Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
[InstrumentMethod(
|
||||
assemblyName: WcfCommonConstants.ServiceModelAssemblyName,
|
||||
typeName: WcfClientConstants.ChannelFactoryTypeName,
|
||||
methodName: WcfClientConstants.InitializeEndpointMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { ClrNames.String, WcfClientConstants.EndpointAddressTypeName, WcfClientConstants.ConfigurationTypeName },
|
||||
minimumVersion: WcfCommonConstants.Min4Version,
|
||||
maximumVersion: WcfCommonConstants.Max4Version,
|
||||
integrationName: WcfClientConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
#endif
|
||||
public static class WcfClientIntegration
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -80,4 +113,3 @@ public static class WcfClientIntegration
|
|||
return CallTargetReturn.GetDefault();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
// <copyright file="WcfClientMessageInspector.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.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using OpenTelemetry.Context.Propagation;
|
||||
using OpenTelemetry.Trace;
|
||||
using Status = OpenTelemetry.Trace.Status;
|
||||
|
||||
// source originated from: https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/06b9a286a6ab2af5257ce26b5dcb6fac56112f96/src/OpenTelemetry.Instrumentation.Wcf
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
|
||||
/// <summary>
|
||||
/// Telemetry client message inspector.
|
||||
/// </summary>
|
||||
internal class WcfClientMessageInspector : IClientMessageInspector
|
||||
{
|
||||
private readonly Dictionary<string, ActionMetadata> _actionMappings;
|
||||
|
||||
public WcfClientMessageInspector(Dictionary<string, ActionMetadata> actionMappings)
|
||||
{
|
||||
_actionMappings = actionMappings;
|
||||
}
|
||||
|
||||
private static Action<Message, string, string> MessageHeaderValueSetter { get; }
|
||||
= (request, name, value) => request.Headers.Add(MessageHeader.CreateHeader(name, "https://www.w3.org/TR/trace-context/", value, false));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object BeforeSendRequest(ref Message request, IClientChannel channel)
|
||||
{
|
||||
var activity = Activity.Current;
|
||||
if (activity is { Source.Name: "OpenTelemetry.AutoInstrumentation.Wcf" })
|
||||
{
|
||||
string action;
|
||||
if (!string.IsNullOrEmpty(request.Headers.Action))
|
||||
{
|
||||
action = request.Headers.Action;
|
||||
activity.DisplayName = action;
|
||||
}
|
||||
else
|
||||
{
|
||||
action = string.Empty;
|
||||
}
|
||||
|
||||
Propagators.DefaultTextMapPropagator.Inject(
|
||||
new PropagationContext(activity.Context, Baggage.Current),
|
||||
request,
|
||||
MessageHeaderValueSetter);
|
||||
|
||||
if (activity.IsAllDataRequested)
|
||||
{
|
||||
activity.SetTag(WcfClientConstants.RpcSystemTag, WcfClientConstants.WcfSystemValue);
|
||||
|
||||
if (!_actionMappings.TryGetValue(action, out ActionMetadata actionMetadata))
|
||||
{
|
||||
actionMetadata = new ActionMetadata(null, action);
|
||||
}
|
||||
|
||||
activity.SetTag(WcfClientConstants.RpcServiceTag, actionMetadata.ContractName);
|
||||
activity.SetTag(WcfClientConstants.RpcMethodTag, actionMetadata.OperationName);
|
||||
|
||||
activity.SetTag(WcfClientConstants.SoapMessageVersionTag, request.Version.ToString());
|
||||
|
||||
var remoteAddressUri = request.Headers.To ?? channel.RemoteAddress?.Uri;
|
||||
if (remoteAddressUri != null)
|
||||
{
|
||||
activity.SetTag(WcfClientConstants.NetPeerNameTag, remoteAddressUri.Host);
|
||||
activity.SetTag(WcfClientConstants.NetPeerPortTag, remoteAddressUri.Port);
|
||||
activity.SetTag(WcfClientConstants.WcfChannelSchemeTag, remoteAddressUri.Scheme);
|
||||
activity.SetTag(WcfClientConstants.WcfChannelPathTag, remoteAddressUri.LocalPath);
|
||||
}
|
||||
|
||||
if (request.Properties.Via != null)
|
||||
{
|
||||
activity.SetTag(WcfClientConstants.SoapViaTag, request.Properties.Via.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return new CorrelationState(activity);
|
||||
}
|
||||
|
||||
return new CorrelationState(null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AfterReceiveReply(ref Message reply, object correlationState)
|
||||
{
|
||||
var state = correlationState as CorrelationState;
|
||||
if (state?.Activity is { IsStopped: false } activity)
|
||||
{
|
||||
if (activity.IsAllDataRequested)
|
||||
{
|
||||
if (reply.IsFault)
|
||||
{
|
||||
activity.SetStatus(Status.Error);
|
||||
}
|
||||
|
||||
activity.SetTag(WcfClientConstants.SoapReplyActionTag, reply.Headers.Action);
|
||||
}
|
||||
|
||||
activity.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: inline
|
||||
private class CorrelationState
|
||||
{
|
||||
public CorrelationState(Activity? activity)
|
||||
{
|
||||
Activity = activity;
|
||||
}
|
||||
|
||||
public Activity? Activity { get; }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf;
|
||||
|
||||
internal interface IKeyedByTypeCollection
|
||||
|
|
@ -22,4 +21,3 @@ internal interface IKeyedByTypeCollection
|
|||
|
||||
bool Contains(Type t);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Service;
|
|||
methodName: WcfServiceConstants.InitializeDescriptionMethodName,
|
||||
returnTypeName: ClrNames.Void,
|
||||
parameterTypeNames: new[] { WcfServiceConstants.UriSchemeKeyedCollectionTypeName },
|
||||
minimumVersion: WcfCommonConstants.MinVersion,
|
||||
maximumVersion: WcfCommonConstants.MaxVersion,
|
||||
minimumVersion: WcfCommonConstants.Min4Version,
|
||||
maximumVersion: WcfCommonConstants.Max4Version,
|
||||
integrationName: WcfServiceConstants.IntegrationName,
|
||||
type: InstrumentationType.Trace)]
|
||||
public static class ServiceHostIntegration
|
||||
|
|
|
|||
|
|
@ -13,13 +13,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf;
|
||||
|
||||
internal static class WcfCommonConstants
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
public const string ServiceModelAssemblyName = "System.ServiceModel";
|
||||
public const string MinVersion = "4.0.0";
|
||||
public const string MaxVersion = "4.*.*";
|
||||
}
|
||||
#else
|
||||
public const string ServiceModelAssemblyName = "System.Private.ServiceModel";
|
||||
|
||||
public const string ServiceModelPrimitivesAssemblyName = "System.ServiceModel.Primitives";
|
||||
public const string Min6Version = "6.0.0";
|
||||
public const string Max6Version = "6.*.*";
|
||||
#endif
|
||||
public const string Min4Version = "4.0.0";
|
||||
public const string Max4Version = "4.*.*";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
#if NETFRAMEWORK
|
||||
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Instrumentation.Wcf;
|
||||
|
||||
|
|
@ -46,4 +44,3 @@ internal class WcfInitializer : InstrumentationInitializer
|
|||
instrumentationType?.GetProperty("Options")?.SetValue(null, options);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<PackageReference Include="OpenTelemetry.ResourceDetectors.Azure" />
|
||||
<PackageReference Include="OpenTelemetry.ResourceDetectors.Container" />
|
||||
<PackageReference Include="OpenTelemetry.Shims.OpenTracing" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Wcf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
|
||||
|
|
@ -47,7 +48,6 @@
|
|||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNet" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Wcf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
<PackageVersion Include="System.Reactive" Version="6.0.0" />
|
||||
<PackageVersion Include="System.Runtime.InteropServices" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
|
||||
<PackageVersion Include="System.ServiceModel.Http" Version="6.0.0" />
|
||||
<PackageVersion Include="System.ServiceModel.NetTcp" Version="6.0.0" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageVersion Include="Testcontainers" Version="3.4.0" />
|
||||
<PackageVersion Include="Verify.Xunit" Version="20.8.2" />
|
||||
|
|
|
|||
|
|
@ -34,13 +34,17 @@
|
|||
/net/OpenTelemetry.Instrumentation.Runtime.dll,
|
||||
/net/OpenTelemetry.Instrumentation.SqlClient.dll,
|
||||
/net/OpenTelemetry.Instrumentation.StackExchangeRedis.dll,
|
||||
/net/OpenTelemetry.Instrumentation.Wcf.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Azure.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Container.dll,
|
||||
/net/OpenTelemetry.Shims.OpenTracing.dll,
|
||||
/net/OpenTelemetry.dll,
|
||||
/net/OpenTracing.dll,
|
||||
/net/System.Diagnostics.DiagnosticSource.dll,
|
||||
/net/System.Private.ServiceModel.dll,
|
||||
/net/System.Security.Permissions.dll,
|
||||
/net/System.ServiceModel.Primitives.dll,
|
||||
/net/System.ServiceModel.dll,
|
||||
/net/ruleEngine.json,
|
||||
/store/x64/net6.0/microsoft.extensions.configuration.abstractions/7.0.0/lib/net7.0/Microsoft.Extensions.Configuration.Abstractions.dll,
|
||||
/store/x64/net6.0/microsoft.extensions.configuration.binder/7.0.0/lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll,
|
||||
|
|
|
|||
|
|
@ -34,13 +34,17 @@
|
|||
/net/OpenTelemetry.Instrumentation.Runtime.dll,
|
||||
/net/OpenTelemetry.Instrumentation.SqlClient.dll,
|
||||
/net/OpenTelemetry.Instrumentation.StackExchangeRedis.dll,
|
||||
/net/OpenTelemetry.Instrumentation.Wcf.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Azure.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Container.dll,
|
||||
/net/OpenTelemetry.Shims.OpenTracing.dll,
|
||||
/net/OpenTelemetry.dll,
|
||||
/net/OpenTracing.dll,
|
||||
/net/System.Diagnostics.DiagnosticSource.dll,
|
||||
/net/System.Private.ServiceModel.dll,
|
||||
/net/System.Security.Permissions.dll,
|
||||
/net/System.ServiceModel.Primitives.dll,
|
||||
/net/System.ServiceModel.dll,
|
||||
/net/ruleEngine.json,
|
||||
/store/x64/net6.0/microsoft.extensions.configuration.abstractions/7.0.0/lib/net7.0/Microsoft.Extensions.Configuration.Abstractions.dll,
|
||||
/store/x64/net6.0/microsoft.extensions.configuration.binder/7.0.0/lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll,
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@
|
|||
/net/OpenTelemetry.Instrumentation.Runtime.dll,
|
||||
/net/OpenTelemetry.Instrumentation.SqlClient.dll,
|
||||
/net/OpenTelemetry.Instrumentation.StackExchangeRedis.dll,
|
||||
/net/OpenTelemetry.Instrumentation.Wcf.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Azure.dll,
|
||||
/net/OpenTelemetry.ResourceDetectors.Container.dll,
|
||||
/net/OpenTelemetry.Shims.OpenTracing.dll,
|
||||
/net/OpenTelemetry.dll,
|
||||
/net/OpenTracing.dll,
|
||||
/net/System.Diagnostics.DiagnosticSource.dll,
|
||||
/net/System.Private.ServiceModel.dll,
|
||||
/net/System.Security.Permissions.dll,
|
||||
/net/System.ServiceModel.Primitives.dll,
|
||||
/net/System.ServiceModel.dll,
|
||||
/net/ruleEngine.json,
|
||||
/osx-x64/OpenTelemetry.AutoInstrumentation.Native.dylib,
|
||||
/store/x64/net6.0/microsoft.extensions.configuration.abstractions/7.0.0/lib/net7.0/Microsoft.Extensions.Configuration.Abstractions.dll,
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@
|
|||
\net\OpenTelemetry.Instrumentation.Runtime.dll,
|
||||
\net\OpenTelemetry.Instrumentation.SqlClient.dll,
|
||||
\net\OpenTelemetry.Instrumentation.StackExchangeRedis.dll,
|
||||
\net\OpenTelemetry.Instrumentation.Wcf.dll,
|
||||
\net\OpenTelemetry.ResourceDetectors.Azure.dll,
|
||||
\net\OpenTelemetry.ResourceDetectors.Container.dll,
|
||||
\net\OpenTelemetry.Shims.OpenTracing.dll,
|
||||
\net\OpenTelemetry.dll,
|
||||
\net\OpenTracing.dll,
|
||||
\net\System.Diagnostics.DiagnosticSource.dll,
|
||||
\net\System.Private.ServiceModel.dll,
|
||||
\net\System.Security.Permissions.dll,
|
||||
\net\System.ServiceModel.Primitives.dll,
|
||||
\net\System.ServiceModel.dll,
|
||||
\net\ruleEngine.json,
|
||||
\netfx\Google.Protobuf.dll,
|
||||
\netfx\Grpc.Core.Api.dll,
|
||||
|
|
|
|||
|
|
@ -152,6 +152,15 @@ public static class LibraryVersion
|
|||
new object[] { "2.5.61" },
|
||||
new object[] { "2.6.66" },
|
||||
new object[] { "2.6.122" },
|
||||
#endif
|
||||
};
|
||||
public static readonly IReadOnlyCollection<object[]> WCFCoreClient = new List<object[]>
|
||||
{
|
||||
#if DEFAULT_TEST_PACKAGE_VERSIONS
|
||||
new object[] { string.Empty }
|
||||
#else
|
||||
new object[] { "4.10.2" },
|
||||
new object[] { "6.0.0" },
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,72 +13,26 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
|
||||
using IntegrationTests.Helpers;
|
||||
using OpenTelemetry.Proto.Common.V1;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
|
||||
namespace IntegrationTests;
|
||||
|
||||
internal static class WcfClientInstrumentation
|
||||
{
|
||||
public const string NetTcpBindingMessageVersion = "Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)";
|
||||
public const string HttpBindingMessageVersion = "Soap11 (http://schemas.xmlsoap.org/soap/envelope/) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)";
|
||||
public const string NetTcpChannelScheme = "net.tcp";
|
||||
public const string HttpChannelScheme = "http";
|
||||
|
||||
public static bool ValidateBasicSpanExpectations(
|
||||
Span span,
|
||||
string expectedChannelScheme,
|
||||
string expectedChannelPath,
|
||||
string expectedPeerName,
|
||||
int expectedPeerPort,
|
||||
string expectedMessageVersion)
|
||||
{
|
||||
var attributes = span.Attributes;
|
||||
var rpcSystem = ExtractAttribute(attributes, "rpc.system");
|
||||
var rpcService = ExtractAttribute(attributes, "rpc.service");
|
||||
var rpcMethod = ExtractAttribute(attributes, "rpc.method");
|
||||
var soapMessageVersion = ExtractAttribute(attributes, "soap.message_version");
|
||||
var netPeerPort = ExtractAttribute(attributes, "net.peer.port");
|
||||
var netPeerName = ExtractAttribute(attributes, "net.peer.name");
|
||||
var channelSchemeTag = ExtractAttribute(attributes, "wcf.channel.scheme");
|
||||
var channelPath = ExtractAttribute(attributes, "wcf.channel.path");
|
||||
return span.Kind == Span.Types.SpanKind.Client &&
|
||||
rpcSystem.Value.StringValue == "dotnet_wcf" &&
|
||||
rpcService.Value.StringValue == "http://opentelemetry.io/StatusService" &&
|
||||
rpcMethod.Value.StringValue == "Ping" &&
|
||||
netPeerName.Value.StringValue == expectedPeerName &&
|
||||
netPeerPort.Value.IntValue == expectedPeerPort &&
|
||||
channelSchemeTag.Value.StringValue == expectedChannelScheme &&
|
||||
soapMessageVersion.Value.StringValue == expectedMessageVersion &&
|
||||
channelPath.Value.StringValue == expectedChannelPath;
|
||||
}
|
||||
|
||||
public static bool ValidateSpanSuccessStatus(Span span)
|
||||
{
|
||||
return span.Status == null;
|
||||
}
|
||||
|
||||
public static bool ValidateExpectedSpanHierarchy(ICollection<MockSpansCollector.Collected> assertedSpans)
|
||||
{
|
||||
var customParent = assertedSpans.Single(collected =>
|
||||
collected.InstrumentationScopeName == "TestApplication.Wcf.Client.NetFramework" &&
|
||||
collected.InstrumentationScopeName.StartsWith("TestApplication.Wcf.Client") &&
|
||||
collected.Span.Name == "Parent");
|
||||
var customSibling = assertedSpans.Single(collected =>
|
||||
collected.InstrumentationScopeName == "TestApplication.Wcf.Client.NetFramework" &&
|
||||
collected.InstrumentationScopeName.StartsWith("TestApplication.Wcf.Client") &&
|
||||
collected.Span.Name == "Sibling");
|
||||
var wcfClientSpans = assertedSpans.Where(collected =>
|
||||
collected.InstrumentationScopeName == "OpenTelemetry.AutoInstrumentation.Wcf");
|
||||
collected.Span.Kind == Span.Types.SpanKind.Client &&
|
||||
collected.InstrumentationScopeName == "OpenTelemetry.Instrumentation.Wcf");
|
||||
|
||||
return wcfClientSpans.All(span => span.Span.ParentSpanId == customParent.Span.SpanId) &&
|
||||
customSibling.Span.ParentSpanId == customParent.Span.SpanId;
|
||||
}
|
||||
|
||||
private static KeyValue ExtractAttribute(IEnumerable<KeyValue> attributes, string key)
|
||||
{
|
||||
return attributes.Single(kv => kv.Key == key);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// <copyright file="WcfDotNetTests.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>
|
||||
|
||||
// This test won't work outside of windows as it need the server side which is .NET Framework only.
|
||||
#if NET6_0_OR_GREATER && _WINDOWS
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace IntegrationTests;
|
||||
|
||||
public class WcfDotNetTests : WcfTestsBase
|
||||
{
|
||||
public WcfDotNetTests(ITestOutputHelper output)
|
||||
: base("Wcf.Client.DotNet", output)
|
||||
{
|
||||
}
|
||||
|
||||
[Trait("Category", "EndToEnd")]
|
||||
[Theory]
|
||||
[MemberData(nameof(LibraryVersion.WCFCoreClient), MemberType = typeof(LibraryVersion))]
|
||||
public async Task SubmitTraces(string clientPackageVersion)
|
||||
{
|
||||
EnableBytecodeInstrumentation();
|
||||
await SubmitsTracesInternal(clientPackageVersion);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Containers;
|
||||
using FluentAssertions;
|
||||
using Google.Protobuf;
|
||||
using IntegrationTests.Helpers;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
using Xunit.Abstractions;
|
||||
|
|
@ -27,8 +26,6 @@ namespace IntegrationTests;
|
|||
|
||||
public class WcfIISTests : TestHelper
|
||||
{
|
||||
private const string ExpectedChannelPath = "/StatusService.svc";
|
||||
private const string ExpectedPeerName = "localhost";
|
||||
private readonly Dictionary<string, string> _environmentVariables = new();
|
||||
|
||||
public WcfIISTests(ITestOutputHelper output)
|
||||
|
|
@ -54,18 +51,11 @@ public class WcfIISTests : TestHelper
|
|||
var netTcpPort = TcpPortProvider.GetOpenPort();
|
||||
var httpPort = TcpPortProvider.GetOpenPort();
|
||||
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 3");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 4");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 5");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 6");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server, "Server 1");
|
||||
// filtering by name required, because client instrumentation creates some additional spans, e.g for connection registration
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client && span.Name == "http://opentelemetry.io/StatusService/Ping", "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server, "Server 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client && span.Name == "http://opentelemetry.io/StatusService/Ping", "Client 2");
|
||||
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom parent");
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom sibling");
|
||||
|
|
|
|||
|
|
@ -15,10 +15,7 @@
|
|||
// </copyright>
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.Collections;
|
||||
using IntegrationTests.Helpers;
|
||||
using OpenTelemetry.Proto.Common.V1;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
|
@ -26,11 +23,6 @@ namespace IntegrationTests;
|
|||
|
||||
public class WcfNetFrameworkTests : WcfTestsBase
|
||||
{
|
||||
private const int NetTcpPort = 9090;
|
||||
private const int HttpPort = 9009;
|
||||
private const string ExpectedChannelPath = "/Telemetry";
|
||||
private const string ExpectedPeerName = "127.0.0.1";
|
||||
|
||||
public WcfNetFrameworkTests(ITestOutputHelper output)
|
||||
: base("Wcf.Client.NetFramework", output)
|
||||
{
|
||||
|
|
@ -40,26 +32,7 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
[Trait("Category", "EndToEnd")]
|
||||
public async Task SubmitsTraces()
|
||||
{
|
||||
using var collector = await SubmitsTracesInternal(string.Empty);
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 3");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 4");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 5");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && WcfClientInstrumentation.ValidateSpanSuccessStatus(span), "Client 6");
|
||||
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom parent");
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom sibling");
|
||||
|
||||
collector.ExpectCollected(WcfClientInstrumentation.ValidateExpectedSpanHierarchy);
|
||||
|
||||
collector.AssertExpectations();
|
||||
await SubmitsTracesInternal(string.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -69,9 +42,7 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
using var collector = new MockSpansCollector(Output);
|
||||
SetExporter(collector);
|
||||
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 3");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Status.Code == Status.Types.StatusCode.Error, "Client 1");
|
||||
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom parent");
|
||||
collector.Expect("TestApplication.Wcf.Client.NetFramework", span => span.Kind == Span.Types.SpanKind.Internal, "Custom sibling");
|
||||
|
|
@ -85,11 +56,6 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
|
||||
collector.AssertExpectations();
|
||||
}
|
||||
|
||||
private static bool ValidateErrorSpanExpectations(Span span)
|
||||
{
|
||||
return WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && span.Status.Code == Status.Types.StatusCode.Error;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,18 +17,19 @@
|
|||
using System.Net.Sockets;
|
||||
using FluentAssertions;
|
||||
using IntegrationTests.Helpers;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
using Xunit.Abstractions;
|
||||
using static OpenTelemetry.Proto.Trace.V1.Span.Types;
|
||||
|
||||
namespace IntegrationTests;
|
||||
public abstract class WcfTestsBase : TestHelper, IDisposable
|
||||
{
|
||||
private readonly string _testAppName;
|
||||
private ProcessHelper? _serverProcess;
|
||||
|
||||
protected WcfTestsBase(string testAppName, ITestOutputHelper output)
|
||||
: base(testAppName, output)
|
||||
{
|
||||
_testAppName = testAppName;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -52,7 +53,7 @@ public abstract class WcfTestsBase : TestHelper, IDisposable
|
|||
Output.WriteResult(_serverProcess);
|
||||
}
|
||||
|
||||
protected async Task<MockSpansCollector> SubmitsTracesInternal(string clientPackageVersion)
|
||||
protected async Task SubmitsTracesInternal(string clientPackageVersion)
|
||||
{
|
||||
EnvironmentTools.IsWindowsAdministrator().Should().BeTrue(); // WCF Server needs admin
|
||||
|
||||
|
|
@ -68,7 +69,17 @@ public abstract class WcfTestsBase : TestHelper, IDisposable
|
|||
PackageVersion = clientPackageVersion
|
||||
});
|
||||
|
||||
return collector;
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == SpanKind.Server, "Server 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == SpanKind.Client, "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == SpanKind.Server, "Server 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == SpanKind.Client, "Client 2");
|
||||
|
||||
collector.Expect($"TestApplication.{_testAppName}", span => span.Kind == SpanKind.Internal, "Custom parent");
|
||||
collector.Expect($"TestApplication.{_testAppName}", span => span.Kind == SpanKind.Internal, "Custom sibling");
|
||||
|
||||
collector.ExpectCollected(WcfClientInstrumentation.ValidateExpectedSpanHierarchy);
|
||||
|
||||
collector.AssertExpectations();
|
||||
}
|
||||
|
||||
private async Task WaitForServer()
|
||||
|
|
|
|||
|
|
@ -246,9 +246,7 @@ public class SettingsTests : IDisposable
|
|||
[InlineData("ENTITYFRAMEWORKCORE", TracerInstrumentation.EntityFrameworkCore)]
|
||||
[InlineData("ASPNETCORE", TracerInstrumentation.AspNetCore)]
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
[InlineData("WCFCLIENT", TracerInstrumentation.WcfClient)]
|
||||
#endif
|
||||
[InlineData("MYSQLCONNECTOR", TracerInstrumentation.MySqlConnector)]
|
||||
[InlineData("AZURE", TracerInstrumentation.Azure)]
|
||||
internal void TracerSettings_Instrumentations_SupportedValues(string tracerInstrumentation, TracerInstrumentation expectedTracerInstrumentation)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// <copyright file="WcfClientCommon.cs" company="OpenTelemetry Authors">
|
||||
// <copyright file="IStatusServiceContract.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -14,20 +14,14 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
namespace TestApplication.Wcf.Client.DotNet;
|
||||
|
||||
internal static class WcfClientCommon
|
||||
[ServiceContract(Namespace = "http://opentelemetry.io/", Name = "StatusService", SessionMode = SessionMode.Allowed)]
|
||||
public interface IStatusServiceContract
|
||||
{
|
||||
private static readonly ActivitySource Source = new("OpenTelemetry.AutoInstrumentation.Wcf", AutoInstrumentationVersion.Version);
|
||||
|
||||
private static readonly string OutgoingActivityName = $"{Source.Name}.OutgoingActivity";
|
||||
|
||||
internal static Activity? StartActivity()
|
||||
{
|
||||
return Source.StartActivity(OutgoingActivityName, ActivityKind.Client);
|
||||
}
|
||||
[OperationContract]
|
||||
Task<StatusResponse> PingAsync(StatusRequest request);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// <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.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
|
||||
namespace TestApplication.Wcf.Client.DotNet;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
private static readonly ActivitySource Source = new(Assembly.GetExecutingAssembly().GetName().Name!, "1.0.0.0");
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
var netTcpAddress = "net.tcp://127.0.0.1:9090/Telemetry";
|
||||
var httpAddress = "http://127.0.0.1:9009/Telemetry";
|
||||
|
||||
using var parent = Source.StartActivity("Parent");
|
||||
try
|
||||
{
|
||||
Console.WriteLine("=============NetTcp===============");
|
||||
await CallService(netTcpAddress, new NetTcpBinding(SecurityMode.None)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// netTcp fails on open when there is no endpoint
|
||||
}
|
||||
|
||||
Console.WriteLine("=============Http===============");
|
||||
await CallService(httpAddress, new BasicHttpBinding()).ConfigureAwait(false);
|
||||
using var sibling = Source.StartActivity("Sibling");
|
||||
}
|
||||
|
||||
private static async Task CallService(string address, Binding binding)
|
||||
{
|
||||
// Note: Best practice is to re-use your client/channel instances.
|
||||
// This code is not meant to illustrate best practices, only the
|
||||
// instrumentation.
|
||||
var client = new StatusServiceClient(binding, new EndpointAddress(new Uri(address)));
|
||||
await client.OpenAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Task-based Asynchronous Pattern call");
|
||||
var rq = new StatusRequest { Status = "1" };
|
||||
var response = await client.PingAsync(rq).ConfigureAwait(false);
|
||||
|
||||
Console.WriteLine(
|
||||
$"[{DateTimeOffset.UtcNow:o}] Request with status {rq.Status}. Server returned: {response?.ServerTime:o}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (client.State == CommunicationState.Faulted)
|
||||
{
|
||||
client.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
await client.CloseAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// <copyright file="StatusRequest.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.Runtime.Serialization;
|
||||
|
||||
namespace TestApplication.Wcf.Client.DotNet;
|
||||
|
||||
[DataContract(Namespace = "http://opentelemetry.io/")]
|
||||
public class StatusRequest
|
||||
{
|
||||
[DataMember]
|
||||
public string? Status { get; set; }
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// <copyright file="ActionMetadata.cs" company="OpenTelemetry Authors">
|
||||
// <copyright file="StatusResponse.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -14,19 +14,13 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
// source originated from: https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/06b9a286a6ab2af5257ce26b5dcb6fac56112f96/src/OpenTelemetry.Instrumentation.Wcf
|
||||
#if NETFRAMEWORK
|
||||
namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf.Client;
|
||||
internal sealed class ActionMetadata
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TestApplication.Wcf.Client.DotNet;
|
||||
|
||||
[DataContract(Namespace = "http://opentelemetry.io/")]
|
||||
public class StatusResponse
|
||||
{
|
||||
public ActionMetadata(string? contractName, string operationName)
|
||||
{
|
||||
ContractName = contractName;
|
||||
OperationName = operationName;
|
||||
}
|
||||
|
||||
public string? ContractName { get; }
|
||||
|
||||
public string OperationName { get; }
|
||||
[DataMember]
|
||||
public DateTimeOffset ServerTime { get; set; }
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// <copyright file="StatusServiceClient.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.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TestApplication.Wcf.Client.DotNet;
|
||||
|
||||
public class StatusServiceClient : ClientBase<IStatusServiceContract>, IStatusServiceContract
|
||||
{
|
||||
public StatusServiceClient(Binding binding, EndpointAddress remoteAddress)
|
||||
: base(binding, remoteAddress)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<StatusResponse> PingAsync(StatusRequest request)
|
||||
{
|
||||
return this.Channel.PingAsync(request);
|
||||
}
|
||||
|
||||
public Task OpenAsync()
|
||||
{
|
||||
ICommunicationObject communicationObject = this;
|
||||
return Task.Factory.FromAsync(communicationObject.BeginOpen, communicationObject.EndOpen, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.ServiceModel.Http" VersionOverride="$(LibraryVersion)" />
|
||||
<PackageReference Include="System.ServiceModel.NetTcp" VersionOverride="$(LibraryVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -22,14 +22,6 @@ namespace TestApplication.Wcf.Client.NetFramework;
|
|||
[ServiceContract(Namespace = "http://opentelemetry.io/", Name = "StatusService", SessionMode = SessionMode.Allowed)]
|
||||
public interface IStatusServiceContract
|
||||
{
|
||||
[OperationContract(Name = "Ping")]
|
||||
[OperationContract]
|
||||
Task<StatusResponse> PingAsync(StatusRequest request);
|
||||
|
||||
[OperationContract(Name = "Ping")]
|
||||
StatusResponse PingSync(StatusRequest request);
|
||||
|
||||
[OperationContract(Name = "Ping", AsyncPattern = true)]
|
||||
IAsyncResult BeginPing(StatusRequest request, AsyncCallback callback, object asyncState);
|
||||
|
||||
StatusResponse EndPing(IAsyncResult asyncResult);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,35 +91,6 @@ internal static class Program
|
|||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Asynchronous Programming Model pattern call");
|
||||
var rq = new StatusRequest { Status = "2" };
|
||||
var asyncResult = client.BeginPing(rq, null!, null!);
|
||||
var statusResponse = client.EndPing(asyncResult);
|
||||
|
||||
Console.WriteLine(
|
||||
$"[{DateTimeOffset.UtcNow:o}] Request with status {rq.Status}. Server returned: {statusResponse?.ServerTime:o}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Synchronous call");
|
||||
var rq = new StatusRequest { Status = "3" };
|
||||
var response = client.PingSync(rq);
|
||||
|
||||
Console.WriteLine(
|
||||
$"[{DateTimeOffset.UtcNow:o}] Request with status {rq.Status}. Server returned: {response?.ServerTime:o}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,21 +32,6 @@ public class StatusServiceClient : ClientBase<IStatusServiceContract>, IStatusSe
|
|||
return this.Channel.PingAsync(request);
|
||||
}
|
||||
|
||||
public StatusResponse PingSync(StatusRequest request)
|
||||
{
|
||||
return Channel.PingSync(request);
|
||||
}
|
||||
|
||||
public IAsyncResult BeginPing(StatusRequest request, AsyncCallback callback, object asyncState)
|
||||
{
|
||||
return Channel.BeginPing(request, callback, asyncState);
|
||||
}
|
||||
|
||||
public StatusResponse EndPing(IAsyncResult asyncResult)
|
||||
{
|
||||
return Channel.EndPing(asyncResult);
|
||||
}
|
||||
|
||||
public Task OpenAsync()
|
||||
{
|
||||
ICommunicationObject communicationObject = this;
|
||||
|
|
|
|||
|
|
@ -192,6 +192,17 @@ internal static class PackageVersionDefinitions
|
|||
new("2.6.66"),
|
||||
new("*")
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
IntegrationName = "WCFCoreClient",
|
||||
NugetPackageName = "System.ServiceModel.Http",
|
||||
TestApplicationName = "TestApplication.Wcf.Client.DotNet",
|
||||
Versions = new List<PackageVersion>
|
||||
{
|
||||
new("4.10.2"),
|
||||
new("*")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue