Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 865933c

Browse files
authored
Send telemetry on unhandled exceptions inside the AnalysisQueue (#460)
* Telemetrize unhandled AnalysisQueue exceptions * make the main exception the inner one instead * don't bother sending isTerminating, we always send false * rename function, event name
1 parent 5764f7e commit 865933c

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

src/LanguageServer/Impl/LanguageServer.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public sealed partial class LanguageServer : IDisposable {
4545

4646
private IServiceContainer _services;
4747
private IUIService _ui;
48+
private ITelemetryService2 _telemetry;
4849

4950
private JsonRpc _rpc;
5051
private JsonSerializer _jsonSerializer;
@@ -60,10 +61,11 @@ public CancellationToken Start(IServiceContainer services, JsonRpc rpc) {
6061
_ui = services.GetService<IUIService>();
6162
_rpc = rpc;
6263
_jsonSerializer = services.GetService<JsonSerializer>();
64+
_telemetry = services.GetService<ITelemetryService2>();
6365

6466
var progress = services.GetService<IProgressService>();
6567

66-
var rpcTraceListener = new TelemetryRpcTraceListener(services.GetService<ITelemetryService2>());
68+
var rpcTraceListener = new TelemetryRpcTraceListener(_telemetry);
6769
_rpc.TraceSource.Listeners.Add(rpcTraceListener);
6870

6971
_server.OnLogMessage += OnLogMessage;
@@ -72,6 +74,7 @@ public CancellationToken Start(IServiceContainer services, JsonRpc rpc) {
7274
_server.OnApplyWorkspaceEdit += OnApplyWorkspaceEdit;
7375
_server.OnRegisterCapability += OnRegisterCapability;
7476
_server.OnUnregisterCapability += OnUnregisterCapability;
77+
_server.AnalysisQueue.UnhandledException += OnAnalysisQueueUnhandledException;
7578

7679
_disposables
7780
.Add(() => _server.OnLogMessage -= OnLogMessage)
@@ -80,6 +83,7 @@ public CancellationToken Start(IServiceContainer services, JsonRpc rpc) {
8083
.Add(() => _server.OnApplyWorkspaceEdit -= OnApplyWorkspaceEdit)
8184
.Add(() => _server.OnRegisterCapability -= OnRegisterCapability)
8285
.Add(() => _server.OnUnregisterCapability -= OnUnregisterCapability)
86+
.Add(() => _server.AnalysisQueue.UnhandledException -= OnAnalysisQueueUnhandledException)
8387
.Add(() => _shutdownCts.Cancel())
8488
.Add(_prioritizer)
8589
.Add(() => _pathsWatcher?.Dispose())
@@ -454,6 +458,16 @@ private void HandlePathWatchChange(JToken section) {
454458
_searchPaths = _initParams.initializationOptions.searchPaths;
455459
}
456460

461+
private void OnAnalysisQueueUnhandledException(object sender, UnhandledExceptionEventArgs e) {
462+
if (!(e.ExceptionObject is Exception ex)) {
463+
Debug.Fail($"ExceptionObject was {e.ExceptionObject.GetType()}, not Exception");
464+
return;
465+
}
466+
467+
var te = Telemetry.CreateEventWithException("analysis_queue.unhandled_exception", ex);
468+
_telemetry.SendTelemetry(te).DoNotWait();
469+
}
470+
457471
private class Prioritizer : IDisposable {
458472
private const int InitializePriority = 0;
459473
private const int ConfigurationPriority = 1;

src/LanguageServer/Impl/Telemetry.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ internal class Telemetry {
2727
public static TelemetryEvent CreateEvent(string eventName) => new TelemetryEvent {
2828
EventName = EventPrefix + eventName,
2929
};
30+
31+
public static TelemetryEvent CreateEventWithException(string eventName, Exception e) {
32+
var te = CreateEvent(eventName);
33+
34+
if (e is AggregateException ae && ae.InnerException != null) {
35+
te.Properties["outerName"] = e.GetType().Name;
36+
te.Properties["outerStackTrace"] = e.StackTrace;
37+
38+
e = ae.Flatten();
39+
40+
while (e.InnerException != null) {
41+
e = e.InnerException;
42+
}
43+
}
44+
45+
te.Properties["name"] = e.GetType().Name;
46+
te.Properties["stackTrace"] = e.StackTrace;
47+
48+
return te;
49+
}
3050
}
3151

3252
internal class TelemetryRpcTraceListener : TraceListener {
@@ -72,10 +92,8 @@ public override void TraceData(TraceEventCache eventCache, string source, TraceE
7292
return;
7393
}
7494

75-
var e = Telemetry.CreateEvent("rpc.exception");
95+
var e = Telemetry.CreateEventWithException("rpc.exception", exception);
7696
e.Properties["method"] = method;
77-
e.Properties["name"] = exception.GetType().Name;
78-
e.Properties["stackTrace"] = exception.StackTrace;
7997

8098
_telemetryService.SendTelemetry(e).DoNotWait();
8199
}

0 commit comments

Comments
 (0)