migrate more integrations to newer MethodBuilder (#494)

* use MethodBuilder in AspNetMvcIntegration

* use MethodBuilder in AspNetWebApi2Integration

* use MethodBuilder in WcfIntegration

* add object.GetInstrumentedInterface() extension method

* replace uses of WithConcreteTypeName() to WithConcreteType()

* replace more uses of WithConcreteTypeName() to WithConcreteType()

* remove unused MethodBuilder.WithConcreteTypeName()

* clean up code

* rename fields for clarity

* add more type name constants

* stop using "dynamic" keyword

* use object.GetInstrumentedType()

* remove unused static Type fields

* use object.GetInstrumentedType()

* add more type name constants, remove unused static Type fields

* stop using "dynamic" keyword

* use GetInstrumentedInterface() instead of GetInstrumentedType()
This commit is contained in:
Lucas Pimentel-Ordyna 2019-08-30 10:03:09 -04:00 committed by GitHub
parent 2b458b0315
commit b735a4bd38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 196 additions and 107 deletions

View File

@ -81,12 +81,6 @@ namespace Datadog.Trace.ClrProfiler.Emit
return this;
}
public MethodBuilder<TDelegate> WithConcreteTypeName(string typeName)
{
var concreteType = _resolutionModule?.GetType(typeName);
return this.WithConcreteType(concreteType);
}
public MethodBuilder<TDelegate> WithNamespaceAndNameFilters(params string[] namespaceNameFilters)
{
_namespaceAndNameFilter = namespaceNameFilters;

View File

@ -22,13 +22,15 @@ namespace Datadog.Trace.ClrProfiler.Integrations
/// <summary>
/// Type for unobtrusive hooking into Microsoft.AspNetCore.Mvc.Core pipeline.
/// </summary>
private const string DiagnosticSource = "Microsoft.AspNetCore.Mvc.Internal.MvcCoreDiagnosticSourceExtensions";
private const string DiagnosticSourceTypeName = "Microsoft.AspNetCore.Mvc.Internal.MvcCoreDiagnosticSourceExtensions";
/// <summary>
/// Base type used for traversing the pipeline in Microsoft.AspNetCore.Mvc.Core.
/// </summary>
private const string ResourceInvoker = "Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker";
private const string ResourceInvokerTypeName = "Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker";
private static readonly Type DiagnosticSourceType = Type.GetType($"{DiagnosticSourceTypeName}, {AspnetMvcCore}");
private static readonly Type ResourceInvokerType = Type.GetType($"{ResourceInvokerTypeName}, {AspnetMvcCore}");
private static readonly ILog Log = LogProvider.GetLogger(typeof(AspNetCoreMvc2Integration));
private readonly object _httpContext;
@ -47,14 +49,14 @@ namespace Datadog.Trace.ClrProfiler.Integrations
var request = _httpContext.GetProperty("Request").GetValueOrDefault();
GetTagValues(
actionDescriptor,
request,
out string httpMethod,
out string host,
out string resourceName,
out string url,
out string controllerName,
out string actionName);
actionDescriptor,
request,
out string httpMethod,
out string host,
out string resourceName,
out string url,
out string controllerName,
out string actionName);
SpanContext propagatedContext = null;
var tracer = Tracer.Instance;
@ -94,10 +96,10 @@ namespace Datadog.Trace.ClrProfiler.Integrations
var span = _scope.Span;
span.DecorateWebServerSpan(
resourceName: resourceName,
method: httpMethod,
host: host,
httpUrl: url);
resourceName: resourceName,
method: httpMethod,
host: host,
httpUrl: url);
span.SetTag(Tags.AspNetController, controllerName);
span.SetTag(Tags.AspNetAction, actionName);
@ -126,7 +128,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
[InterceptMethod(
CallerAssembly = AspnetMvcCore,
TargetAssembly = AspnetMvcCore,
TargetType = DiagnosticSource,
TargetType = DiagnosticSourceTypeName,
TargetSignatureTypes = new[] { ClrNames.Void, ClrNames.Ignore, "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor", "Microsoft.AspNetCore.Http.HttpContext", "Microsoft.AspNetCore.Routing.RouteData" },
TargetMinimumVersion = Major2,
TargetMaximumVersion = Major2)]
@ -168,7 +170,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
instrumentedMethod =
MethodBuilder<Action<object, object, object, object>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(BeforeAction))
.WithConcreteTypeName(DiagnosticSource)
.WithConcreteType(DiagnosticSourceType)
.WithParameters(diagnosticSource, actionDescriptor, httpContext, routeData)
.WithNamespaceAndNameFilters(
ClrNames.Void,
@ -181,7 +183,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
catch (Exception ex)
{
// profiled app will continue working as expected without this method
Log.ErrorException($"Error resolving {DiagnosticSource}.{nameof(BeforeAction)}(...)", ex);
Log.ErrorException($"Error resolving {DiagnosticSourceTypeName}.{nameof(BeforeAction)}(...)", ex);
}
try
@ -209,7 +211,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
[InterceptMethod(
CallerAssembly = AspnetMvcCore,
TargetAssembly = AspnetMvcCore,
TargetType = DiagnosticSource,
TargetType = DiagnosticSourceTypeName,
TargetSignatureTypes = new[] { ClrNames.Void, ClrNames.Ignore, "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor", "Microsoft.AspNetCore.Http.HttpContext", "Microsoft.AspNetCore.Routing.RouteData" },
TargetMinimumVersion = Major2,
TargetMaximumVersion = Major2)]
@ -244,14 +246,14 @@ namespace Datadog.Trace.ClrProfiler.Integrations
Action<object, object, object, object> instrumentedMethod = null;
string methodDef = $"{DiagnosticSource}.{nameof(AfterAction)}(...)";
string methodDef = $"{DiagnosticSourceTypeName}.{nameof(AfterAction)}(...)";
try
{
instrumentedMethod =
MethodBuilder<Action<object, object, object, object>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(AfterAction))
.WithConcreteTypeName(DiagnosticSource)
.WithConcreteType(DiagnosticSourceType)
.WithParameters(diagnosticSource, actionDescriptor, httpContext, routeData)
.WithNamespaceAndNameFilters(
ClrNames.Void,
@ -294,7 +296,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
[InterceptMethod(
CallerAssembly = AspnetMvcCore,
TargetAssembly = AspnetMvcCore,
TargetType = ResourceInvoker,
TargetType = ResourceInvokerTypeName,
TargetSignatureTypes = new[] { ClrNames.Void, ClrNames.Ignore },
TargetMinimumVersion = Major2,
TargetMaximumVersion = Major2)]
@ -310,14 +312,14 @@ namespace Datadog.Trace.ClrProfiler.Integrations
var shouldTrace = Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName);
Action<object> instrumentedMethod = null;
Action<object> instrumentedMethod;
try
{
instrumentedMethod =
MethodBuilder<Action<object>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(Rethrow))
.WithConcreteTypeName(ResourceInvoker)
.WithConcreteType(ResourceInvokerType)
.WithParameters(context)
.WithNamespaceAndNameFilters(ClrNames.Void, ClrNames.Ignore)
.Build();
@ -325,8 +327,8 @@ namespace Datadog.Trace.ClrProfiler.Integrations
catch (Exception ex)
{
// profiled app will not continue working as expected without this method
var contextTypeName = (context == null) ? string.Empty : (context.GetType().FullName + " ");
var methodDef = $"{ResourceInvoker}.{nameof(Rethrow)}({contextTypeName}context)";
var contextTypeName = context.GetType().FullName + " ";
var methodDef = $"{ResourceInvokerTypeName}.{nameof(Rethrow)}({contextTypeName} context)";
Log.ErrorException($"Error retrieving {methodDef}", ex);
throw;
}
@ -394,14 +396,14 @@ namespace Datadog.Trace.ClrProfiler.Integrations
}
private static void GetTagValues(
object actionDescriptor,
object request,
out string httpMethod,
out string host,
out string resourceName,
out string url,
out string controllerName,
out string actionName)
object actionDescriptor,
object request,
out string httpMethod,
out string host,
out string resourceName,
out string url,
out string controllerName,
out string actionName)
{
controllerName = actionDescriptor.GetProperty<string>("ControllerName").GetValueOrDefault()?.ToLowerInvariant();
@ -420,7 +422,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
url = $"{pathBase}{path}{queryString}";
string resourceUrl = actionDescriptor.GetProperty("AttributeRouteInfo").GetProperty<string>("Template").GetValueOrDefault() ??
UriHelpers.GetRelativeUrl(new Uri($"https://{host}{url}"), tryRemoveIds: true).ToLowerInvariant();
UriHelpers.GetRelativeUrl(new Uri($"https://{host}{url}"), tryRemoveIds: true).ToLowerInvariant();
resourceName = $"{httpMethod} {resourceUrl}";
}

