Skip to content

Commit f6fd6f8

Browse files
authored
[Dynamic Instrumentation] Display interface properties in snapshot (#3761)
* Display interface properties in snapshot * Fix PR's comments * Add AsyncInterfaceProperties to exclude from unoptimize test
1 parent 99befb1 commit f6fd6f8

File tree

14 files changed

+669
-21
lines changed

14 files changed

+669
-21
lines changed

tracer/src/Datadog.Trace/Debugger/Expressions/ProbeProcessor.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,8 @@ private void AddAsyncMethodArguments<T>(DebuggerSnapshotCreator snapshotCreator,
271271
continue;
272272
}
273273

274-
snapshotCreator.AddScopeMember(arg.Name, arg.FieldType, arg.GetValue(asyncCaptureInfo.MoveNextInvocationTarget), ScopeMemberKind.Argument);
274+
var argValue = arg.GetValue(asyncCaptureInfo.MoveNextInvocationTarget);
275+
snapshotCreator.AddScopeMember(arg.Name, argValue?.GetType() ?? arg.FieldType, argValue, ScopeMemberKind.Argument);
275276
}
276277
}
277278

@@ -286,7 +287,8 @@ private void AddAsyncMethodLocals<T>(DebuggerSnapshotCreator snapshotCreator, re
286287
continue;
287288
}
288289

289-
snapshotCreator.AddScopeMember(local.SanitizedName, local.Field.FieldType, local.Field.GetValue(asyncCaptureInfo.MoveNextInvocationTarget), ScopeMemberKind.Local);
290+
var localValue = local.Field.GetValue(asyncCaptureInfo.MoveNextInvocationTarget);
291+
snapshotCreator.AddScopeMember(local.SanitizedName, localValue?.GetType() ?? local.Field.FieldType, localValue, ScopeMemberKind.Local);
290292
}
291293
}
292294

tracer/src/Datadog.Trace/Debugger/Instrumentation/AsyncLineDebuggerInvoker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static void LogLocal<TLocal>(ref TLocal local, int index, ref AsyncLineDe
5353
return;
5454
}
5555

