Skip to content

Commit 66974f6

Browse files
committed
Added support for deduplicating events and submitting with a total count
This allows you to see the overall total
2 parents 90331f9 + 04db85b commit 66974f6

19 files changed

+640
-43
lines changed

Source/Shared/Exceptionless.Portable.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@
6060
<Compile Include="Dependency\TinyIoC.cs" />
6161
<Compile Include="Events\EventSubmissionEventArgsBase.cs" />
6262
<Compile Include="Events\EventSubmittedEventArgs.cs" />
63+
<Compile Include="Extensions\CollectionEqualityExtensions.cs" />
64+
<Compile Include="Plugins\Default\1010_DuplicateCheckerPlugin.cs" />
6365
<Compile Include="Models\Client\Data\ManualStackingInfo.cs" />
6466
<Compile Include="Plugins\Default\025_SessionIdManagementPlugin.cs" />
65-
<Compile Include="Plugins\Default\030_DuplicateCheckerPlugin.cs" />
6667
<Compile Include="Plugins\ContextData.cs" />
6768
<Compile Include="Plugins\Default\1000_CancelSessionsWithNoUserPlugin.cs" />
6869
<Compile Include="Plugins\Default\100_HeartbeatPlugin.cs" />
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace Exceptionless {
6+
internal static class CollectionEqualityExtensions {
7+
public static bool CollectionEquals<T>(this IEnumerable<T> source, IEnumerable<T> other) {
8+
var sourceEnumerator = source.GetEnumerator();
9+
var otherEnumerator = other.GetEnumerator();
10+
11+
while (sourceEnumerator.MoveNext()) {
12+
if (!otherEnumerator.MoveNext()) {
13+
// counts differ
14+
return false;
15+
}
16+
17+
if (sourceEnumerator.Current.Equals(otherEnumerator.Current)) {
18+
// values aren't equal
19+
return false;
20+
}
21+
}
22+
23+
if (otherEnumerator.MoveNext()) {
24+
// counts differ
25+
return false;
26+
}
27+
return true;
28+
}
29+
30+
public static bool CollectionEquals<TValue>(this IDictionary<string, TValue> source, IDictionary<string, TValue> other) {
31+
if (source.Count != other.Count) {
32+
return false;
33+
}
34+
35+
foreach (var key in source.Keys) {
36+
var sourceValue = source[key];
37+
38+
TValue otherValue;
39+
if (!other.TryGetValue(key, out otherValue)) {
40+
return false;
41+
}
42+
43+
if (sourceValue.Equals(otherValue)) {
44+
return false;
45+
}
46+
}
47+
return true;
48+
}
49+
50+
public static int GetCollectionHashCode<T>(this IEnumerable<T> source) {
51+
var assemblyQualifiedName = typeof(T).AssemblyQualifiedName;
52+
int hashCode = assemblyQualifiedName == null ? 0 : assemblyQualifiedName.GetHashCode();
53+
54+
foreach (var item in source) {
55+
if (item == null)
56+
continue;
57+
58+
unchecked {
59+
hashCode = (hashCode * 397) ^ item.GetHashCode();
60+
}
61+
}
62+
return hashCode;
63+
}
64+
65+
public static int GetCollectionHashCode<TValue>(this IDictionary<string, TValue> source) {
66+
var assemblyQualifiedName = typeof(TValue).AssemblyQualifiedName;
67+
int hashCode = assemblyQualifiedName == null ? 0 : assemblyQualifiedName.GetHashCode();
68+
69+
var keyValuePairHashes = new List<int>(source.Keys.Count);
70+
71+
foreach (var key in source.Keys.OrderBy(x => x)) {
72+
var item = source[key];
73+
unchecked {
74+
var kvpHash = key.GetHashCode();
75+
kvpHash = (kvpHash * 397) ^ item.GetHashCode();
76+
keyValuePairHashes.Add(kvpHash);
77+
}
78+
}
79+
80+
keyValuePairHashes.Sort();
81+
foreach (var kvpHash in keyValuePairHashes) {
82+
unchecked {
83+
hashCode = (hashCode * 397) ^ kvpHash;
84+
}
85+
}
86+
return hashCode;
87+
}
88+
}
89+
}