View File

@ -23,11 +23,11 @@ namespace Datadog.Trace.ClrProfiler.Integrations
private const string Major5Minor1 = "5.1";
private const string Major5 = "5";
private const string AssemblyName = "System.Web.Mvc";
private const string AsyncActionInvokerTypeName = "System.Web.Mvc.Async.IAsyncActionInvoker";
private static readonly Type ControllerContextType = Type.GetType($"System.Web.Mvc.ControllerContext, {AssemblyName}", throwOnError: false);
private static readonly Type RouteCollectionRouteType = Type.GetType($"System.Web.Mvc.Routing.RouteCollectionRoute, {AssemblyName}", throwOnError: false);
private static readonly Type AsyncActionInvokerType = Type.GetType($"{AsyncActionInvokerTypeName}, {AssemblyName}", throwOnError: false);
private const string AsyncActionInvokerTypeName = "System.Web.Mvc.Async.IAsyncActionInvoker";
private const string ControllerContextTypeName = "System.Web.Mvc.ControllerContext";
private const string RouteCollectionRouteTypeName = "System.Web.Mvc.Routing.RouteCollectionRoute";
private static readonly ILog Log = LogProvider.GetLogger(typeof(AspNetMvcIntegration));
/// <summary>
@ -35,16 +35,8 @@ namespace Datadog.Trace.ClrProfiler.Integrations
/// </summary>
/// <param name="controllerContext">The System.Web.Mvc.ControllerContext that was passed as an argument to the instrumented method.</param>
/// <returns>A new scope used to instrument an MVC action.</returns>
public static Scope CreateScope(dynamic controllerContext)
public static Scope CreateScope(object controllerContext)
{
if (ControllerContextType == null ||
controllerContext == null ||
((object)controllerContext)?.GetType() != ControllerContextType)
{
// bail out early
return null;
}
Scope scope = null;
try
@ -55,7 +47,12 @@ namespace Datadog.Trace.ClrProfiler.Integrations
return null;
}
var httpContext = controllerContext?.HttpContext as HttpContextBase;
if (controllerContext == null || controllerContext.GetType().FullName != ControllerContextTypeName)
{
return null;
}
var httpContext = controllerContext.GetProperty<HttpContextBase>("HttpContext").GetValueOrDefault();
if (httpContext == null)
{
@ -67,11 +64,11 @@ namespace Datadog.Trace.ClrProfiler.Integrations
string url = httpContext.Request.RawUrl.ToLowerInvariant();
string resourceName = null;
RouteData routeData = controllerContext.RouteData as RouteData;
RouteData routeData = controllerContext.GetProperty<RouteData>("RouteData").GetValueOrDefault();
Route route = routeData?.Route as Route;
RouteValueDictionary routeValues = routeData?.Values;
if (route == null && routeData?.Route.GetType() == RouteCollectionRouteType)
if (route == null && routeData?.Route.GetType().FullName == RouteCollectionRouteTypeName)
{
var routeMatches = routeValues?.GetValueOrDefault("MS_DirectRouteMatches") as List<RouteData>;
@ -173,7 +170,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
CallerAssembly = AssemblyName,
TargetAssembly = AssemblyName,
TargetType = AsyncActionInvokerTypeName,
TargetSignatureTypes = new[] { ClrNames.IAsyncResult, "System.Web.Mvc.ControllerContext", ClrNames.String, ClrNames.AsyncCallback, ClrNames.Object },
TargetSignatureTypes = new[] { ClrNames.IAsyncResult, ControllerContextTypeName, ClrNames.String, ClrNames.AsyncCallback, ClrNames.Object },
TargetMinimumVersion = Major5Minor1,
TargetMaximumVersion = Major5)]
public static object BeginInvokeAction(
@ -201,20 +198,38 @@ namespace Datadog.Trace.ClrProfiler.Integrations
Log.ErrorException("Error instrumenting method {0}", ex, "System.Web.Mvc.Async.IAsyncActionInvoker.BeginInvokeAction()");
}
var beginInvokeAction = Emit.DynamicMethodBuilder<Func<object, object, object, object, object, object>>
.GetOrCreateMethodCallDelegate(
AsyncActionInvokerType,
"BeginInvokeAction",
(OpCodeValue)opCode);
Func<object, object, object, object, object, object> instrumentedMethod;
try
{
var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName);
instrumentedMethod = MethodBuilder<Func<object, object, object, object, object, object>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(BeginInvokeAction))
.WithConcreteType(asyncActionInvokerType)
.WithParameters(controllerContext, actionName, callback, state)
.WithNamespaceAndNameFilters(
ClrNames.IAsyncResult,
"System.Web.Mvc.ControllerContext",
ClrNames.String,
ClrNames.AsyncCallback,
ClrNames.Object)
.Build();
}
catch (Exception ex)
{
Log.ErrorException($"Error resolving {AsyncActionInvokerTypeName}.{nameof(BeginInvokeAction)}(...)", ex);
throw;
}
try
{
// call the original method, inspecting (but not catching) any unhandled exceptions
return beginInvokeAction(asyncControllerActionInvoker, controllerContext, actionName, callback, state);
return instrumentedMethod(asyncControllerActionInvoker, controllerContext, actionName, callback, state);
}
catch (Exception ex) when (scope?.Span.SetExceptionForFilter(ex) ?? false)
catch (Exception ex)
{
// unreachable code
scope?.Span.SetException(ex);
throw;
}
}
@ -254,20 +269,33 @@ namespace Datadog.Trace.ClrProfiler.Integrations
Log.ErrorException("Error instrumenting method {0}", ex, $"{AsyncActionInvokerTypeName}.EndInvokeAction()");
}
var endInvokeAction = Emit.DynamicMethodBuilder<Func<object, object, bool>>
.GetOrCreateMethodCallDelegate(
AsyncActionInvokerType,
"EndInvokeAction",
(OpCodeValue)opCode);
Func<object, object, bool> instrumentedMethod;
try
{
var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName);
instrumentedMethod = MethodBuilder<Func<object, object, bool>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(EndInvokeAction))
.WithConcreteType(asyncActionInvokerType)
.WithParameters(asyncResult)
.WithNamespaceAndNameFilters(ClrNames.Bool, ClrNames.IAsyncResult)
.Build();
}
catch (Exception ex)
{
Log.ErrorException($"Error resolving {AsyncActionInvokerTypeName}.{nameof(EndInvokeAction)}(...)", ex);
throw;
}
try
{
// call the original method, inspecting (but not catching) any unhandled exceptions
return endInvokeAction(asyncControllerActionInvoker, asyncResult);
return instrumentedMethod(asyncControllerActionInvoker, asyncResult);
}
catch (Exception ex) when (scope?.Span.SetExceptionForFilter(ex) ?? false)
catch (Exception ex)
{
// unreachable code
scope?.Span.SetException(ex);
throw;
}
finally

