Skip to content

Commit fce5096

Browse files
author
William Li
authored
Collect crash exception (#3318)
1 parent 9d81590 commit fce5096

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

src/Tasks/Common/TaskBase.cs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
using System;
55
using Microsoft.Build.Utilities;
6+
using Microsoft.Build.Framework;
7+
using System.Collections.Generic;
8+
using System.Globalization;
69

710
namespace Microsoft.NET.Build.Tasks
811
{
@@ -38,10 +41,74 @@ public override bool Execute()
3841
{
3942
Log.LogError(e.Message);
4043
}
44+
catch (Exception e)
45+
{
46+
LogErrorTelemetry("taskBaseCatchException", e);
47+
throw;
48+
}
4149

4250
return !Log.HasLoggedErrors;
4351
}
4452

53+
private void LogErrorTelemetry(string eventName, Exception e)
54+
{
55+
(BuildEngine as IBuildEngine5)?.LogTelemetry(eventName, new Dictionary<string, string> {
56+
{"exceptionType", e.GetType().ToString() },
57+
{"detail", ExceptionToStringWithoutMessage(e) }});
58+
}
59+
60+
private static string ExceptionToStringWithoutMessage(Exception e)
61+
{
62+
const string AggregateException_ToString = "{0}{1}---> (Inner Exception #{2}) {3}{4}{5}";
63+
if (e is AggregateException aggregate)
64+
{
65+
string text = NonAggregateExceptionToStringWithoutMessage(aggregate);
66+
67+
for (int i = 0; i < aggregate.InnerExceptions.Count; i++)
68+
{
69+
text = string.Format(CultureInfo.InvariantCulture,
70+
AggregateException_ToString,
71+
text,
72+
Environment.NewLine,
73+
i,
74+
ExceptionToStringWithoutMessage(aggregate.InnerExceptions[i]),
75+
"<---",
76+
Environment.NewLine);
77+
}
78+
79+
return text;
80+
}
81+
else
82+
{
83+
return NonAggregateExceptionToStringWithoutMessage(e);
84+
}
85+
}
86+
87+
private static string NonAggregateExceptionToStringWithoutMessage(Exception e)
88+
{
89+
string s;
90+
const string Exception_EndOfInnerExceptionStack = "--- End of inner exception stack trace ---";
91+
92+
93+
s = e.GetType().ToString();
94+
95+
if (e.InnerException != null)
96+
{
97+
s = s + " ---> " + ExceptionToStringWithoutMessage(e.InnerException) + Environment.NewLine +
98+
" " + Exception_EndOfInnerExceptionStack;
99+
100+
}
101+
102+
var stackTrace = e.StackTrace;
103+
104+
if (stackTrace != null)
105+
{
106+
s += Environment.NewLine + stackTrace;
107+
}
108+
109+
return s;
110+
}
111+
45112
protected abstract void ExecuteCore();
46113
}
47114
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using FluentAssertions;
2+
using Microsoft.NET.TestFramework;
3+
using Microsoft.NET.TestFramework.Assertions;
4+
using Microsoft.NET.TestFramework.Commands;
5+
using System;
6+
using System.IO;
7+
using Xunit.Abstractions;
8+
using System.Reflection;
9+
10+
namespace Microsoft.NET.Build.Tests
11+
{
12+
public class GivenThatWeWantToCollectExceptionTelemetry : SdkTest
13+
{
14+
public GivenThatWeWantToCollectExceptionTelemetry(ITestOutputHelper log) : base(log)
15+
{
16+
}
17+
18+
[CoreMSBuildAndWindowsOnlyFact]
19+
public void It_collects_Exception()
20+
{
21+
Type loggerType = typeof(LogTelemetryToStdOutForTest);
22+
string telemetryTestLogger = $"/Logger:{loggerType.FullName},{loggerType.GetTypeInfo().Assembly.Location}";
23+
24+
var testAsset = _testAssetsManager.CopyTestAsset("HelloWorld").WithSource().Restore(Log);
25+
26+
var mSBuildCommand = new MSBuildCommand(Log, "GenerateToolsSettingsFileFromBuildProperty", Path.Combine(testAsset.TestRoot));
27+
28+
string invalidPath = @"\\.\COM56";
29+
string causeTaskToFail = $"/p:_ToolsSettingsFilePath={invalidPath}";
30+
31+
mSBuildCommand
32+
.Execute(telemetryTestLogger, causeTaskToFail)
33+
.StdOut.Should()
34+
.Contain("\"EventName\":\"taskBaseCatchException\",\"Properties\":{\"exceptionType\":\"System.IO.FileNotFoundException\"")
35+
.And.Contain("detail");
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)