Source/Shared/Models/Client/Data/EnvironmentInfo.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,42 @@ public EnvironmentInfo() {
9999
/// Extended data entries for this machine environment.
100100
/// </summary>
101101
public DataDictionary Data { get; set; }
102+
103+
protected bool Equals(EnvironmentInfo other) {
104+
return ProcessorCount == other.ProcessorCount && TotalPhysicalMemory == other.TotalPhysicalMemory && AvailablePhysicalMemory == other.AvailablePhysicalMemory && string.Equals(CommandLine, other.CommandLine) && string.Equals(ProcessName, other.ProcessName) && string.Equals(ProcessId, other.ProcessId) && ProcessMemorySize == other.ProcessMemorySize && string.Equals(ThreadName, other.ThreadName) && string.Equals(ThreadId, other.ThreadId) && string.Equals(Architecture, other.Architecture) && string.Equals(OSName, other.OSName) && string.Equals(OSVersion, other.OSVersion) && string.Equals(IpAddress, other.IpAddress) && string.Equals(MachineName, other.MachineName) && string.Equals(InstallId, other.InstallId) && string.Equals(RuntimeVersion, other.RuntimeVersion) && Equals(Data, other.Data);
105+
}
106+
107+
public override bool Equals(object obj) {
108+
if (ReferenceEquals(null, obj))
109+
return false;
110+
if (ReferenceEquals(this, obj))
111+
return true;
112+
if (obj.GetType() != this.GetType())
113+
return false;
114+
return Equals((EnvironmentInfo)obj);
115+
}
116+
117+
public override int GetHashCode() {
118+
unchecked {
119+
var hashCode = ProcessorCount;
120+
hashCode = (hashCode * 397) ^ TotalPhysicalMemory.GetHashCode();
121+
hashCode = (hashCode * 397) ^ AvailablePhysicalMemory.GetHashCode();
122+
hashCode = (hashCode * 397) ^ (CommandLine == null ? 0 : CommandLine.GetHashCode());
123+
hashCode = (hashCode * 397) ^ (ProcessName == null ? 0 : ProcessName.GetHashCode());
124+
hashCode = (hashCode * 397) ^ (ProcessId == null ? 0 : ProcessId.GetHashCode());
125+
hashCode = (hashCode * 397) ^ ProcessMemorySize.GetHashCode();
126+
hashCode = (hashCode * 397) ^ (ThreadName == null ? 0 : ThreadName.GetHashCode());
127+
hashCode = (hashCode * 397) ^ (ThreadId == null ? 0 : ThreadId.GetHashCode());
128+
hashCode = (hashCode * 397) ^ (Architecture == null ? 0 : Architecture.GetHashCode());
129+
hashCode = (hashCode * 397) ^ (OSName == null ? 0 : OSName.GetHashCode());
130+
hashCode = (hashCode * 397) ^ (OSVersion == null ? 0 :OSVersion.GetHashCode());
131+
hashCode = (hashCode * 397) ^ (IpAddress == null ? 0 : IpAddress.GetHashCode());
132+
hashCode = (hashCode * 397) ^ (MachineName == null ? 0 : MachineName.GetHashCode());
133+
hashCode = (hashCode * 397) ^ (InstallId == null ? 0 : InstallId.GetHashCode());
134+
hashCode = (hashCode * 397) ^ (RuntimeVersion == null ? 0 : RuntimeVersion.GetHashCode());
135+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
136+
return hashCode;
137+
}
138+
}
102139
}
103140
}

Source/Shared/Models/Client/Data/Error.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,25 @@ public static class KnownDataKeys {
1515
public const string ExtraProperties = "@ext";
1616
public const string TargetInfo = "@target";
1717
}
18+
19+
protected bool Equals(Error other) {
20+
return base.Equals(other) && Modules.CollectionEquals(other.Modules);
21+
}
22+
23+
public override bool Equals(object obj) {
24+
if (ReferenceEquals(null, obj))
25+
return false;
26+
if (ReferenceEquals(this, obj))
27+
return true;
28+
if (obj.GetType() != this.GetType())
29+
return false;
30+
return Equals((Error)obj);
31+
}
32+
33+
public override int GetHashCode() {
34+
unchecked {
35+
return (base.GetHashCode() * 397) ^ (Modules != null ? Modules.GetCollectionHashCode() : 0);
36+
}
37+
}
1838
}
1939
}

Source/Shared/Models/Client/Data/InnerError.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,32 @@ public InnerError() {
4141
/// The target method.
4242
/// </summary>
4343
public Method TargetMethod { get; set; }
44+
45+
protected bool Equals(InnerError other) {
46+
return string.Equals(Message, other.Message) && string.Equals(Type, other.Type) && string.Equals(Code, other.Code) && Equals(Data, other.Data) && Equals(Inner, other.Inner) && StackTrace.CollectionEquals(other.StackTrace) && Equals(TargetMethod, other.TargetMethod);
47+
}
48+
49+
public override bool Equals(object obj) {
50+
if (ReferenceEquals(null, obj))
51+
return false;
52+
if (ReferenceEquals(this, obj))
53+
return true;
54+
if (obj.GetType() != this.GetType())
55+
return false;
56+
return Equals((InnerError)obj);
57+
}
58+
59+
public override int GetHashCode() {
60+
unchecked {
61+
var hashCode = Message == null ? 0 : Message.GetHashCode();
62+
hashCode = (hashCode * 397) ^ (Type == null ? 0 : Type.GetHashCode());
63+
hashCode = (hashCode * 397) ^ (Code == null ? 0 : Code.GetHashCode());
64+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
65+
hashCode = (hashCode * 397) ^ (Inner == null ? 0 : Inner.GetHashCode());
66+
hashCode = (hashCode * 397) ^ (StackTrace == null ? 0 : StackTrace.GetCollectionHashCode());
67+
hashCode = (hashCode * 397) ^ (TargetMethod == null ? 0 : TargetMethod.GetHashCode());
68+
return hashCode;
69+
}
70+
}
4471
}
4572
}