View File

@ -13,7 +13,7 @@ using Datadog.Trace.Logging;
namespace Datadog.Trace.ClrProfiler.Integrations
{
/// <summary>
/// AspNetWeb5Integration wraps the Web API.
/// Contains instrumentation wrappers for ASP.NET Web API 5.
/// </summary>
public static class AspNetWebApi2Integration
{
@ -22,6 +22,10 @@ namespace Datadog.Trace.ClrProfiler.Integrations
private const string Major5Minor2 = "5.2";
private const string Major5 = "5";
private const string SystemWebHttpAssemblyName = "System.Web.Http";
private const string HttpControllerTypeName = "System.Web.Http.Controllers.IHttpController";
private const string HttpControllerContextTypeName = "System.Web.Http.Controllers.HttpControllerContext";
private static readonly ILog Log = LogProvider.GetLogger(typeof(AspNetWebApi2Integration));
/// <summary>
@ -35,9 +39,9 @@ namespace Datadog.Trace.ClrProfiler.Integrations
/// <param name="moduleVersionPtr">A pointer to the module version GUID.</param>
/// <returns>A task with the result</returns>
[InterceptMethod(
TargetAssembly = "System.Web.Http",
TargetType = "System.Web.Http.Controllers.IHttpController",
TargetSignatureTypes = new[] { ClrNames.HttpResponseMessageTask, "System.Web.Http.Controllers.HttpControllerContext", ClrNames.CancellationToken },
TargetAssembly = SystemWebHttpAssemblyName,
TargetType = HttpControllerTypeName,
TargetSignatureTypes = new[] { ClrNames.HttpResponseMessageTask, HttpControllerContextTypeName, ClrNames.CancellationToken },
TargetMinimumVersion = Major5Minor2,
TargetMaximumVersion = Major5)]
public static object ExecuteAsync(
@ -52,8 +56,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
var tokenSource = cancellationTokenSource as CancellationTokenSource;
var cancellationToken = tokenSource?.Token ?? CancellationToken.None;
var callOpCode = (OpCodeValue)opCode;
return ExecuteAsyncInternal(apiController, controllerContext, cancellationToken, callOpCode);
return ExecuteAsyncInternal(apiController, controllerContext, cancellationToken, opCode, mdToken, moduleVersionPtr);
}
/// <summary>
@ -62,26 +65,46 @@ namespace Datadog.Trace.ClrProfiler.Integrations
/// <param name="apiController">The Api Controller</param>
/// <param name="controllerContext">The controller context for the call</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <param name="callOpCode">The <see cref="OpCodeValue"/> used in the original method call.</param>
/// <param name="opCode">The OpCode used in the original method call.</param>
/// <param name="mdToken">The mdToken of the original method call.</param>
/// <param name="moduleVersionPtr">A pointer to the module version GUID.</param>
/// <returns>A task with the result</returns>
private static async Task<HttpResponseMessage> ExecuteAsyncInternal(object apiController, object controllerContext, CancellationToken cancellationToken, OpCodeValue callOpCode)
private static async Task<HttpResponseMessage> ExecuteAsyncInternal(
object apiController,
object controllerContext,
CancellationToken cancellationToken,
int opCode,
int mdToken,
long moduleVersionPtr)
{
Type controllerType = apiController.GetType();
Func<object, object, CancellationToken, Task<HttpResponseMessage>> instrumentedMethod;
// in some cases, ExecuteAsync() is an explicit interface implementation,
// which is not public and has a different name, so try both
var executeAsyncFunc =
Emit.DynamicMethodBuilder<Func<object, object, CancellationToken, Task<HttpResponseMessage>>>
.GetOrCreateMethodCallDelegate(controllerType, "ExecuteAsync", callOpCode) ??
Emit.DynamicMethodBuilder<Func<object, object, CancellationToken, Task<HttpResponseMessage>>>
.GetOrCreateMethodCallDelegate(controllerType, "System.Web.Http.Controllers.IHttpController.ExecuteAsync", callOpCode);
try
{
var httpControllerType = apiController.GetInstrumentedInterface(HttpControllerTypeName);
instrumentedMethod = MethodBuilder<Func<object, object, CancellationToken, Task<HttpResponseMessage>>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(ExecuteAsync))
.WithConcreteType(httpControllerType)
.WithParameters(controllerContext, cancellationToken)
.WithNamespaceAndNameFilters(
ClrNames.HttpResponseMessageTask,
HttpControllerContextTypeName,
ClrNames.CancellationToken)
.Build();
}
catch (Exception ex)
{
Log.ErrorException($"Error resolving {HttpControllerTypeName}.{nameof(ExecuteAsync)}(...)", ex);
throw;
}
using (Scope scope = CreateScope(controllerContext))
{
try
{
// call the original method, inspecting (but not catching) any unhandled exceptions
var responseMessage = await executeAsyncFunc(apiController, controllerContext, cancellationToken).ConfigureAwait(false);
var responseMessage = await instrumentedMethod(apiController, controllerContext, cancellationToken).ConfigureAwait(false);
if (scope != null)
{
@ -91,15 +114,15 @@ namespace Datadog.Trace.ClrProfiler.Integrations
return responseMessage;
}
catch (Exception ex) when (scope?.Span.SetExceptionForFilter(ex) ?? false)
catch (Exception ex)
{
// unreachable code
scope?.Span.SetException(ex);
throw;
}
}
}
private static Scope CreateScope(dynamic controllerContext)
private static Scope CreateScope(object controllerContext)
{
Scope scope = null;
@ -112,7 +135,7 @@ namespace Datadog.Trace.ClrProfiler.Integrations
}
var tracer = Tracer.Instance;
var request = controllerContext?.Request as HttpRequestMessage;
var request = controllerContext.GetProperty<HttpRequestMessage>("Request").GetValueOrDefault();
SpanContext propagatedContext = null;
if (request != null && tracer.ActiveScope == null)

View File

@ -25,5 +25,28 @@ namespace Datadog.Trace.ClrProfiler
return null;
}
public static System.Type GetInstrumentedInterface(
this object runtimeObject,
string instrumentedInterfaceName)
{
if (runtimeObject == null)
{
return null;
}
var currentType = runtimeObject.GetType();
var interfaces = currentType.GetInterfaces();
foreach (var interfaceType in interfaces)
{
if ($"{interfaceType.Namespace}.{interfaceType.Name}" == instrumentedInterfaceName)
{
return interfaceType;
}
}
return null;
}
}
}