56-
var captureInfo = new CaptureInfo<TLocal>(value: local, type: typeof(TLocal), methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
56+
var captureInfo = new CaptureInfo<TLocal>(value: local, methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
5757

5858
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
5959
{

tracer/src/Datadog.Trace/Debugger/Instrumentation/AsyncMethodDebuggerInvoker.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public static void LogLocal<TLocal>(ref TLocal local, int index, ref AsyncMethod
163163
return;
164164
}
165165

166-
var captureInfo = new CaptureInfo<TLocal>(value: local, type: typeof(TLocal), methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
166+
var captureInfo = new CaptureInfo<TLocal>(value: local, methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
167167
if (!asyncState.ProbeData.Processor.Process(ref captureInfo, asyncState.SnapshotCreator))
168168
{
169169
asyncState.IsActive = false;
@@ -192,7 +192,7 @@ public static DebuggerReturn EndMethod_StartMarker<TTarget>(TTarget instance, Ex
192192
}
193193

194194
var asyncCaptureInfo = new AsyncCaptureInfo(asyncState.MoveNextInvocationTarget, asyncState.KickoffInvocationTarget, asyncState.MethodMetadataInfo.KickoffInvocationTargetType, hoistedLocals: asyncState.MethodMetadataInfo.AsyncMethodHoistedLocals, hoistedArgs: asyncState.MethodMetadataInfo.AsyncMethodHoistedArguments);
195-
var capture = new CaptureInfo<Exception>(value: exception, methodState: MethodState.ExitStartAsync, type: exception?.GetType(), asyncCaptureInfo: asyncCaptureInfo, memberKind: ScopeMemberKind.Exception);
195+
var capture = new CaptureInfo<Exception>(value: exception, methodState: MethodState.ExitStartAsync, asyncCaptureInfo: asyncCaptureInfo, memberKind: ScopeMemberKind.Exception);
196196

197197
if (!asyncState.ProbeData.Processor.Process(ref capture, asyncState.SnapshotCreator))
198198
{
@@ -226,15 +226,15 @@ public static DebuggerReturn<TReturn> EndMethod_StartMarker<TTarget, TReturn>(TT
226226
var asyncCaptureInfo = new AsyncCaptureInfo(asyncState.MoveNextInvocationTarget, asyncState.KickoffInvocationTarget, asyncState.MethodMetadataInfo.KickoffInvocationTargetType, hoistedLocals: asyncState.MethodMetadataInfo.AsyncMethodHoistedLocals, hoistedArgs: asyncState.MethodMetadataInfo.AsyncMethodHoistedArguments);
227227
if (exception != null)
228228
{
229-
var captureInfo = new CaptureInfo<Exception>(value: exception, type: exception.GetType(), methodState: MethodState.ExitStartAsync, memberKind: ScopeMemberKind.Exception, asyncCaptureInfo: asyncCaptureInfo);
229+
var captureInfo = new CaptureInfo<Exception>(value: exception, methodState: MethodState.ExitStartAsync, memberKind: ScopeMemberKind.Exception, asyncCaptureInfo: asyncCaptureInfo);
230230
if (!asyncState.ProbeData.Processor.Process(ref captureInfo, asyncState.SnapshotCreator))
231231
{
232232
asyncState.IsActive = false;
233233
}
234234
}
235235
else if (returnValue != null)
236236
{
237-
var captureInfo = new CaptureInfo<TReturn>(value: returnValue, name: "@return", type: typeof(TReturn), methodState: MethodState.ExitStartAsync, memberKind: ScopeMemberKind.Return, asyncCaptureInfo: asyncCaptureInfo);
237+
var captureInfo = new CaptureInfo<TReturn>(value: returnValue, name: "@return", methodState: MethodState.ExitStartAsync, memberKind: ScopeMemberKind.Return, asyncCaptureInfo: asyncCaptureInfo);
238238
if (!asyncState.ProbeData.Processor.Process(ref captureInfo, asyncState.SnapshotCreator))
239239
{
240240
asyncState.IsActive = false;

tracer/src/Datadog.Trace/Debugger/Instrumentation/LineDebuggerInvoker.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static void LogArg<TArg>(ref TArg arg, int index, ref LineDebuggerState s
4747
}
4848

4949
var paramName = state.MethodMetadataInfo.ParameterNames[index];
50-
var captureInfo = new CaptureInfo<TArg>(value: arg, type: typeof(TArg), methodState: MethodState.LogArg, name: paramName, memberKind: ScopeMemberKind.Argument);
50+
var captureInfo = new CaptureInfo<TArg>(value: arg, methodState: MethodState.LogArg, name: paramName, memberKind: ScopeMemberKind.Argument);
5151

5252
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
5353
{
@@ -85,7 +85,7 @@ public static void LogLocal<TLocal>(ref TLocal local, int index, ref LineDebugge
8585
return;
8686
}
8787

88-
var captureInfo = new CaptureInfo<TLocal>(value: local, type: typeof(TLocal), methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
88+
var captureInfo = new CaptureInfo<TLocal>(value: local, methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
8989

9090
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
9191
{

tracer/src/Datadog.Trace/Debugger/Instrumentation/MethodDebuggerInvoker.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public static void LogArg<TArg>(ref TArg arg, int index, ref MethodDebuggerState
109109
}
110110

111111
var paramName = state.MethodMetadataInfo.ParameterNames[index];
112-
var captureInfo = new CaptureInfo<TArg>(value: arg, type: typeof(TArg), methodState: MethodState.LogArg, name: paramName, memberKind: ScopeMemberKind.Argument);
112+
var captureInfo = new CaptureInfo<TArg>(value: arg, methodState: MethodState.LogArg, name: paramName, memberKind: ScopeMemberKind.Argument);
113113

114114
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
115115
{
@@ -140,7 +140,7 @@ public static void LogLocal<TLocal>(ref TLocal local, int index, ref MethodDebug
140140
return;
141141
}
142142

143-
var captureInfo = new CaptureInfo<TLocal>(value: local, type: typeof(TLocal), methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
143+
var captureInfo = new CaptureInfo<TLocal>(value: local, methodState: MethodState.LogLocal, name: localName, memberKind: ScopeMemberKind.Local);
144144

145145
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
146146
{
@@ -168,7 +168,7 @@ public static DebuggerReturn EndMethod_StartMarker<TTarget>(TTarget instance, Ex
168168

169169
state.MethodPhase = EvaluateAt.Exit;
170170

171-
var captureInfo = new CaptureInfo<Exception>(value: exception, type: exception?.GetType(), invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Exception, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
171+
var captureInfo = new CaptureInfo<Exception>(value: exception, invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Exception, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
172172

173173
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
174174
{
@@ -200,15 +200,15 @@ public static DebuggerReturn<TReturn> EndMethod_StartMarker<TTarget, TReturn>(TT
200200

201201
if (exception != null)
202202
{
203-
var captureInfo = new CaptureInfo<Exception>(value: exception, type: exception.GetType(), invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Exception, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
203+
var captureInfo = new CaptureInfo<Exception>(value: exception, invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Exception, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
204204
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
205205
{
206206
state.IsActive = false;
207207
}
208208
}
209209
else
210210
{
211-
var captureInfo = new CaptureInfo<TReturn>(value: returnValue, name: "@return", type: typeof(TReturn), invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Return, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
211+
var captureInfo = new CaptureInfo<TReturn>(value: returnValue, name: "@return", invocationTargetType: state.MethodMetadataInfo.DeclaringType, methodState: MethodState.ExitStart, memberKind: ScopeMemberKind.Return, localsCount: state.MethodMetadataInfo.LocalVariableNames.Length, argumentsCount: state.MethodMetadataInfo.ParameterNames.Length);
212212
if (!state.ProbeData.Processor.Process(ref captureInfo, state.SnapshotCreator))
213213
{
214214
state.IsActive = false;

tracer/src/Datadog.Trace/Debugger/Snapshots/DebuggerSnapshotCreator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ private void ExitMethodStart<TReturnOrException>(ref CaptureInfo<TReturnOrExcept
402402
}
403403
else if (info.MemberKind == ScopeMemberKind.Return)
404404
{
405-
CaptureLocal(info.Value, "@return");
405+
CaptureLocal(info.Value, "@return", info.Type);
406406
}
407407

408408
break;
@@ -460,7 +460,7 @@ private bool CaptureAsyncMethodArguments(System.Reflection.FieldInfo[] asyncHois
460460
}
461461

462462
var argumentValue = argument.GetValue(moveNextInvocationTarget);
463-
CaptureArgument(argumentValue, argument.Name, argument.FieldType);
463+
CaptureArgument(argumentValue, argument.Name, argumentValue?.GetType() ?? argument.FieldType);
464464
hasArgument = true;
465465
}
466466

@@ -489,7 +489,7 @@ private void CaptureAsyncMethodLocals(AsyncHelper.FieldInfoNameSanitized[] hoist
489489
}
490490

491491
var localValue = local.Field.GetValue(moveNextInvocationTarget);
492-
CaptureLocal(localValue, local.SanitizedName, local.Field.FieldType);
492+
CaptureLocal(localValue, local.SanitizedName, localValue?.GetType() ?? local.Field.FieldType);
493493
}
494494
}
495495

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
[
2+
{
3+
"dd.span_id": "ScrubbedValue",
4+
"dd.trace_id": "ScrubbedValue",
5+
"ddsource": "dd_debugger",
6+
"ddtags": "Unknown",
7+
"debugger": {
8+
"snapshot": {
9+
"captures": {
10+
"entry": {
11+
"arguments": {
12+
"parameter": {
13+
"fields": {
14+
"_privateField": {
15+
"type": "String",
16+
"value": "bla bla"
17+
},
18+
"Field": {
19+
"type": "String",
20+
"value": "I'm a class field"
21+
},
22+
"ShowMe": {
23+
"type": "String",
24+
"value": "Show Me!"
25+
}
26+
},
27+
"type": "Class",
28+
"value": "Class"
29+
},
30+
"this": {
31+
"type": "AsyncInterfaceProperties",
32+
"value": "AsyncInterfaceProperties"
33+
}
34+
}
35+
},
36+
"return": {
37+
"arguments": {
38+
"parameter": {
39+
"fields": {
40+
"_privateField": {
41+
"type": "String",
42+
"value": "This string should never be visible"
43+
},
44+
"Field": {
45+
"type": "String",
46+
"value": "I'm a class field"
47+
},
48+
"ShowMe": {
49+
"type": "String",
50+
"value": "Show Me!"
51+
}
52+
},
53+
"type": "Class",
54+
"value": "Class"
55+
},
56+
"this": {
57+
"type": "AsyncInterfaceProperties",
58+
"value": "AsyncInterfaceProperties"
59+
}
60+
},
61+
"locals": {
62+
"@return": {
63+
"type": "String",
64+
"value": "Show Me!"
65+
},
66+
"iInterface": {
67+
"isNull": "true",
68+
"type": "IInterface"
69+
}
70+
}
71+
}
72+
},
73+
"duration": "ScrubbedValue",
74+
"id": "ScrubbedValue",
75+
"language": "dotnet",
76+
"probe": {
77+
"id": "ScrubbedValue",
78+
"location": {
79+
"method": "Method",
80+
"type": "Samples.Probes.TestRuns.SmokeTests.AsyncInterfaceProperties"
81+
}
82+
},
83+
"stack": "ScrubbedValue",
84+
"timestamp": "ScrubbedValue"
85+
}
86+
},
87+
"logger": {
88+
"method": "Method",
89+
"name": "Samples.Probes.TestRuns.SmokeTests.AsyncInterfaceProperties",
90+
"thread_id": "ScrubbedValue",
91+
"thread_name": "ScrubbedValue",
92+
"version": "2"
93+
},
94+
"message": "ScrubbedValue",
95+
"service": "probes"
96+
},
97+
{
98+
"dd.span_id": "ScrubbedValue",
99+
"dd.trace_id": "ScrubbedValue",
100+
"ddsource": "dd_debugger",
101+
"ddtags": "Unknown",
102+
"debugger": {
103+
"snapshot": {
104+
"captures": {
105+
"lines": {
106+
"34": {
107+
"arguments": {
108+
"parameter": {
109+
"fields": {
110+
"_privateField": {
111+
"type": "String",
112+
"value": "This string should never be visible"
113+
},
114+
"Field": {
115+
"type": "String",
116+
"value": "I'm a class field"
117+
},
118+
"ShowMe": {
119+
"type": "String",
120+
"value": "Show Me!"
121+
}
122+
},
123+
"type": "Class",
124+
"value": "Class"
125+
},
126+
"this": {
127+
"type": "AsyncInterfaceProperties",
128+
"value": "AsyncInterfaceProperties"
129+
}
130+
},
131+
"locals": {
132+
"iInterface": {
133+
"fields": {
134+
"_privateField": {
135+
"isNull": "true",
136+
"type": "String"
137+
},
138+
"Field": {
139+
"type": "String",
140+
"value": "I'm a class field"
141+
},
142+
"ShowMe": {
143+
"type": "String",
144+
"value": ""
145+
}
146+
},
147+
"type": "Class",
148+
"value": "Class"
149+
}
150+
}
151+
}
152+
}
153+
},
154+
"duration": "ScrubbedValue",
155+
"id": "ScrubbedValue",
156+
"language": "dotnet",
157+
"probe": {
158+
"id": "ScrubbedValue",
159+
"location": {
160+
"file": "AsyncInterfaceProperties.cs",
161+
"lines": [
162+
34
163+
]
164+
}
165+
},
166+
"stack": "ScrubbedValue",
167+
"timestamp": "ScrubbedValue"
168+
}
169+
},
170+
"logger": {
171+
"method": "Method",
172+
"name": "Samples.Probes.TestRuns.SmokeTests.AsyncInterfaceProperties",
173+
"thread_id": "ScrubbedValue",
174+
"thread_name": "ScrubbedValue",
175+
"version": "2"
176+
},
177+
"message": "ScrubbedValue",
178+
"service": "probes"
179+
}
180+
]

0 commit comments

Comments
 (0)