Source/Shared/Models/Client/Data/Method.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,32 @@ public Method() {
1818
public DataDictionary Data { get; set; }
1919
public GenericArguments GenericArguments { get; set; }
2020
public ParameterCollection Parameters { get; set; }
21+
22+
protected bool Equals(Method other) {
23+
return IsSignatureTarget == other.IsSignatureTarget && string.Equals(DeclaringNamespace, other.DeclaringNamespace) && string.Equals(DeclaringType, other.DeclaringType) && string.Equals(Name, other.Name) && Equals(Data, other.Data) && GenericArguments.CollectionEquals(other.GenericArguments) && Parameters.CollectionEquals(other.Parameters);
24+
}
25+
26+
public override bool Equals(object obj) {
27+
if (ReferenceEquals(null, obj))
28+
return false;
29+
if (ReferenceEquals(this, obj))
30+
return true;
31+
if (obj.GetType() != this.GetType())
32+
return false;
33+
return Equals((Method)obj);
34+
}
35+
36+
public override int GetHashCode() {
37+
unchecked {
38+
var hashCode = IsSignatureTarget.GetHashCode();
39+
hashCode = (hashCode * 397) ^ (DeclaringNamespace == null ? 0 : DeclaringNamespace.GetHashCode());
40+
hashCode = (hashCode * 397) ^ (DeclaringType == null ? 0 : DeclaringType.GetHashCode());
41+
hashCode = (hashCode * 397) ^ (Name == null ? 0 : Name.GetHashCode());
42+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
43+
hashCode = (hashCode * 397) ^ (GenericArguments == null ? 0 : GenericArguments.GetCollectionHashCode());
44+
hashCode = (hashCode * 397) ^ (Parameters == null ? 0 : Parameters.GetCollectionHashCode());
45+
return hashCode;
46+
}
47+
}
2148
}
2249
}

Source/Shared/Models/Client/Data/Module.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,32 @@ public override string ToString() {
2525

2626
return sb.ToString();
2727
}
28+
29+
protected bool Equals(Module other) {
30+
return ModuleId == other.ModuleId && string.Equals(Name, other.Name) && string.Equals(Version, other.Version) && IsEntry == other.IsEntry && CreatedDate.Equals(other.CreatedDate) && ModifiedDate.Equals(other.ModifiedDate) && Equals(Data, other.Data);
31+
}
32+
33+
public override bool Equals(object obj) {
34+
if (ReferenceEquals(null, obj))
35+
return false;
36+
if (ReferenceEquals(this, obj))
37+
return true;
38+
if (obj.GetType() != this.GetType())
39+
return false;
40+
return Equals((Module)obj);
41+
}
42+
43+
public override int GetHashCode() {
44+
unchecked {
45+
var hashCode = ModuleId;
46+
hashCode = (hashCode * 397) ^ (Name == null ? 0 : Name.GetHashCode());
47+
hashCode = (hashCode * 397) ^ (Version == null ? 0 : Version.GetHashCode());
48+
hashCode = (hashCode * 397) ^ IsEntry.GetHashCode();
49+
hashCode = (hashCode * 397) ^ CreatedDate.GetHashCode();
50+
hashCode = (hashCode * 397) ^ ModifiedDate.GetHashCode();
51+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
52+
return hashCode;
53+
}
54+
}
2855
}
2956
}

