diff --git a/Mindscape.Raygun4Net.Core/IRaygunMessageInitializer.cs b/Mindscape.Raygun4Net.Core/IRaygunMessageInitializer.cs
new file mode 100644
index 00000000..793df0e0
--- /dev/null
+++ b/Mindscape.Raygun4Net.Core/IRaygunMessageInitializer.cs
@@ -0,0 +1,20 @@
+using Mindscape.Raygun4Net.Messages;
+
+namespace Mindscape.Raygun4Net
+{
+ ///
+ /// Represents an initializer for objects.
+ ///
+ ///
+ /// The Raygun Clients use registered
+ /// to automatically add additional properties to objects.
+ ///
+ public interface IRaygunMessageInitializer
+ {
+ ///
+ /// Initializes properties of the specified object.
+ ///
+ /// The to initialize.
+ void Initialize(RaygunMessage raygunMessage);
+ }
+}
\ No newline at end of file
diff --git a/Mindscape.Raygun4Net.Core/Mindscape.Raygun4Net.Core.csproj b/Mindscape.Raygun4Net.Core/Mindscape.Raygun4Net.Core.csproj
index 5b219fcb..5099311b 100644
--- a/Mindscape.Raygun4Net.Core/Mindscape.Raygun4Net.Core.csproj
+++ b/Mindscape.Raygun4Net.Core/Mindscape.Raygun4Net.Core.csproj
@@ -121,6 +121,7 @@
SimpleJson.cs
+
diff --git a/Mindscape.Raygun4Net.WebApi.Tests/Mindscape.Raygun4Net.WebApi.Tests.csproj b/Mindscape.Raygun4Net.WebApi.Tests/Mindscape.Raygun4Net.WebApi.Tests.csproj
index d3bb63fc..39828cb6 100644
--- a/Mindscape.Raygun4Net.WebApi.Tests/Mindscape.Raygun4Net.WebApi.Tests.csproj
+++ b/Mindscape.Raygun4Net.WebApi.Tests/Mindscape.Raygun4Net.WebApi.Tests.csproj
@@ -49,6 +49,7 @@
+
diff --git a/Mindscape.Raygun4Net.WebApi.Tests/Model/FakeRaygunWebApiClient.cs b/Mindscape.Raygun4Net.WebApi.Tests/Model/FakeRaygunWebApiClient.cs
index 42b0894e..a6cdf491 100644
--- a/Mindscape.Raygun4Net.WebApi.Tests/Model/FakeRaygunWebApiClient.cs
+++ b/Mindscape.Raygun4Net.WebApi.Tests/Model/FakeRaygunWebApiClient.cs
@@ -1,5 +1,6 @@
using Mindscape.Raygun4Net.Messages;
using System;
+using System.Collections;
using System.Collections.Generic;
namespace Mindscape.Raygun4Net.WebApi.Tests.Model
@@ -15,5 +16,10 @@ public IEnumerable ExposeStripWrapperExceptions(Exception exception)
{
return base.StripWrapperExceptions(exception);
}
+
+ public RaygunMessage ExposeBuildMessage(Exception exception, IList tags, IDictionary userCustomData, DateTime? currentTime = null)
+ {
+ return base.BuildMessage(exception, tags, userCustomData, currentTime);
+ }
}
}
diff --git a/Mindscape.Raygun4Net.WebApi.Tests/Model/TestRaygunMessageInitializer.cs b/Mindscape.Raygun4Net.WebApi.Tests/Model/TestRaygunMessageInitializer.cs
new file mode 100644
index 00000000..1c677aa5
--- /dev/null
+++ b/Mindscape.Raygun4Net.WebApi.Tests/Model/TestRaygunMessageInitializer.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Mindscape.Raygun4Net.Messages;
+
+namespace Mindscape.Raygun4Net.WebApi.Tests.Model
+{
+ public class TestRaygunMessageInitializer : IRaygunMessageInitializer
+ {
+ public void Initialize(RaygunMessage raygunMessage)
+ {
+ if (raygunMessage.Details.UserCustomData == null)
+ {
+ raygunMessage.Details.UserCustomData = new Dictionary();
+ }
+ raygunMessage.Details.UserCustomData["initializerTestData"] = "true";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mindscape.Raygun4Net.WebApi.Tests/RaygunWebApiClientTests.cs b/Mindscape.Raygun4Net.WebApi.Tests/RaygunWebApiClientTests.cs
index 353daa69..f0daffe1 100644
--- a/Mindscape.Raygun4Net.WebApi.Tests/RaygunWebApiClientTests.cs
+++ b/Mindscape.Raygun4Net.WebApi.Tests/RaygunWebApiClientTests.cs
@@ -265,5 +265,14 @@ public void StripReflectionTypeLoadException()
Assert.IsTrue(ex1.Data["Type"].ToString().Contains("FakeRaygunWebApiClient"));
Assert.IsTrue(ex2.Data["Type"].ToString().Contains("WrapperException"));
}
+
+ [Test]
+ public void CanUseInitializerToSetData()
+ {
+ _client.AddMessageInitializer(new TestRaygunMessageInitializer());
+ var message = _client.ExposeBuildMessage(_exception, null, null);
+
+ Assert.IsTrue(message.Details.UserCustomData.Contains("initializerTestData"));
+ }
}
}
diff --git a/Mindscape.Raygun4Net.WebApi/RaygunWebApiClient.cs b/Mindscape.Raygun4Net.WebApi/RaygunWebApiClient.cs
index 4d9362cf..99968812 100644
--- a/Mindscape.Raygun4Net.WebApi/RaygunWebApiClient.cs
+++ b/Mindscape.Raygun4Net.WebApi/RaygunWebApiClient.cs
@@ -22,7 +22,6 @@ public class RaygunWebApiClient : RaygunClientBase
private readonly List _wrapperExceptions = new List();
private readonly ThreadLocal _currentWebRequest = new ThreadLocal(() => null);
- private readonly ThreadLocal _currentRequestMessage = new ThreadLocal(() => null);
private static RaygunWebApiExceptionFilter _exceptionFilter;
private static RaygunWebApiActionFilter _actionFilter;
@@ -354,8 +353,6 @@ public void Send(Exception exception, IList tags, IDictionary userCustom
{
if (CanSend(exception))
{
- _currentRequestMessage.Value = BuildRequestMessage();
-
StripAndSend(exception, tags, userCustomData);
FlagAsSent(exception);
}
@@ -390,15 +387,9 @@ public void SendInBackground(Exception exception, IList tags, IDictionar
{
if (CanSend(exception))
{
- // We need to process the HttpRequestMessage on the current thread,
- // otherwise it will be disposed while we are using it on the other thread.
- RaygunRequestMessage currentRequestMessage = BuildRequestMessage();
DateTime currentTime = DateTime.UtcNow;
-
- ThreadPool.QueueUserWorkItem(c => {
- _currentRequestMessage.Value = currentRequestMessage;
- StripAndSend(exception, tags, userCustomData, currentTime);
- });
+
+ StripAndSendInBackground(exception, tags, userCustomData, currentTime);
FlagAsSent(exception);
}
}
@@ -439,7 +430,7 @@ protected RaygunMessage BuildMessage(Exception exception, IList tags, ID
protected RaygunMessage BuildMessage(Exception exception, IList tags, IDictionary userCustomData, DateTime? currentTime = null)
{
var message = RaygunWebApiMessageBuilder.New
- .SetHttpDetails(_currentRequestMessage.Value)
+ .SetHttpDetails(BuildRequestMessage())
.SetTimeStamp(currentTime)
.SetEnvironmentDetails()
.SetMachineName(Environment.MachineName)
@@ -455,6 +446,25 @@ protected RaygunMessage BuildMessage(Exception exception, IList tags, ID
{
message.Details.GroupingKey = customGroupingKey;
}
+
+ var initializers = GetRaygunMessageInitializers();
+ foreach (var initializer in initializers)
+ {
+ try
+ {
+ initializer.Initialize(message);
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Trace.WriteLine(string.Format("Error Initializing RaygunMessage {0}", ex.Message));
+
+ if (RaygunSettings.Settings.ThrowOnError)
+ {
+ throw;
+ }
+ }
+ }
+
return message;
}
@@ -466,6 +476,21 @@ private void StripAndSend(Exception exception, IList tags, IDictionary u
}
}
+ private void StripAndSendInBackground(Exception exception, IList tags, IDictionary userCustomData, DateTime? currentTime = null)
+ {
+ var messages = new List();
+ foreach (Exception e in StripWrapperExceptions(exception))
+ {
+ messages.Add(BuildMessage(e, tags, userCustomData, currentTime));
+ }
+ // Could use SendInBackground here, but like this we queue multiple sends on a single thread
+ ThreadPool.QueueUserWorkItem(c => {
+ foreach (var message in messages) {
+ Send(message);
+ }
+ });
+ }
+
protected IEnumerable StripWrapperExceptions(Exception exception)
{
if (exception != null && _wrapperExceptions.Any(wrapperException => exception.GetType() == wrapperException && (exception.InnerException != null || exception is ReflectionTypeLoadException)))
diff --git a/Mindscape.Raygun4Net/RaygunClientBase.cs b/Mindscape.Raygun4Net/RaygunClientBase.cs
index 2418c44e..9c792efd 100644
--- a/Mindscape.Raygun4Net/RaygunClientBase.cs
+++ b/Mindscape.Raygun4Net/RaygunClientBase.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Net;
using Mindscape.Raygun4Net.Messages;
@@ -115,6 +116,44 @@ protected string OnCustomGroupingKey(Exception exception, RaygunMessage message)
return result;
}
+ ///
+ /// List of registered objects.
+ ///
+ private List RaygunMessageInitializers { get; set; } = new List();
+
+ ///
+ /// Return a copy of the registered objects.
+ ///
+ ///
+ /// Ensures that changes made to the collection during processing does not cause problems.
+ ///
+ protected virtual List GetRaygunMessageInitializers()
+ {
+ return new List(RaygunMessageInitializers);
+ }
+
+ ///
+ /// Register a to initialize properties on the .
+ ///
+ /// The to register.
+ public virtual void AddMessageInitializer(IRaygunMessageInitializer raygunMessageInitializer)
+ {
+ if (RaygunMessageInitializers == null)
+ {
+ RaygunMessageInitializers = new List();
+ }
+ RaygunMessageInitializers.Add(raygunMessageInitializer);
+ }
+
+ ///
+ /// Removes a from the list of registered objects.
+ ///
+ /// The to remove.
+ public virtual bool RemoveMessageInitializer(IRaygunMessageInitializer raygunMessageInitializer)
+ {
+ return RaygunMessageInitializers.Remove(raygunMessageInitializer);
+ }
+
///
/// Transmits an exception to Raygun.io synchronously.
///