Skip to content

Commit c50d70e

Browse files
Add new instrumentation for System.ServiceModel.Dispatcher.SyncMethodInvoker and update snapshots
1 parent e75fdd2 commit c50d70e

5 files changed

+305
-3
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// <copyright file="SyncMethodInvokerIntegration.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
#if NETFRAMEWORK
7+
using System;
8+
using System.ComponentModel;
9+
using System.Reflection;
10+
using Datadog.Trace.ClrProfiler.CallTarget;
11+
using Datadog.Trace.ClrProfiler.Emit;
12+
using Datadog.Trace.ClrProfiler.Integrations;
13+
using Datadog.Trace.Configuration;
14+
15+
namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Wcf
16+
{
17+
/// <summary>
18+
/// System.ServiceModel.Dispatcher.SyncMethodInvoker calltarget instrumentation
19+
/// </summary>
20+
[InstrumentMethod(
21+
AssemblyName = "System.ServiceModel",
22+
TypeName = "System.ServiceModel.Dispatcher.SyncMethodInvoker",
23+
MethodName = "Invoke",
24+
ReturnTypeName = ClrNames.Object,
25+
ParameterTypeNames = new[] { ClrNames.Object, "System.Object[]", "System.Object[]&" },
26+
TargetMethodArgumentsToLoad = new ushort[] { 0, 1 }, // DO NOT pass the "out object[]" parameter into the instrumentation method
27+
MinimumVersion = "4.0.0",
28+
MaximumVersion = "4.*.*",
29+
IntegrationName = IntegrationName)]
30+
[Browsable(false)]
31+
[EditorBrowsable(EditorBrowsableState.Never)]
32+
public class SyncMethodInvokerIntegration
33+
{
34+
private const string IntegrationName = nameof(IntegrationIds.Wcf);
35+
private static readonly Func<object> _getCurrentOperationContext;
36+
37+
static SyncMethodInvokerIntegration()
38+
{
39+
var operationContextType = Type.GetType("System.ServiceModel.OperationContext, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", throwOnError: false);
40+
if (operationContextType is not null)
41+
{
42+
var property = operationContextType.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
43+
var method = property.GetGetMethod();
44+
_getCurrentOperationContext = (Func<object>)method.CreateDelegate(typeof(Func<object>));
45+
}
46+
}
47+
48+
/// <summary>
49+
/// OnMethodBegin callback
50+
/// </summary>
51+
/// <typeparam name="TTarget">Type of the target</typeparam>
52+
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
53+
/// <param name="instanceArg">RequestContext instance</param>
54+
/// <param name="inputs">Input arguments</param>
55+
/// <returns>Calltarget state value</returns>
56+
public static CallTargetState OnMethodBegin<TTarget>(TTarget instance, object instanceArg, object[] inputs)
57+
{
58+
// TODO Just use the OperationContext.Current object to get the span information
59+
// context.IncomingMessageHeaders contains:
60+
// - Action
61+
// - To
62+
//
63+
// context.IncomingMessageProperties contains:
64+
// - ["httpRequest"] key to find distributed tracing headers
65+
if (_getCurrentOperationContext is null || !Tracer.Instance.Settings.WcfEnableNewInstrumentation)
66+
{
67+
return CallTargetState.GetDefault();
68+
}
69+
70+
var requestContext = _getCurrentOperationContext()?.GetProperty<object>("RequestContext").GetValueOrDefault();
71+
return new CallTargetState(WcfIntegration.CreateScope(requestContext));
72+
}
73+
74+
/// <summary>
75+
/// OnMethodEnd callback
76+
/// </summary>
77+
/// <typeparam name="TTarget">Type of the target</typeparam>
78+
/// <typeparam name="TReturn">Type of the response</typeparam>
79+
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
80+
/// <param name="returnValue">Return value</param>
81+
/// <param name="exception">Exception instance in case the original code threw an exception.</param>
82+
/// <param name="state">Calltarget state value</param>
83+
/// <returns>A response value, in an async scenario will be T of Task of T</returns>
84+
public static CallTargetReturn<TReturn> OnMethodEnd<TTarget, TReturn>(TTarget instance, TReturn returnValue, Exception exception, CallTargetState state)
85+
{
86+
state.Scope.DisposeWithException(exception);
87+
return new CallTargetReturn<TReturn>(returnValue);
88+
}
89+
}
90+
}
91+
#endif