View File

@ -1,10 +1,10 @@
#if !NETSTANDARD2_0
using System;
using System.ServiceModel.Channels;
using Datadog.Trace.ClrProfiler.Emit;
using Datadog.Trace.ClrProfiler.ExtensionMethods;
using Datadog.Trace.ClrProfiler.Models;
using Datadog.Trace.Logging;
namespace Datadog.Trace.ClrProfiler.Integrations
{
@ -16,10 +16,14 @@ namespace Datadog.Trace.ClrProfiler.Integrations
private const string IntegrationName = "Wcf";
private const string Major4 = "4";
private const string ChannelHandlerTypeName = "System.ServiceModel.Dispatcher.ChannelHandler";
private static readonly ILog Log = LogProvider.GetLogger(typeof(WcfIntegration));
/// <summary>
/// Instrumentation wrapper for System.ServiceModel.Dispatcher.ChannelHandler
/// </summary>
/// <param name="thisObj">The ChannelHandler instance.</param>
/// <param name="channelHandler">The ChannelHandler instance.</param>
/// <param name="requestContext">A System.ServiceModel.Channels.RequestContext implementation instance.</param>
/// <param name="currentOperationContext">A System.ServiceModel.OperationContext instance.</param>
/// <param name="opCode">The OpCode used in the original method call.</param>
@ -28,39 +32,54 @@ namespace Datadog.Trace.ClrProfiler.Integrations
/// <returns>The value returned by the instrumented method.</returns>
[InterceptMethod(
TargetAssembly = "System.ServiceModel",
TargetType = "System.ServiceModel.Dispatcher.ChannelHandler",
TargetType = ChannelHandlerTypeName,
TargetSignatureTypes = new[] { ClrNames.Bool, "System.ServiceModel.Channels.RequestContext", "System.ServiceModel.OperationContext" },
TargetMinimumVersion = Major4,
TargetMaximumVersion = Major4)]
public static bool HandleRequest(
object thisObj,
object channelHandler,
object requestContext,
object currentOperationContext,
int opCode,
int mdToken,
long moduleVersionPtr)
{
var handleRequestDelegate = Emit.DynamicMethodBuilder<Func<object, object, object, bool>>
.GetOrCreateMethodCallDelegate(
thisObj.GetType(),
"HandleRequest",
(OpCodeValue)opCode);
Func<object, object, object, bool> instrumentedMethod;
var declaringType = channelHandler.GetInstrumentedType(ChannelHandlerTypeName);
try
{
instrumentedMethod = MethodBuilder<Func<object, object, object, bool>>
.Start(moduleVersionPtr, mdToken, opCode, nameof(HandleRequest))
.WithConcreteType(declaringType)
.WithParameters(requestContext, currentOperationContext)
.WithNamespaceAndNameFilters(
ClrNames.Bool,
"System.ServiceModel.Channels.RequestContext",
"System.ServiceModel.OperationContext")
.Build();
}
catch (Exception ex)
{
Log.ErrorException($"Error resolving {ChannelHandlerTypeName}.{nameof(HandleRequest)}(...)", ex);
throw;
}
if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName) ||
!(requestContext is RequestContext castRequestContext))
{
return handleRequestDelegate(thisObj, requestContext, currentOperationContext);
return instrumentedMethod(channelHandler, requestContext, currentOperationContext);
}
using (var wcfDelegate = WcfRequestMessageSpanIntegrationDelegate.CreateAndBegin(castRequestContext))
{
try
{
return handleRequestDelegate(thisObj, requestContext, currentOperationContext);
return instrumentedMethod(channelHandler, requestContext, currentOperationContext);
}
catch (Exception ex) when (wcfDelegate?.SetExceptionForFilter(ex) ?? false)
catch (Exception ex)
{
// unreachable code
wcfDelegate?.SetExceptionForFilter(ex);
throw;
}
}