Skip to content

Commit 896432e

Browse files
committed
Fixed an issue where data exclusion wildcards weren't being checked
* We are now checking data exclusion wildcards. * We are now flowing the ExceptionlessClient through the codebase and using it to get dependencies that we were not before (Add Object is now using the proper json serializer.
1 parent ef15440 commit 896432e

File tree

10 files changed

+133
-35
lines changed

10 files changed

+133
-35
lines changed

Source/Extras/Extensions/ToErrorModelExtensions.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Linq;
88
using System.Reflection;
99
using System.Security;
10+
using Exceptionless.Dependency;
1011
using Exceptionless.Extensions;
1112
using Exceptionless.Logging;
1213
using Exceptionless.Models;
@@ -27,13 +28,19 @@ internal static class ToErrorModelExtensions {
2728
/// Sets the properties from an exception.
2829
/// </summary>
2930
/// <param name="exception">The exception to populate properties from.</param>
30-
/// <param name="log">The log implementation used for diagnostic information.</param>
31-
/// <param name="dataExclusions">Data exclusions that get run on extra exception properties.</param>
32-
public static Error ToErrorModel(this Exception exception, IExceptionlessLog log, IEnumerable<string> dataExclusions) {
33-
return ToErrorModelInternal(exception, log, dataExclusions);
31+
/// <param name="client">
32+
/// The ExceptionlessClient instance used for configuration. If a client is not specified, it will use
33+
/// ExceptionlessClient.Default.
34+
/// </param>
35+
public static Error ToErrorModel(this Exception exception, ExceptionlessClient client = null) {
36+
if (client == null)
37+
client = ExceptionlessClient.Default;
38+
39+
return ToErrorModelInternal(exception, client);
3440
}
3541

36-
private static Error ToErrorModelInternal(Exception exception, IExceptionlessLog log, IEnumerable<string> dataExclusions, bool isInner = false) {
42+
private static Error ToErrorModelInternal(Exception exception, ExceptionlessClient client, bool isInner = false) {
43+
var log = client.Configuration.Resolver.GetLog();
3744
Type type = exception.GetType();
3845

3946
var error = new Error {
@@ -62,8 +69,8 @@ private static Error ToErrorModelInternal(Exception exception, IExceptionlessLog
6269
}
6370

6471
try {
65-
var exclusions = _exceptionExclusions.Union(dataExclusions ?? new List<string>());
66-
var extraProperties = type.GetPublicProperties().Where(p => !exclusions.Contains(p.Name)).ToDictionary(p => p.Name, p => {
72+
var exclusions = _exceptionExclusions.Union(client.Configuration.DataExclusions);
73+
var extraProperties = type.GetPublicProperties().Where(p => !p.Name.AnyWildcardMatches(exclusions, true)).ToDictionary(p => p.Name, p => {
6774
try {
6875
return p.GetValue(exception, null);
6976
} catch { }
@@ -78,12 +85,12 @@ private static Error ToErrorModelInternal(Exception exception, IExceptionlessLog
7885
Name = Error.KnownDataKeys.ExtraProperties,
7986
IgnoreSerializationErrors = true,
8087
MaxDepthToSerialize = 5
81-
});
88+
}, client);
8289
}
8390
} catch { }
8491

8592
if (exception.InnerException != null)
86-
error.Inner = ToErrorModelInternal(exception.InnerException, log, dataExclusions, true);
93+
error.Inner = ToErrorModelInternal(exception.InnerException, client, true);
8794

8895
return error;
8996
}

Source/Extras/Plugins/ErrorPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public void Run(EventPluginContext context) {
1111
return;
1212

1313
context.Event.Type = Event.KnownTypes.Error;
14-
context.Event.Data[Event.KnownDataKeys.Error] = exception.ToErrorModel(context.Log, context.Client.Configuration.DataExclusions);
14+
context.Event.Data[Event.KnownDataKeys.Error] = exception.ToErrorModel(context.Client);
1515
}
1616
}
1717
}

Source/Samples/SampleMvc/Controllers/HomeController.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ public ActionResult Index() {
1717

1818
[HttpPost]
1919
public ViewResult Index(SomeModel model) {
20-
throw new ApplicationException("Error on form submit.");
20+
throw new MyApplicationException("Error on form submit.") {
21+
IgnoredProperty = "Index Test",
22+
RandomValue = Guid.NewGuid().ToString()
23+
};
2124
}
2225

2326
[HttpGet]
@@ -72,15 +75,16 @@ public ActionResult CustomBoom() {
7275
public ActionResult Boom25() {
7376
for (int i = 0; i < 25; i++) {
7477
try {
75-
throw new ApplicationException("Boom!");
78+
throw new MyApplicationException("Boom!") {
79+
IgnoredProperty = "Test",
80+
RandomValue = Guid.NewGuid().ToString()
81+
};
7682
} catch (Exception ex) {
77-
ex.ToExceptionless()
83+
ex.ToExceptionless()
7884
.SetUserIdentity("[email protected]")
7985
.AddRecentTraceLogEntries()
8086
.AddRequestInfo()
81-
.AddObject(new {
82-
Blah = "Hello"
83-
}, name: "Hello")
87+
.AddObject(new { Blah = "Hello" }, name: "Hello")
8488
.AddTags("SomeTag", "AnotherTag")
8589
.MarkAsCritical()
8690
.Submit();
@@ -92,9 +96,7 @@ public ActionResult Boom25() {
9296
.SetUserDescription("[email protected]", "Some description.")
9397
.AddRecentTraceLogEntries()
9498
.AddRequestInfo()
95-
.AddObject(new {
96-
Blah = "Hello"
97-
}, name: "Hello", excludedPropertyNames: new[] { "Blah" })
99+
.AddObject(new { Blah = "Hello" }, name: "Hello", excludedPropertyNames: new[] { "Blah" })
98100
.AddTags("SomeTag", "AnotherTag")
99101
.MarkAsCritical()
100102
.Submit();
@@ -110,4 +112,12 @@ public ActionResult CreateRequestValidationException(string value) {
110112
return RedirectToAction("Index");
111113
}
112114
}
115+
116+
public class MyApplicationException : ApplicationException {
117+
public MyApplicationException(string message) : base(message) {}
118+
119+
public string IgnoredProperty { get; set; }
120+
121+
public string RandomValue { get; set; }
122+
}
113123
}

Source/Samples/SampleMvc/Global.asax.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class MvcApplication : HttpApplication {
1515
protected void Application_Start() {
1616
Trace.Listeners.Add(new NLogTraceListener());
1717
//ExceptionlessClient.Default.Log = new NLogExceptionlessLog();
18+
ExceptionlessClient.Default.Configuration.DefaultData["FirstName"] = "Blake";
19+
ExceptionlessClient.Default.Configuration.DefaultData["IgnoredProperty"] = "Some random data";
1820

1921
AreaRegistration.RegisterAllAreas();
2022

Source/Shared/Extensions/DataDictionaryExtensions.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,14 @@ public static void AddObject(this IData data, object value, string name = null,
7171
Data = value,
7272
Name = name,
7373
MaxDepthToSerialize = maxDepth,
74-
ExcludedPropertyNames = excludedPropertyNames != null ? client.Configuration.DataExclusions.Union(excludedPropertyNames).ToArray() : client.Configuration.DataExclusions.ToArray(),
7574
IgnoreSerializationErrors = ignoreSerializationErrors
7675
};
76+
77+
if (excludedPropertyNames != null)
78+
info.ExcludedPropertyNames.AddRange(excludedPropertyNames);
7779
}
7880

79-
AddObject(data, info);
81+
AddObject(data, info, client);
8082
}
8183

8284
/// <summary>
@@ -94,13 +96,19 @@ public static void AddObject(this IData data, ExtendedDataInfo info, Exceptionle
9496

9597
if (info == null || info.Data == null)
9698
return;
99+
100+
string[] exclusions = info.ExcludedPropertyNames != null
101+
? client.Configuration.DataExclusions.Union(info.ExcludedPropertyNames).ToArray()
102+
: client.Configuration.DataExclusions.ToArray();
97103

98104
string name = !String.IsNullOrWhiteSpace(info.Name) ? info.Name.Trim() : null;
99105
if (String.IsNullOrEmpty(name)) {
100106
name = info.Data.GetType().Name;
101107
int index = 1;
102108
while (data.Data.ContainsKey(name))
103109
name = info.Data.GetType().Name + index++;
110+
} else if (name.AnyWildcardMatches(exclusions, true)) {
111+
return;
104112
}
105113

106114
Type dataType = info.Data.GetType();
@@ -118,10 +126,8 @@ public static void AddObject(this IData data, ExtendedDataInfo info, Exceptionle
118126
if (dataType.IsPrimitiveType()) {
119127
json = info.Data.ToString();
120128
} else {
121-
string[] excludedPropertyNames = info.ExcludedPropertyNames != null ? client.Configuration.DataExclusions.Union(info.ExcludedPropertyNames).ToArray() : client.Configuration.DataExclusions.ToArray();
122-
123-
var serializer = DependencyResolver.Default.GetJsonSerializer();
124-
json = serializer.Serialize(info.Data, excludedPropertyNames, info.MaxDepthToSerialize.HasValue ? info.MaxDepthToSerialize.Value : 5, info.IgnoreSerializationErrors);
129+
var serializer = client.Configuration.Resolver.GetJsonSerializer();
130+
json = serializer.Serialize(info.Data, exclusions, info.MaxDepthToSerialize.HasValue ? info.MaxDepthToSerialize.Value : 5, info.IgnoreSerializationErrors);
125131
}
126132
} catch (Exception ex) {
127133
json = ex.ToString();

Source/Shared/Extensions/StringExtensions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public static string ToLowerUnderscoredWords(this string value) {
2323
}
2424

2525
public static bool AnyWildcardMatches(this string value, IEnumerable<string> patternsToMatch, bool ignoreCase = false) {
26-
if (patternsToMatch == null)
26+
if (patternsToMatch == null || value == null)
2727
return false;
2828

2929
if (ignoreCase)
@@ -33,6 +33,9 @@ public static bool AnyWildcardMatches(this string value, IEnumerable<string> pat
3333
}
3434

3535
private static bool CheckForMatch(string pattern, string value, bool ignoreCase = true) {
36+
if (pattern == null || value == null)
37+
return false;
38+
3639
bool startsWithWildcard = pattern.StartsWith("*");
3740
if (startsWithWildcard)
3841
pattern = pattern.Substring(1);

Source/Shared/Extensions/ToSimpleErrorModelExtensions.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ internal static class ToSimpleErrorModelExtensions {
1717
/// Sets the properties from an exception.
1818
/// </summary>
1919
/// <param name="exception">The exception to populate properties from.</param>
20-
/// <param name="log">The log implementation used for diagnostic information.</param>
21-
/// <param name="dataExclusions">Data exclusions that get run on extra exception properties.</param>
22-
public static SimpleError ToSimpleErrorModel(this Exception exception, IExceptionlessLog log, IEnumerable<string> dataExclusions) {
20+
/// <param name="client">
21+
/// The ExceptionlessClient instance used for configuration. If a client is not specified, it will use
22+
/// ExceptionlessClient.Default.
23+
/// </param>
24+
public static SimpleError ToSimpleErrorModel(this Exception exception, ExceptionlessClient client = null) {
25+
if (client == null)
26+
client = ExceptionlessClient.Default;
27+
2328
Type type = exception.GetType();
2429

2530
var error = new SimpleError {
@@ -29,8 +34,8 @@ public static SimpleError ToSimpleErrorModel(this Exception exception, IExceptio
2934
};
3035

3136
try {
32-
var exclusions = _exceptionExclusions.Union(dataExclusions ?? new List<string>());
33-
var extraProperties = type.GetPublicProperties().Where(p => !exclusions.Contains(p.Name)).ToDictionary(p => p.Name, p => {
37+
var exclusions = _exceptionExclusions.Union(client.Configuration.DataExclusions);
38+
var extraProperties = type.GetPublicProperties().Where(p => !p.Name.AnyWildcardMatches(exclusions, true)).ToDictionary(p => p.Name, p => {
3439
try {
3540
return p.GetValue(exception, null);
3641
} catch {}
@@ -45,12 +50,12 @@ public static SimpleError ToSimpleErrorModel(this Exception exception, IExceptio
4550
Name = SimpleError.KnownDataKeys.ExtraProperties,
4651
IgnoreSerializationErrors = true,
4752
MaxDepthToSerialize = 5
48-
});
53+
}, client);
4954
}
5055
} catch {}
5156

5257
if (exception.InnerException != null)
53-
error.Inner = exception.InnerException.ToSimpleErrorModel(log, dataExclusions);
58+
error.Inner = exception.InnerException.ToSimpleErrorModel(client);
5459

5560
return error;
5661
}

Source/Shared/Plugins/Default/ConfigurationDefaultsPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public void Run(EventPluginContext context) {
88
context.Event.Tags.Add(tag);
99

1010
foreach (var data in context.Client.Configuration.DefaultData)
11-
context.Event.SetProperty(data.Key, data.Value, excludedPropertyNames: context.Client.Configuration.DataExclusions);
11+
context.Event.SetProperty(data.Key, data.Value, client: context.Client);
1212
}
1313
}
1414
}

Source/Shared/Plugins/Default/SimpleErrorPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public void Run(EventPluginContext context) {
1111
return;
1212

1313
context.Event.Type = Event.KnownTypes.Error;
14-
context.Event.Data[Event.KnownDataKeys.SimpleError] = exception.ToSimpleErrorModel(context.Log, context.Client.Configuration.DataExclusions);
14+
context.Event.Data[Event.KnownDataKeys.SimpleError] = exception.ToSimpleErrorModel(context.Client);
1515
}
1616
}
1717
}

Source/Tests/Plugins/PluginTests.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading.Tasks;
45
using Exceptionless.Dependency;
56
using Exceptionless.Plugins;
67
using Exceptionless.Plugins.Default;
78
using Exceptionless.Models;
9+
using Exceptionless.Models.Data;
810
using Exceptionless.Tests.Utility;
911
using Xunit;
1012
using Xunit.Abstractions;
@@ -38,6 +40,61 @@ public void ConfigurationDefaults_EnsureNoDuplicateTagsOrData() {
3840
}
3941
}
4042

43+
[Fact]
44+
public void ConfigurationDefaults_IgnoredProperties() {
45+
var client = new ExceptionlessClient();
46+
client.Configuration.DefaultData.Add("Message", "Test");
47+
48+
var context = new EventPluginContext(client, new Event());
49+
var plugin = new ConfigurationDefaultsPlugin();
50+
plugin.Run(context);
51+
Assert.Equal(1, context.Event.Data.Count);
52+
Assert.Equal("Test", context.Event.Data["Message"]);
53+
54+
client.Configuration.AddDataExclusions("Ignore*");
55+
client.Configuration.DefaultData.Add("Ignored", "Test");
56+
plugin.Run(context);
57+
Assert.Equal(1, context.Event.Data.Count);
58+
Assert.Equal("Test", context.Event.Data["Message"]);
59+
}
60+
61+
[Fact]
62+
public void ErrorPlugin_IgnoredProperties() {
63+
var exception = new MyApplicationException("Test") {
64+
IgnoredProperty = "Test",
65+
RandomValue = "Test"
66+
};
67+
68+
var errorPlugins = new List<IEventPlugin> {
69+
new ErrorPlugin(),
70+
new SimpleErrorPlugin()
71+
};
72+
73+
foreach (var plugin in errorPlugins) {
74+
var client = new ExceptionlessClient();
75+
var context = new EventPluginContext(client, new Event());
76+
context.ContextData.SetException(exception);
77+
78+
plugin.Run(context);
79+
IData error = context.Event.GetError() as IData ?? context.Event.GetSimpleError();
80+
Assert.NotNull(error);
81+
Assert.True(error.Data.ContainsKey(Error.KnownDataKeys.ExtraProperties));
82+
var json = error.Data[Error.KnownDataKeys.ExtraProperties] as string;
83+
Assert.Equal("{\"ignored_property\":\"Test\",\"random_value\":\"Test\"}", json);
84+
85+
client.Configuration.AddDataExclusions("Ignore*");
86+
context = new EventPluginContext(client, new Event());
87+
context.ContextData.SetException(exception);
88+
89+
plugin.Run(context);
90+
error = context.Event.GetError() as IData ?? context.Event.GetSimpleError();
91+
Assert.NotNull(error);
92+
Assert.True(error.Data.ContainsKey(Error.KnownDataKeys.ExtraProperties));
93+
json = error.Data[Error.KnownDataKeys.ExtraProperties] as string;
94+
Assert.Equal("{\"random_value\":\"Test\"}", json);
95+
}
96+
}
97+
4198
[Theory(Skip = "TODO: This needs to be skipped until the client is sending session start and end.")]
4299
[InlineData(Event.KnownTypes.Error)]
43100
[InlineData(Event.KnownTypes.FeatureUsage)]
@@ -147,5 +204,13 @@ public void Run(EventPluginContext context) {}
147204
public class PluginWithPriority11 : IEventPlugin {
148205
public void Run(EventPluginContext context) {}
149206
}
207+
208+
public class MyApplicationException : ApplicationException {
209+
public MyApplicationException(string message) : base(message) {}
210+
211+
public string IgnoredProperty { get; set; }
212+
213+
public string RandomValue { get; set; }
214+
}
150215
}
151216
}

0 commit comments

Comments
 (0)