tracer/src/Datadog.Trace/ClrProfiler/InstrumentationDefinitions.Generated.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ private static NativeCallTargetDefinition[] GetDefinitionsArray()
267267

268268
// Wcf
269269
new("System.ServiceModel", "System.ServiceModel.Dispatcher.ChannelHandler", "HandleRequest", new[] { "System.Boolean", "System.ServiceModel.Channels.RequestContext", "System.ServiceModel.OperationContext" }, new ushort[] { }, 4, 0, 0, 4, 65535, 65535, assemblyFullName, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Wcf.ChannelHandlerIntegration"),
270+
new("System.ServiceModel", "System.ServiceModel.Dispatcher.SyncMethodInvoker", "Invoke", new[] { "System.Object", "System.Object", "System.Object[]", "System.Object[]&" }, new ushort[] { 0, 1 }, 4, 0, 0, 4, 65535, 65535, assemblyFullName, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Wcf.SyncMethodInvokerIntegration"),
270271

271272
// WebRequest
272273
new("System", "System.Net.HttpWebRequest", "BeginGetRequestStream", new[] { "System.IAsyncResult", "System.AsyncCallback", "System.Object" }, new ushort[] { }, 4, 0, 0, 4, 65535, 65535, assemblyFullName, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Http.WebRequest.HttpWebRequest_BeginGetRequestStream_Integration"),
Original file line numberDiff line numberDiff line change
@@ -1 +1,74 @@
1-
[]
1+
[
2+
{
3+
TraceId: Id_1,
4+
SpanId: Id_2,
5+
Name: wcf.request,
6+
Resource: WcfSample/ICalculator/ServerSyncAdd,
7+
Service: Samples.Wcf,
8+
Type: web,
9+
ParentId: Id_3,
10+
Tags: {
11+
env: integration_tests,
12+
http.method: POST,
13+
http.request.headers.host: localhost:00000,
14+
http.url: http://localhost:00000/WcfSample/CalculatorService,
15+
language: dotnet,
16+
runtime-id: Guid_1,
17+
span.kind: server,
18+
version: 1.0.0
19+
},
20+
Metrics: {
21+
_sampling_priority_v1: 1.0,
22+
_dd.tracer_kr: 1.0,
23+
_dd.top_level: 1.0
24+
}
25+
},
26+
{
27+
TraceId: Id_4,
28+
SpanId: Id_5,
29+
Name: wcf.request,
30+
Resource: WcfSample/ICalculator/ServerSyncAdd,
31+
Service: Samples.Wcf,
32+
Type: web,
33+
ParentId: Id_6,
34+
Tags: {
35+
env: integration_tests,
36+
http.method: POST,
37+
http.request.headers.host: localhost:00000,
38+
http.url: http://localhost:00000/WcfSample/CalculatorService,
39+
language: dotnet,
40+
runtime-id: Guid_1,
41+
span.kind: server,
42+
version: 1.0.0
43+
},
44+
Metrics: {
45+
_sampling_priority_v1: 1.0,
46+
_dd.tracer_kr: 1.0,
47+
_dd.top_level: 1.0
48+
}
49+
},
50+
{
51+
TraceId: Id_7,
52+
SpanId: Id_8,
53+
Name: wcf.request,
54+
Resource: WcfSample/ICalculator/ServerSyncAdd,
55+
Service: Samples.Wcf,
56+
Type: web,
57+
ParentId: Id_9,
58+
Tags: {
59+
env: integration_tests,
60+
http.method: POST,
61+
http.request.headers.host: localhost:00000,
62+
http.url: http://localhost:00000/WcfSample/CalculatorService,
63+
language: dotnet,
64+
runtime-id: Guid_1,
65+
span.kind: server,
66+
version: 1.0.0
67+
},
68+
Metrics: {
69+
_sampling_priority_v1: 1.0,
70+
_dd.tracer_kr: 1.0,
71+
_dd.top_level: 1.0
72+
}
73+
}
74+
]
Original file line numberDiff line numberDiff line change
@@ -1 +1,65 @@
1-
[]
1+
[
2+
{
3+
TraceId: Id_1,
4+
SpanId: Id_2,
5+
Name: wcf.request,
6+
Resource: WcfSample/ICalculator/ServerSyncAdd,
7+
Service: Samples.Wcf,
8+
Type: web,
9+
Tags: {
10+
env: integration_tests,
11+
http.url: net.tcp://localhost:00000/WcfSample/CalculatorService,
12+
language: dotnet,
13+
runtime-id: Guid_1,
14+
span.kind: server,
15+
version: 1.0.0
16+
},
17+
Metrics: {
18+
_sampling_priority_v1: 1.0,
19+
_dd.tracer_kr: 1.0,
20+
_dd.top_level: 1.0
21+
}
22+
},
23+
{
24+
TraceId: Id_3,
25+
SpanId: Id_4,
26+
Name: wcf.request,
27+
Resource: WcfSample/ICalculator/ServerSyncAdd,
28+
Service: Samples.Wcf,
29+
Type: web,
30+
Tags: {
31+
env: integration_tests,
32+
http.url: net.tcp://localhost:00000/WcfSample/CalculatorService,
33+
language: dotnet,
34+
runtime-id: Guid_1,
35+
span.kind: server,
36+
version: 1.0.0
37+
},
38+
Metrics: {
39+
_sampling_priority_v1: 1.0,
40+
_dd.tracer_kr: 1.0,
41+
_dd.top_level: 1.0
42+
}
43+
},
44+
{
45+
TraceId: Id_5,
46+
SpanId: Id_6,
47+
Name: wcf.request,
48+
Resource: WcfSample/ICalculator/ServerSyncAdd,
49+
Service: Samples.Wcf,
50+
Type: web,
51+
Tags: {
52+
env: integration_tests,
53+
http.url: net.tcp://localhost:00000/WcfSample/CalculatorService,
54+
language: dotnet,
55+
runtime-id: Guid_1,
56+
span.kind: server,
57+
version: 1.0.0
58+
},
59+
Metrics: {
60+
_sampling_priority_v1: 1.0,
61+
_dd.tracer_kr: 1.0,
62+
_dd.top_level: 1.0
63+
}
64+
}
65+
]
Original file line numberDiff line numberDiff line change
@@ -1 +1,74 @@
1-
[]
1+
[
2+
{
3+
TraceId: Id_1,
4+
SpanId: Id_2,
5+
Name: wcf.request,
6+
Resource: WcfSample/ICalculator/ServerSyncAdd,
7+
Service: Samples.Wcf,
8+
Type: web,
9+
ParentId: Id_3,
10+
Tags: {
11+
env: integration_tests,
12+
http.method: POST,
13+
http.request.headers.host: localhost:00000,
14+
http.url: http://localhost:00000/WcfSample/CalculatorService,
15+
language: dotnet,
16+
runtime-id: Guid_1,
17+
span.kind: server,
18+
version: 1.0.0
19+
},
20+
Metrics: {
21+
_sampling_priority_v1: 1.0,
22+
_dd.tracer_kr: 1.0,
23+
_dd.top_level: 1.0
24+
}
25+
},
26+
{
27+
TraceId: Id_4,
28+
SpanId: Id_5,
29+
Name: wcf.request,
30+
Resource: WcfSample/ICalculator/ServerSyncAdd,
31+
Service: Samples.Wcf,
32+
Type: web,
33+
ParentId: Id_6,
34+
Tags: {
35+
env: integration_tests,
36+
http.method: POST,
37+
http.request.headers.host: localhost:00000,
38+
http.url: http://localhost:00000/WcfSample/CalculatorService,
39+
language: dotnet,
40+
runtime-id: Guid_1,
41+
span.kind: server,
42+
version: 1.0.0
43+
},
44+
Metrics: {
45+
_sampling_priority_v1: 1.0,
46+
_dd.tracer_kr: 1.0,
47+
_dd.top_level: 1.0
48+
}
49+
},
50+
{
51+
TraceId: Id_7,
52+
SpanId: Id_8,
53+
Name: wcf.request,
54+
Resource: WcfSample/ICalculator/ServerSyncAdd,
55+
Service: Samples.Wcf,
56+
Type: web,
57+
ParentId: Id_9,
58+
Tags: {
59+
env: integration_tests,
60+
http.method: POST,
61+
http.request.headers.host: localhost:00000,
62+
http.url: http://localhost:00000/WcfSample/CalculatorService,
63+
language: dotnet,
64+
runtime-id: Guid_1,
65+
span.kind: server,
66+
version: 1.0.0
67+
},
68+
Metrics: {
69+
_sampling_priority_v1: 1.0,
70+
_dd.tracer_kr: 1.0,
71+
_dd.top_level: 1.0
72+
}
73+
}
74+
]

0 commit comments

Comments
 (0)