Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit aa670be

Browse files
committed
[Debugger] Added telemetry for stepping and Locals/Watch/CallStack/Tooltips
Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1010671/
1 parent 6fd3949 commit aa670be

File tree

14 files changed

+164
-55
lines changed

14 files changed

+164
-55
lines changed

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/PinnedWatches/PinnedWatchView.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public PinnedWatchView (PinnedWatch watch, StackFrame frame)
5757
controller.AllowExpanding = false;
5858

5959
treeView = controller.GetMacControl (ObjectValueTreeViewFlags.PinnedWatchFlags);
60-
60+
treeView.UIElementName = "PinnedWatch";
6161
controller.PinnedWatch = watch;
6262

6363
if (watch.Value != null)

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using Microsoft.VisualStudio.Language.Intellisense;
88
using Microsoft.VisualStudio.Text;
99
using Microsoft.VisualStudio.Text.Editor;
10-
10+
using Mono.Debugging.Client;
1111
using MonoDevelop.Core;
1212
using MonoDevelop.Ide.Gui.Documents;
1313

@@ -119,22 +119,27 @@ public async Task<QuickInfoItem> GetQuickInfoItemAsync (IAsyncQuickInfoSession s
119119
return null;
120120
}
121121

122-
private async Task EvaluateAndShowTooltipAsync (IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken)
122+
async Task EvaluateAndShowTooltipAsync (IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken)
123123
{
124124
var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone ();
125125
options.AllowMethodEvaluation = true;
126126
options.AllowTargetInvoke = true;
127+
ObjectValue val;
127128

128-
var val = DebuggingService.CurrentFrame.GetExpressionValue (debugInfo.Text, options);
129+
using (var timer = DebuggingService.CurrentFrame.DebuggerSession.TooltipStats.StartTimer ()) {
130+
val = DebuggingService.CurrentFrame.GetExpressionValue (debugInfo.Text, options);
129131

130-
if (val.IsEvaluating)
131-
await WaitOneAsync (val.WaitHandle, cancellationToken);
132+
if (val.IsEvaluating)
133+
await WaitOneAsync (val.WaitHandle, cancellationToken);
132134

133-
if (cancellationToken.IsCancellationRequested)
134-
return;
135+
if (cancellationToken.IsCancellationRequested)
136+
return;
135137

136-
if (val == null || val.IsUnknown || val.IsNotSupported)
137-
return;
138+
if (val == null || val.IsUnknown || val.IsNotSupported)
139+
return;
140+
141+
timer.Success = true;
142+
}
138143

139144
if (!view.Properties.TryGetProperty (typeof (Widget), out Widget gtkParent))
140145
return;

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/MacDebuggerTooltipWindow.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public MacDebuggerTooltipWindow (PinnedWatchLocation location, StackFrame frame,
5353
controller.PinnedWatchLocation = location;
5454

5555
treeView = controller.GetMacControl (ObjectValueTreeViewFlags.TooltipFlags);
56+
treeView.UIElementName = "Tooltip";
5657
treeView.NodePinned += OnPinStatusChanged;
5758
treeView.StartEditing += OnStartEditing;
5859
treeView.EndEditing += OnEndEditing;

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,36 @@
2424
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525
// THE SOFTWARE.
2626

27-
using MonoDevelop.Core.Instrumentation;
2827
using System;
2928

29+
using MonoDevelop.Core.Instrumentation;
30+
3031
namespace MonoDevelop.Debugger
3132
{
3233
static class Counters
3334
{
3435
public static Counter DebugSession = InstrumentationService.CreateCounter ("Debug Session", "Debugger", id: "Debugger.DebugSession");
3536
public static Counter EvaluationStats = InstrumentationService.CreateCounter ("Evaluation Statistics", "Debugger", id: "Debugger.EvaluationStatistics");
37+
public static Counter StepInStats = InstrumentationService.CreateCounter ("Step In Statistics", "Debugger", id: "Debugger.StepInStatistics");
38+
public static Counter StepOutStats = InstrumentationService.CreateCounter ("Step Out Statistics", "Debugger", id: "Debugger.StepOutStatistics");
39+
public static Counter StepOverStats = InstrumentationService.CreateCounter ("Step Over Statistics", "Debugger", id: "Debugger.StepOverStatistics");
40+
public static Counter StepInstructionStats = InstrumentationService.CreateCounter ("Step Instruction Statistics", "Debugger", id: "Debugger.StepInstructionStatistics");
41+
public static Counter NextInstructionStats = InstrumentationService.CreateCounter ("Next Instruction Statistics", "Debugger", id: "Debugger.NextInstructionStatistics");
3642
public static TimerCounter<DebuggerStartMetadata> DebuggerStart = InstrumentationService.CreateTimerCounter<DebuggerStartMetadata> ("Debugger Start", "Debugger", id: "Debugger.Start");
3743
public static TimerCounter<DebuggerActionMetadata> DebuggerAction = InstrumentationService.CreateTimerCounter<DebuggerActionMetadata> ("Debugger Action", "Debugger", id: "Debugger.Action");
44+
public static Counter LocalVariableStats = InstrumentationService.CreateCounter ("Local Variable Statistics", "Debugger", id: "Debugger.LocalVariableStatistics");
45+
public static Counter WatchExpressionStats = InstrumentationService.CreateCounter ("Watch Expression Statistics", "Debugger", id: "Debugger.WatchExpressionStatistics");
46+
public static Counter StackTraceStats = InstrumentationService.CreateCounter ("Stack Trace Statistics", "Debugger", id: "Debugger.StackTraceStatistics");
47+
public static Counter TooltipStats = InstrumentationService.CreateCounter ("Tooltip Statistics", "Debugger", id: "Debugger.TooltipStatistics");
3848
public static Counter DebuggerBusy = InstrumentationService.CreateCounter ("Debugger Busy", "Debugger", id: "Debugger.Busy");
49+
public static Counter LocalsPadFrameChanged = InstrumentationService.CreateCounter ("The StackFrame changed in the Locals Pad", "Debugger", id: "Debugger.LocalsPadFrameChanged");
50+
public static Counter AddedWatchFromLocals = InstrumentationService.CreateCounter ("Added a Watch Expression from the Locals Pad", "Debugger", id: "Debugger.AddedWatchFromLocals");
51+
public static Counter ManuallyAddedWatch = InstrumentationService.CreateCounter ("User Manually Added Watch Expression", "Debugger", id: "Debugger.ManuallyAddedWatch");
52+
public static Counter PinnedWatch = InstrumentationService.CreateCounter ("Pinned Watch Expression", "Debugger", id: "Debugger.PinnedWatch");
53+
public static Counter EditedValue = InstrumentationService.CreateCounter ("User Edited Variable Value", "Debugger", id: "Debugger.EditedValue");
54+
public static Counter ExpandedNode = InstrumentationService.CreateCounter ("User Expanded ObjectValue Node", "Debugger", id: "Debugger.ExpandedObjectValueNode");
55+
public static Counter OpenedPreviewer = InstrumentationService.CreateCounter ("User opened the value in the previewer", "Debugger", id: "Debugger.OpenedPreviewer");
56+
public static Counter OpenedVisualizer = InstrumentationService.CreateCounter ("User opened the value in a Visualizer", "Debugger", id: "Debugger.OpenedVisualizer");
3957
}
4058

4159
class DebuggerStartMetadata : CounterMetadata

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,31 @@
2727
//
2828

2929
using System;
30-
using System.Collections.Generic;
3130
using System.Xml;
31+
using System.Linq;
32+
using System.Threading;
33+
using System.Globalization;
34+
using System.Threading.Tasks;
35+
using System.Collections.Generic;
36+
using System.Collections.Concurrent;
37+
3238
using Mono.Addins;
39+
3340
using Mono.Debugging.Client;
34-
using MonoDevelop.Core;
35-
using MonoDevelop.Core.Execution;
41+
42+
using Microsoft.VisualStudio.Text;
43+
using Microsoft.CodeAnalysis.Text;
44+
3645
using MonoDevelop.Ide;
46+
using MonoDevelop.Core;
3747
using MonoDevelop.Ide.Gui;
38-
using MonoDevelop.Ide.Gui.Content;
3948
using MonoDevelop.Projects;
40-
using MonoDevelop.Debugger.Viewers;
41-
42-
/*
43-
* Some places we should be doing some error handling we used to toss
44-
* exceptions, now we error out silently, this needs a real solution.
45-
*/
49+
using MonoDevelop.Components;
50+
using MonoDevelop.Core.Execution;
4651
using MonoDevelop.Ide.TextEditing;
47-
using System.Linq;
48-
using System.Threading.Tasks;
49-
using System.Collections.Concurrent;
50-
using System.Threading;
52+
using MonoDevelop.Ide.Gui.Content;
53+
using MonoDevelop.Debugger.Viewers;
5154
using MonoDevelop.Core.Instrumentation;
52-
using MonoDevelop.Components;
53-
using Microsoft.VisualStudio.Text;
54-
using Microsoft.CodeAnalysis.Text;
5555

5656
namespace MonoDevelop.Debugger
5757
{
@@ -135,7 +135,6 @@ static void IdeApp_Exiting (object sender, ExitEventArgs args)
135135
args.Cancel = true;
136136
}
137137

138-
139138
public static IExecutionHandler GetExecutionHandler ()
140139
{
141140
return executionHandlerFactory;
@@ -145,7 +144,6 @@ public static DebuggerSession DebuggerSession {
145144
get { return currentSession?.Session ?? sessions.Values.FirstOrDefault ()?.Session; }
146145
}
147146

148-
149147
public static DebuggerSession [] GetSessions ()
150148
{
151149
return sessions.Keys.ToArray ();
@@ -815,7 +813,19 @@ public void BreakpointTraceHandler (BreakEvent be, string trace)
815813
public void Dispose ()
816814
{
817815
UpdateDebugSessionCounter ();
818-
UpdateEvaluationStatsCounter ();
816+
817+
UpdateStatsCounter (Counters.EvaluationStats, Session.EvaluationStats);
818+
819+
UpdateStatsCounter (Counters.StepInStats, Session.StepInStats);
820+
UpdateStatsCounter (Counters.StepOutStats, Session.StepOutStats);
821+
UpdateStatsCounter (Counters.StepOverStats, Session.StepOverStats);
822+
UpdateStatsCounter (Counters.StepInstructionStats, Session.StepInstructionStats);
823+
UpdateStatsCounter (Counters.NextInstructionStats, Session.NextInstructionStats);
824+
825+
UpdateStatsCounter (Counters.LocalVariableStats, Session.LocalVariableStats);
826+
UpdateStatsCounter (Counters.WatchExpressionStats, Session.WatchExpressionStats);
827+
UpdateStatsCounter (Counters.StackTraceStats, Session.StackTraceStats);
828+
UpdateStatsCounter (Counters.TooltipStats, Session.TooltipStats);
819829

820830
console?.Dispose ();
821831
console = null;
@@ -844,37 +854,33 @@ public bool SessionError {
844854
void UpdateDebugSessionCounter ()
845855
{
846856
var metadata = new Dictionary<string, object> ();
847-
metadata ["Success"] = (!SessionError).ToString ();
857+
metadata ["Success"] = (!SessionError).ToString (CultureInfo.InvariantCulture);
848858
metadata ["DebuggerType"] = Engine.Id;
849859

850860
if (firstAssemblyLoadTimer != null) {
851861
if (firstAssemblyLoadTimer.IsRunning) {
852862
// No first assembly load event.
853863
firstAssemblyLoadTimer.Stop ();
854864
} else {
855-
metadata ["AssemblyFirstLoadDuration"] = firstAssemblyLoadTimer.ElapsedMilliseconds.ToString ();
865+
metadata ["AssemblyFirstLoadDuration"] = firstAssemblyLoadTimer.ElapsedMilliseconds.ToString (CultureInfo.InvariantCulture);
856866
}
857867
}
858868

859869
Counters.DebugSession.Inc (1, null, metadata);
860870
}
861871

862-
void UpdateEvaluationStatsCounter ()
872+
void UpdateStatsCounter (Counter counter, DebuggerStatistics stats)
863873
{
864-
if (Session.EvaluationStats.TimingsCount == 0 && Session.EvaluationStats.FailureCount == 0) {
874+
if (stats.TimingsCount == 0 && stats.FailureCount == 0) {
865875
// No timings or failures recorded.
866876
return;
867877
}
868878

869879
var metadata = new Dictionary<string, object> ();
870-
metadata ["DebuggerType"] = Engine.Id;
871-
metadata ["AverageDuration"] = Session.EvaluationStats.AverageTime.ToString ();
872-
metadata ["MaximumDuration"] = Session.EvaluationStats.MaxTime.ToString ();
873-
metadata ["MinimumDuration"] = Session.EvaluationStats.MinTime.ToString ();
874-
metadata ["FailureCount"] = Session.EvaluationStats.FailureCount.ToString ();
875-
metadata ["SuccessCount"] = Session.EvaluationStats.TimingsCount.ToString ();
880+
metadata["DebuggerType"] = Engine.Id;
881+
stats.Serialize (metadata);
876882

877-
Counters.EvaluationStats.Inc (1, null, metadata);
883+
counter.Inc (1, null, metadata);
878884
}
879885

880886
bool ExceptionHandler (Exception ex)

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ Widget CreateExceptionValueTreeView ()
194194

195195
if (Platform.IsMac) {
196196
macExceptionValueTreeView = controller.GetMacControl (ObjectValueTreeViewFlags.ObjectValuePadFlags);
197+
macExceptionValueTreeView.UIElementName = "ExceptionCaughtDialog";
197198
} else {
198199
exceptionValueTreeView = controller.GetGtkControl (ObjectValueTreeViewFlags.ExceptionCaughtFlags);
199200
}

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
//
2727

2828
using System;
29+
using System.Collections.Generic;
2930

3031
using Mono.Debugging.Client;
3132

@@ -67,7 +68,7 @@ public LocalsPad ()
6768

6869
void AddFakeNodes ()
6970
{
70-
var xx = new System.Collections.Generic.List<ObjectValueNode> ();
71+
var xx = new List<ObjectValueNode> ();
7172

7273
xx.Add (new FakeObjectValueNode ("f1"));
7374
xx.Add (new FakeIsImplicitNotSupportedObjectValueNode ());
@@ -84,14 +85,35 @@ void AddFakeNodes ()
8485
controller.AddValues (xx);
8586
}
8687

87-
void ReloadValues ()
88+
void ReloadValues (bool frameChanged)
8889
{
8990
var frame = DebuggingService.CurrentFrame;
9091

9192
if (frame == null)
9293
return;
9394

94-
var locals = frame.GetAllLocals ();
95+
ObjectValue[] locals;
96+
TimeSpan elapsed;
97+
98+
using (var timer = frame.DebuggerSession.LocalVariableStats.StartTimer ()) {
99+
try {
100+
locals = frame.GetAllLocals ();
101+
timer.Stop (true);
102+
} catch {
103+
locals = new ObjectValue[0];
104+
timer.Stop (false);
105+
}
106+
107+
elapsed = timer.Elapsed;
108+
}
109+
110+
if (frameChanged) {
111+
var metadata = new Dictionary<string, object> ();
112+
metadata["LocalsCount"] = locals.Length;
113+
metadata["Elapsed"] = elapsed.TotalMilliseconds;
114+
115+
Counters.LocalsPadFrameChanged.Inc (1, null, metadata);
116+
}
95117

96118
DebuggerLoggingService.LogMessage ("Begin Local Variables:");
97119
foreach (var local in locals)
@@ -107,7 +129,6 @@ void ReloadValues ()
107129
_treeview.EndUpdates ();
108130
}
109131

110-
111132
if (EnableFakeNodes)
112133
AddFakeNodes ();
113134
} else {
@@ -119,13 +140,13 @@ void ReloadValues ()
119140
public override void OnUpdateFrame ()
120141
{
121142
base.OnUpdateFrame ();
122-
ReloadValues ();
143+
ReloadValues (true);
123144
}
124145

125146
public override void OnUpdateValues ()
126147
{
127148
base.OnUpdateValues ();
128-
ReloadValues ();
149+
ReloadValues (false);
129150
}
130151
}
131152
}

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,10 @@ void CommitEdit ()
182182
UpdateContents ();
183183

184184
if (Node is AddNewExpressionObjectValueNode) {
185-
if (newValue.Length > 0)
185+
if (newValue.Length > 0) {
186186
TreeView.OnExpressionAdded (newValue);
187+
Counters.ManuallyAddedWatch.Inc (1);
188+
}
187189
} else if (newValue != oldValue) {
188190
TreeView.OnExpressionEdited (Node, newValue);
189191
}
@@ -429,6 +431,12 @@ void OnPreviewButtonClicked (object sender, EventArgs e)
429431
SetPreviewButtonIcon (PreviewButtonIcon.Active);
430432

431433
DebuggingService.ShowPreviewVisualizer (val, IdeApp.Workbench.RootWindow, buttonArea);
434+
435+
var metadata = new Dictionary<string, object> ();
436+
metadata["UIElementName"] = TreeView.UIElementName;
437+
metadata["ObjectValue.Type"] = val.TypeName;
438+
439+
Counters.OpenedPreviewer.Inc (1, null, metadata);
432440
}
433441

434442
void OnEditorLostFocus (object sender, EventArgs e)

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerTextField.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525
// THE SOFTWARE.
2626

27+
using System.Collections.Generic;
28+
2729
using AppKit;
2830
using Foundation;
2931

@@ -103,8 +105,14 @@ public override void DidEndEditing (NSNotification notification)
103105
cellView.TreeView.OnExpressionEdited (cellView.Node, newValue);
104106
}
105107
} else if (cellView is MacDebuggerObjectValueView) {
106-
if (newValue != oldValue && cellView.TreeView.GetEditValue (cellView.Node, newValue))
108+
if (newValue != oldValue && cellView.TreeView.GetEditValue (cellView.Node, newValue)) {
109+
var metadata = new Dictionary<string, object> ();
110+
metadata["UIElementName"] = cellView.TreeView.UIElementName;
111+
metadata["ObjectValue.Type"] = cellView.Node.TypeName;
112+
113+
Counters.EditedValue.Inc (1, null, metadata);
107114
cellView.Refresh ();
115+
}
108116
}
109117

110118
oldValue = newValue = null;

0 commit comments

Comments
 (0)