Source/Shared/Models/Client/Data/Parameter.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,30 @@ public Parameter() {
1313

1414
public DataDictionary Data { get; set; }
1515
public GenericArguments GenericArguments { get; set; }
16+
17+
protected bool Equals(Parameter other) {
18+
return string.Equals(Name, other.Name) && string.Equals(Type, other.Type) && string.Equals(TypeNamespace, other.TypeNamespace) && Equals(Data, other.Data) && GenericArguments.CollectionEquals(other.GenericArguments);
19+
}
20+
21+
public override bool Equals(object obj) {
22+
if (ReferenceEquals(null, obj))
23+
return false;
24+
if (ReferenceEquals(this, obj))
25+
return true;
26+
if (obj.GetType() != this.GetType())
27+
return false;
28+
return Equals((Parameter)obj);
29+
}
30+
31+
public override int GetHashCode() {
32+
unchecked {
33+
var hashCode = Name == null ? 0 : Name.GetHashCode();
34+
hashCode = (hashCode * 397) ^ (Type == null ? 0 : Type.GetHashCode());
35+
hashCode = (hashCode * 397) ^ (TypeNamespace == null ? 0 : TypeNamespace.GetHashCode());
36+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
37+
hashCode = (hashCode * 397) ^ (GenericArguments == null ? 0 : GenericArguments.GetCollectionHashCode());
38+
return hashCode;
39+
}
40+
}
1641
}
1742
}

Source/Shared/Models/Client/Data/RequestInfo.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,37 @@ public RequestInfo() {
6969
/// </summary>
7070
public DataDictionary Data { get; set; }
7171

72+
protected bool Equals(RequestInfo other) {
73+
return string.Equals(UserAgent, other.UserAgent) && string.Equals(HttpMethod, other.HttpMethod) && IsSecure == other.IsSecure && string.Equals(Host, other.Host) && Port == other.Port && string.Equals(Path, other.Path) && string.Equals(Referrer, other.Referrer) && string.Equals(ClientIpAddress, other.ClientIpAddress) && Cookies.CollectionEquals(other.Cookies) && QueryString.CollectionEquals(other.QueryString) && Equals(Data, other.Data);
74+
}
75+
76+
public override bool Equals(object obj) {
77+
if (ReferenceEquals(null, obj))
78+
return false;
79+
if (ReferenceEquals(this, obj))
80+
return true;
81+
if (obj.GetType() != this.GetType())
82+
return false;
83+
return Equals((RequestInfo)obj);
84+
}
85+
86+
public override int GetHashCode() {
87+
unchecked {
88+
var hashCode = UserAgent == null ? 0 : UserAgent.GetHashCode();
89+
hashCode = (hashCode * 397) ^ (HttpMethod == null ? 0 : HttpMethod.GetHashCode());
90+
hashCode = (hashCode * 397) ^ IsSecure.GetHashCode();
91+
hashCode = (hashCode * 397) ^ (Host == null ? 0 : Host.GetHashCode());
92+
hashCode = (hashCode * 397) ^ Port;
93+
hashCode = (hashCode * 397) ^ (Path == null ? 0 : Path.GetHashCode());
94+
hashCode = (hashCode * 397) ^ (Referrer == null ? 0 : Referrer.GetHashCode());
95+
hashCode = (hashCode * 397) ^ (ClientIpAddress == null ? 0 : ClientIpAddress.GetHashCode());
96+
hashCode = (hashCode * 397) ^ (Cookies == null ? 0 : Cookies.GetCollectionHashCode());
97+
hashCode = (hashCode * 397) ^ (QueryString == null ? 0 : QueryString.GetCollectionHashCode());
98+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
99+
return hashCode;
100+
}
101+
}
102+
72103
public static class KnownDataKeys {
73104
public const string Browser = "@browser";
74105
public const string BrowserVersion = "@browser_version";

Source/Shared/Models/Client/Data/SimpleError.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ public SimpleError() {
3131
/// </summary>
3232
public SimpleError Inner { get; set; }
3333

34+
protected bool Equals(SimpleError other) {
35+
return string.Equals(Message, other.Message) && string.Equals(Type, other.Type) && string.Equals(StackTrace, other.StackTrace) && Equals(Data, other.Data) && Equals(Inner, other.Inner);
36+
}
37+
38+
public override bool Equals(object obj) {
39+
if (ReferenceEquals(null, obj))
40+
return false;
41+
if (ReferenceEquals(this, obj))
42+
return true;
43+
if (obj.GetType() != this.GetType())
44+
return false;
45+
return Equals((SimpleError)obj);
46+
}
47+
48+
public override int GetHashCode() {
49+
unchecked {
50+
var hashCode = Message == null ? 0 : Message.GetHashCode();
51+
hashCode = (hashCode * 397) ^ (Type == null ? 0 : Type.GetHashCode());
52+
hashCode = (hashCode * 397) ^ (StackTrace == null ? 0 : StackTrace.GetHashCode());
53+
hashCode = (hashCode * 397) ^ (Data == null ? 0 : Data.GetHashCode());
54+
hashCode = (hashCode * 397) ^ (Inner == null ? 0 : Inner.GetHashCode());
55+
return hashCode;
56+
}
57+
}
58+
3459
public static class KnownDataKeys {
3560
public const string ExtraProperties = "@ext";
3661
}

0 commit comments

Comments
 (0)