-
Notifications
You must be signed in to change notification settings - Fork 94
Expand file tree
/
Copy pathRaygunClientBase.cs
More file actions
170 lines (151 loc) · 5.92 KB
/
RaygunClientBase.cs
File metadata and controls
170 lines (151 loc) · 5.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System;
using System.Collections.Generic;
using System.Net;
using Mindscape.Raygun4Net.Messages;
namespace Mindscape.Raygun4Net
{
public abstract class RaygunClientBase
{
protected internal const string SentKey = "AlreadySentByRaygun";
/// <summary>
/// Gets or sets the user identity string.
/// </summary>
public virtual string User { get; set; }
/// <summary>
/// Gets or sets information about the user including the identity string.
/// </summary>
public virtual RaygunIdentifierMessage UserInfo { get; set; }
/// <summary>
/// Gets or sets a custom application version identifier for all error messages sent to the Raygun.io endpoint.
/// </summary>
public string ApplicationVersion { get; set; }
protected virtual bool CanSend(Exception exception)
{
return exception == null || exception.Data == null || !exception.Data.Contains(SentKey) || false.Equals(exception.Data[SentKey]);
}
protected void FlagAsSent(Exception exception)
{
if (exception != null && exception.Data != null)
{
try
{
Type[] genericTypes = exception.Data.GetType().GetGenericArguments();
if (genericTypes.Length == 0 || genericTypes[0].IsAssignableFrom(typeof(string)))
{
exception.Data[SentKey] = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(String.Format("Failed to flag exception as sent: {0}", ex.Message));
}
}
}
/// <summary>
/// Raised just before a message is sent. This can be used to make final adjustments to the <see cref="RaygunMessage"/>, or to cancel the send.
/// </summary>
public event EventHandler<RaygunSendingMessageEventArgs> SendingMessage;
private bool _handlingRecursiveErrorSending;
// Returns true if the message can be sent, false if the sending is canceled.
protected bool OnSendingMessage(RaygunMessage raygunMessage)
{
bool result = true;
if (!_handlingRecursiveErrorSending)
{
EventHandler<RaygunSendingMessageEventArgs> handler = SendingMessage;
if (handler != null)
{
RaygunSendingMessageEventArgs args = new RaygunSendingMessageEventArgs(raygunMessage);
try
{
handler(this, args);
}
catch (Exception e)
{
// Catch and send exceptions that occur in the SendingMessage event handler.
// Set the _handlingRecursiveErrorSending flag to prevent infinite errors.
_handlingRecursiveErrorSending = true;
Send(e);
_handlingRecursiveErrorSending = false;
}
result = !args.Cancel;
}
}
return result;
}
/// <summary>
/// Raised before a message is sent. This can be used to add a custom grouping key to a RaygunMessage before sending it to the Raygun service.
/// </summary>
public event EventHandler<RaygunCustomGroupingKeyEventArgs> CustomGroupingKey;
private bool _handlingRecursiveGrouping;
protected string OnCustomGroupingKey(Exception exception, RaygunMessage message)
{
string result = null;
if(!_handlingRecursiveGrouping)
{
var handler = CustomGroupingKey;
if(handler != null)
{
var args = new RaygunCustomGroupingKeyEventArgs(exception, message);
try
{
handler(this, args);
}
catch (Exception e)
{
_handlingRecursiveGrouping = true;
Send(e);
_handlingRecursiveGrouping = false;
}
result = args.CustomGroupingKey;
}
}
return result;
}
/// <summary>
/// List of registered <see cref="IRaygunMessageInitializer"/> objects.
/// </summary>
private List<IRaygunMessageInitializer> RaygunMessageInitializers { get; set; } = new List<IRaygunMessageInitializer>();
/// <summary>
/// Return a copy of the registered <see cref="IRaygunMessageInitializer"/> objects.
/// </summary>
/// <remarks>
/// Ensures that changes made to the collection during processing does not cause problems.
/// </remarks>
protected virtual List<IRaygunMessageInitializer> GetRaygunMessageInitializers()
{
return new List<IRaygunMessageInitializer>(RaygunMessageInitializers);
}
/// <summary>
/// Register a <see cref="IRaygunMessageInitializer"/> to initialize properties on the <see cref="RaygunMessage"/>.
/// </summary>
/// <param name="raygunMessageInitializer">The <see cref="IRaygunMessageInitializer"/> to register.</param>
public virtual void AddMessageInitializer(IRaygunMessageInitializer raygunMessageInitializer)
{
if (RaygunMessageInitializers == null)
{
RaygunMessageInitializers = new List<IRaygunMessageInitializer>();
}
RaygunMessageInitializers.Add(raygunMessageInitializer);
}
/// <summary>
/// Removes a <see cref="IRaygunMessageInitializer"/> from the list of registered <see cref="IRaygunMessageInitializer"/> objects.
/// </summary>
/// <param name="raygunMessageInitializer">The <see cref="IRaygunMessageInitializer"/> to remove.</param>
public virtual bool RemoveMessageInitializer(IRaygunMessageInitializer raygunMessageInitializer)
{
return RaygunMessageInitializers.Remove(raygunMessageInitializer);
}
/// <summary>
/// Transmits an exception to Raygun.io synchronously.
/// </summary>
/// <param name="exception">The exception to deliver.</param>
public abstract void Send(Exception exception);
/// <summary>
/// Posts a RaygunMessage to the Raygun.io api endpoint.
/// </summary>
/// <param name="raygunMessage">The RaygunMessage to send. This needs its OccurredOn property
/// set to a valid DateTime and as much of the Details property as is available.</param>
public abstract void Send(RaygunMessage raygunMessage);
}
}