From 1fb4e4e0879ba4f76ba5f21f197979be72ad1e41 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 19 Feb 2020 08:51:04 +1000 Subject: [PATCH 01/38] Dev version bump [skip ci] --- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index 0d5d6b2..914937a 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -14,8 +14,8 @@ https://github.com/serilog/serilog-sinks-raygun serilog sink raygun Copyright © Serilog Contributors 2017-2019 - Serilog event sink that writes to the Raygun.io service. - 4.0.0 + Serilog event sink that writes to the Raygun.io service. + 4.0.1 4.0.0.0 4.0.0.0 From 9f2411dd2dd01ba64d6f84bcc5798241d6b0a41b Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Wed, 5 Aug 2020 15:42:13 +1200 Subject: [PATCH 02/38] Implement RaygunIdentifierMessage support --- .../LoggerConfigurationRaygunExtensions.cs | 5 +- .../Sinks/Raygun/RaygunSink.cs | 70 ++++++++++++++++++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs index 8e68722..6a7cd89 100644 --- a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs +++ b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs @@ -53,7 +53,8 @@ public static LoggerConfiguration Raygun( IEnumerable tags = null, IEnumerable ignoredFormFieldNames = null, string groupKeyProperty = "GroupKey", - string tagsProperty = "Tags") + string tagsProperty = "Tags", + string userInfoProperty = null) { if (loggerConfiguration == null) throw new ArgumentNullException("loggerConfiguration"); @@ -61,7 +62,7 @@ public static LoggerConfiguration Raygun( throw new ArgumentNullException("applicationKey"); return loggerConfiguration.Sink( - new RaygunSink(formatProvider, applicationKey, wrapperExceptions, userNameProperty, applicationVersionProperty, tags, ignoredFormFieldNames, groupKeyProperty, tagsProperty), + new RaygunSink(formatProvider, applicationKey, wrapperExceptions, userNameProperty, applicationVersionProperty, tags, ignoredFormFieldNames, groupKeyProperty, tagsProperty, userInfoProperty), restrictedToMinimumLevel); } } diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 0817f29..fabf2b4 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -39,6 +39,7 @@ public class RaygunSink : ILogEventSink readonly IEnumerable _ignoredFormFieldNames; readonly string _groupKeyProperty; readonly string _tagsProperty; + readonly string _userInfoProperty; readonly RaygunClient _client; /// @@ -61,7 +62,8 @@ public RaygunSink(IFormatProvider formatProvider, IEnumerable tags = null, IEnumerable ignoredFormFieldNames = null, string groupKeyProperty = "GroupKey", - string tagsProperty = "Tags") + string tagsProperty = "Tags", + string userInfoProperty = null) { if (string.IsNullOrEmpty(applicationKey)) throw new ArgumentNullException("applicationKey"); @@ -73,6 +75,7 @@ public RaygunSink(IFormatProvider formatProvider, _ignoredFormFieldNames = ignoredFormFieldNames ?? Enumerable.Empty(); _groupKeyProperty = groupKeyProperty; _tagsProperty = tagsProperty; + _userInfoProperty = userInfoProperty; _client = new RaygunClient(applicationKey); if (wrapperExceptions != null) @@ -108,12 +111,24 @@ public void Emit(LogEvent logEvent) : new RaygunErrorMessage() { ClassName = logEvent.MessageTemplate.Text, - Message = logEvent.MessageTemplate.Text, + Message = logEvent.MessageTemplate.Text, Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()) }; // Add user when requested - if (!string.IsNullOrWhiteSpace(_userNameProperty) && + if (!string.IsNullOrWhiteSpace(_userInfoProperty) && + logEvent.Properties.ContainsKey(_userInfoProperty) && + logEvent.Properties[_userInfoProperty] != null) + { + var userInfoScalar = logEvent.Properties[_userInfoProperty] as ScalarValue; + if (userInfoScalar != null && userInfoScalar.Value is string) + { + raygunMessage.Details.User = ParseUserInformation((string)userInfoScalar.Value); + } + } + + if (raygunMessage.Details.User == null && + !string.IsNullOrWhiteSpace(_userNameProperty) && logEvent.Properties.ContainsKey(_userNameProperty) && logEvent.Properties[_userNameProperty] != null) { @@ -148,5 +163,54 @@ public void Emit(LogEvent logEvent) // Submit _client.SendInBackground(raygunMessage); } + + private static RaygunIdentifierMessage ParseUserInformation(string userInfo) + { + RaygunIdentifierMessage result = null; + + // This is a parse of the ToString implementation of RaygunIdentifierMessage which uses the format: + // [RaygunIdentifierMessage: Identifier=X, IsAnonymous=X, Email=X, FullName=X, FirstName=X, UUID=X] + string[] properties = userInfo.Split(new[] {',', ']'}, StringSplitOptions.RemoveEmptyEntries); + if (properties.Length == 6) + { + string[] identifierSplit = properties[0].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (identifierSplit.Length == 2) + { + result = new RaygunIdentifierMessage(identifierSplit[1]); + + string[] isAnonymousSplit = properties[1].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (isAnonymousSplit.Length == 2) + { + result.IsAnonymous = "True".Equals(isAnonymousSplit[1]); + } + + string[] emailSplit = properties[2].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (emailSplit.Length == 2) + { + result.Email = emailSplit[1]; + } + + string[] fullNameSplit = properties[3].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (fullNameSplit.Length == 2) + { + result.FullName = fullNameSplit[1]; + } + + string[] firstNameSplit = properties[4].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (firstNameSplit.Length == 2) + { + result.FirstName = firstNameSplit[1]; + } + + string[] uuidSplit = properties[5].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (uuidSplit.Length == 2) + { + result.UUID = uuidSplit[1]; + } + } + } + + return result; + } } } From fca7e48a782aa3f1c8f414473aa3b2e3974ba393 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Wed, 5 Aug 2020 16:37:06 +1200 Subject: [PATCH 03/38] Documentation --- README.md | 23 ++++++++++++++++++- .../Sinks/Raygun/RaygunSink.cs | 3 ++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5645d80..846de3b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ Log.Logger = new LoggerConfiguration() new[] { "globalTag1", "globalTag2" }, new[] { "ignoreField1", "ignoreField2" }, "CustomGroupKeyProperty", - "CustomTagsProperty") + "CustomTagsProperty", + "CustomUserInfoProperty") .CreateLogger(); ``` ### Required @@ -86,4 +87,24 @@ Log.ForContext("CustomGroupKeyProperty", "TransactionId-12345").Error(new Except ```csharp Log.ForContext("CustomTagsProperty", new[] {"tag1", "tag2"}).Error(new Exception("random error"), "other information"); Log.Error(new Exception("random error"), "other information {@CustomTagsProperty}", new[] {"tag3", "tag4"}); +``` + +#### userInfoProperty +`type: string` + +`default: null` + +This is null by default, so you need to configure the userInfoProperty name if you want to log more user information in this way. This will cause the RaygunIdentifierMessage to be included in the "User" section of the Raygun payload, allowing the information to be picked up by the "Users" section of the Raygun service. This will not happen if the RaygunIdentifierMessage is destructured into the log message. Sending user information in this way will overwrite the use of the userNameProperty. + +The user identifier passed into the RaygunIdentifierMessage constructor could be the users name, email address, database id or whatever works best for you to identify unique users. + +```csharp +var userInfo = new RaygunIdentifierMessage("12345") +{ + FirstName = "John", + FullName = "John Doe", + Email = "johndoe@email.address" +}; + +Log.ForContext("CustomUserInfoProperty", userInfo).Error(new Exception("random error"), "other information"); ``` \ No newline at end of file diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index fabf2b4..d021c10 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -53,7 +53,8 @@ public class RaygunSink : ILogEventSink /// Specifies the tags to include with every log message. The log level will always be included as a tag. /// Specifies the form field names which to ignore when including request form data. /// The property containing the custom group key for the Raygun message. - /// The property where additional tags are stored when emitting log events + /// The property where additional tags are stored when emitting log events. + /// The property where a RaygunIdentifierMessage with more user information can optionally be provided. public RaygunSink(IFormatProvider formatProvider, string applicationKey, IEnumerable wrapperExceptions = null, From 6b9ad4974edb8e39db358ff679904f96bcb7f65f Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Wed, 5 Aug 2020 16:49:15 +1200 Subject: [PATCH 04/38] Since the RaygunIdentifierMessage is included in the payload, we don't need to keep it in the custom data dictionary --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index d021c10..a2e9ad2 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -125,6 +125,10 @@ public void Emit(LogEvent logEvent) if (userInfoScalar != null && userInfoScalar.Value is string) { raygunMessage.Details.User = ParseUserInformation((string)userInfoScalar.Value); + if (raygunMessage.Details.User != null) + { + properties.Remove(_userInfoProperty); + } } } From 586dd8fd0310f18c278034d6d82e44e7ac2caed3 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 7 Aug 2020 14:49:30 +1200 Subject: [PATCH 05/38] Remove duplicate data from UserCustomData --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 0817f29..972f86a 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -118,6 +118,8 @@ public void Emit(LogEvent logEvent) logEvent.Properties[_userNameProperty] != null) { raygunMessage.Details.User = new RaygunIdentifierMessage(logEvent.Properties[_userNameProperty].ToString()); + + properties.Remove(_userNameProperty); } // Add version when requested @@ -126,25 +128,34 @@ public void Emit(LogEvent logEvent) logEvent.Properties[_applicationVersionProperty] != null) { raygunMessage.Details.Version = logEvent.Properties[_applicationVersionProperty].ToString("l", null); + + properties.Remove(_applicationVersionProperty); } // Build up the rest of the message raygunMessage.Details.Environment = new RaygunEnvironmentMessage(); raygunMessage.Details.Tags = tags; - raygunMessage.Details.UserCustomData = properties; raygunMessage.Details.MachineName = Environment.MachineName; // Add the custom group key when provided if (properties.TryGetValue(_groupKeyProperty, out var customKey)) + { raygunMessage.Details.GroupingKey = customKey.ToString(); + properties.Remove(_groupKeyProperty); + } + // Add additional custom tags if (properties.TryGetValue(_tagsProperty, out var eventTags) && eventTags is object[]) { foreach (var tag in (object[])eventTags) raygunMessage.Details.Tags.Add(tag.ToString()); + + properties.Remove(_tagsProperty); } + raygunMessage.Details.UserCustomData = properties; + // Submit _client.SendInBackground(raygunMessage); } From 1e107217f81909a40c510bd0e8103602581bed9c Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 7 Aug 2020 16:30:30 +1200 Subject: [PATCH 06/38] Added the RaygunClientMessage --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 0817f29..e689da5 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using Mindscape.Raygun4Net; #if NETSTANDARD2_0 using Mindscape.Raygun4Net.AspNetCore; @@ -133,6 +134,13 @@ public void Emit(LogEvent logEvent) raygunMessage.Details.Tags = tags; raygunMessage.Details.UserCustomData = properties; raygunMessage.Details.MachineName = Environment.MachineName; + + raygunMessage.Details.Client = new RaygunClientMessage() + { + Name = "RaygunSerilogSink", + Version = new AssemblyName(this.GetType().Assembly.FullName).Version.ToString(), + ClientUrl = "https://github.com/serilog/serilog-sinks-raygun" + }; // Add the custom group key when provided if (properties.TryGetValue(_groupKeyProperty, out var customKey)) From 21a848c89e85c3a85b854c9321ded2aebaf62ad7 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 7 Aug 2020 17:26:40 +1200 Subject: [PATCH 07/38] Populate the environment section --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 0817f29..cc6255f 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -129,7 +129,11 @@ public void Emit(LogEvent logEvent) } // Build up the rest of the message - raygunMessage.Details.Environment = new RaygunEnvironmentMessage(); +#if NETSTANDARD2_0 + raygunMessage.Details.Environment = RaygunEnvironmentMessageBuilder.Build(new RaygunSettings()); +#else + raygunMessage.Details.Environment = RaygunEnvironmentMessageBuilder.Build(); +#endif raygunMessage.Details.Tags = tags; raygunMessage.Details.UserCustomData = properties; raygunMessage.Details.MachineName = Environment.MachineName; From 7ef1986ace4f466e0ba0c9499434ee12723202fd Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 10 Aug 2020 17:08:31 +1000 Subject: [PATCH 08/38] Update NuGet.org publishing key --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 0aca527..bbc8551 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: eY0pNgTWxzEUVfkitD3R/g5Qfg2GVLYdiJiyvnwfiOLBd2FMRRrJKD89j8XMeK9A + secure: K3/810hkTO6rd2AEHVkUQAadjGmDREus9k96QHu6hxrA1/wRTuAJemHMKtVVgIvf skip_symbols: true on: branch: /^(master|dev)$/ From b2e9b24b3caf61c0bf42e7f1088a1edb36f3541f Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 11 Aug 2020 16:40:52 +1200 Subject: [PATCH 09/38] Add support for destructured RaygunIdentifierMessage values --- .../Sinks/Raygun/RaygunSink.cs | 68 +++++++++++++++---- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index a2e9ad2..d818907 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -121,15 +121,24 @@ public void Emit(LogEvent logEvent) logEvent.Properties.ContainsKey(_userInfoProperty) && logEvent.Properties[_userInfoProperty] != null) { - var userInfoScalar = logEvent.Properties[_userInfoProperty] as ScalarValue; - if (userInfoScalar != null && userInfoScalar.Value is string) + var userInfoStructure = logEvent.Properties[_userInfoProperty] as StructureValue; + if (userInfoStructure != null) { - raygunMessage.Details.User = ParseUserInformation((string)userInfoScalar.Value); - if (raygunMessage.Details.User != null) + raygunMessage.Details.User = BuildUserInformationFromStructureValue(userInfoStructure); + } + else + { + var userInfoScalar = logEvent.Properties[_userInfoProperty] as ScalarValue; + if (userInfoScalar != null && userInfoScalar.Value is string) { - properties.Remove(_userInfoProperty); + raygunMessage.Details.User = ParseUserInformation((string) userInfoScalar.Value); } } + + if (raygunMessage.Details.User != null) + { + properties.Remove(_userInfoProperty); + } } if (raygunMessage.Details.User == null && @@ -169,9 +178,42 @@ public void Emit(LogEvent logEvent) _client.SendInBackground(raygunMessage); } + private static RaygunIdentifierMessage BuildUserInformationFromStructureValue(StructureValue userStructure) + { + RaygunIdentifierMessage userIdentifier = new RaygunIdentifierMessage(null); + + foreach (var property in userStructure.Properties) + { + ScalarValue scalar = property.Value as ScalarValue; + switch (property.Name) + { + case nameof(RaygunIdentifierMessage.Identifier): + userIdentifier.Identifier = scalar?.Value != null ? property.Value.ToString("l", null) : null; + break; + case nameof(RaygunIdentifierMessage.IsAnonymous): + userIdentifier.IsAnonymous = "True".Equals(property.Value.ToString()); + break; + case nameof(RaygunIdentifierMessage.Email): + userIdentifier.Email = scalar?.Value != null ? property.Value.ToString("l", null) : null; + break; + case nameof(RaygunIdentifierMessage.FullName): + userIdentifier.FullName = scalar?.Value != null ? property.Value.ToString("l", null) : null; + break; + case nameof(RaygunIdentifierMessage.FirstName): + userIdentifier.FirstName = scalar?.Value != null ? property.Value.ToString("l", null) : null; + break; + case nameof(RaygunIdentifierMessage.UUID): + userIdentifier.UUID = scalar?.Value != null ? property.Value.ToString("l", null) : null; + break; + } + } + + return userIdentifier; + } + private static RaygunIdentifierMessage ParseUserInformation(string userInfo) { - RaygunIdentifierMessage result = null; + RaygunIdentifierMessage userIdentifier = null; // This is a parse of the ToString implementation of RaygunIdentifierMessage which uses the format: // [RaygunIdentifierMessage: Identifier=X, IsAnonymous=X, Email=X, FullName=X, FirstName=X, UUID=X] @@ -181,41 +223,41 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) string[] identifierSplit = properties[0].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (identifierSplit.Length == 2) { - result = new RaygunIdentifierMessage(identifierSplit[1]); + userIdentifier = new RaygunIdentifierMessage(identifierSplit[1]); string[] isAnonymousSplit = properties[1].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (isAnonymousSplit.Length == 2) { - result.IsAnonymous = "True".Equals(isAnonymousSplit[1]); + userIdentifier.IsAnonymous = "True".Equals(isAnonymousSplit[1]); } string[] emailSplit = properties[2].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (emailSplit.Length == 2) { - result.Email = emailSplit[1]; + userIdentifier.Email = emailSplit[1]; } string[] fullNameSplit = properties[3].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (fullNameSplit.Length == 2) { - result.FullName = fullNameSplit[1]; + userIdentifier.FullName = fullNameSplit[1]; } string[] firstNameSplit = properties[4].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (firstNameSplit.Length == 2) { - result.FirstName = firstNameSplit[1]; + userIdentifier.FirstName = firstNameSplit[1]; } string[] uuidSplit = properties[5].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); if (uuidSplit.Length == 2) { - result.UUID = uuidSplit[1]; + userIdentifier.UUID = uuidSplit[1]; } } } - return result; + return userIdentifier; } } } From b89c0d7908188f14880e5ef0fea07f4fdf3bdf75 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 11 Aug 2020 16:47:25 +1200 Subject: [PATCH 10/38] Updated readme based on latest change --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 846de3b..2df0ca7 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Log.Error(new Exception("random error"), "other information {@CustomTagsProperty `default: null` -This is null by default, so you need to configure the userInfoProperty name if you want to log more user information in this way. This will cause the RaygunIdentifierMessage to be included in the "User" section of the Raygun payload, allowing the information to be picked up by the "Users" section of the Raygun service. This will not happen if the RaygunIdentifierMessage is destructured into the log message. Sending user information in this way will overwrite the use of the userNameProperty. +This is null by default, so you need to configure the userInfoProperty name if you want to log more user information in this way. This will cause the provided RaygunIdentifierMessage to be included in the "User" section of the Raygun payload, allowing the information to be picked up by the "Users" section of the Raygun service. It's recommended to destructure the RaygunIdentifierMessage, but this feature will still work if you don't. Sending user information in this way will overwrite the use of the userNameProperty. The user identifier passed into the RaygunIdentifierMessage constructor could be the users name, email address, database id or whatever works best for you to identify unique users. @@ -106,5 +106,5 @@ var userInfo = new RaygunIdentifierMessage("12345") Email = "johndoe@email.address" }; -Log.ForContext("CustomUserInfoProperty", userInfo).Error(new Exception("random error"), "other information"); +Log.ForContext("CustomUserInfoProperty", userInfo, true).Error(new Exception("random error"), "other information"); ``` \ No newline at end of file From 613e67a4610a059466ad2b65c0a10bd90b431920 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 11 Aug 2020 16:50:21 +1200 Subject: [PATCH 11/38] Replaced a tab with whitespace --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2df0ca7..33b56ab 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Log.Logger = new LoggerConfiguration() new[] { "ignoreField1", "ignoreField2" }, "CustomGroupKeyProperty", "CustomTagsProperty", - "CustomUserInfoProperty") + "CustomUserInfoProperty") .CreateLogger(); ``` ### Required From 6fe938aa578b38a05e07769fd733a87184c01284 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 11 Aug 2020 17:10:44 +1200 Subject: [PATCH 12/38] Minor whitespace removal --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 90c6677..2a443ce 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -97,7 +97,7 @@ public void Emit(LogEvent logEvent) .Select(pv => new { Name = pv.Key, Value = RaygunPropertyFormatter.Simplify(pv.Value) }) .ToDictionary(a => a.Name, b => b.Value); - // Add the message + // Add the message properties.Add("RenderedLogMessage", logEvent.RenderMessage(_formatProvider)); properties.Add("LogMessageTemplate", logEvent.MessageTemplate.Text); @@ -170,7 +170,7 @@ public void Emit(LogEvent logEvent) #endif raygunMessage.Details.Tags = tags; raygunMessage.Details.MachineName = Environment.MachineName; - + raygunMessage.Details.Client = new RaygunClientMessage() { Name = "RaygunSerilogSink", From 3b7828583e923da9427ad4bf162ef75be64470a9 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 14 Aug 2020 17:02:55 +1200 Subject: [PATCH 13/38] Code tidy ups --- .../Sinks/Raygun/RaygunSink.cs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 2a443ce..abe2c35 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -119,21 +119,17 @@ public void Emit(LogEvent logEvent) // Add user when requested if (!string.IsNullOrWhiteSpace(_userInfoProperty) && - logEvent.Properties.ContainsKey(_userInfoProperty) && - logEvent.Properties[_userInfoProperty] != null) + logEvent.Properties.TryGetValue(_userInfoProperty, out var userInfoPropertyValue) && + userInfoPropertyValue != null) { - var userInfoStructure = logEvent.Properties[_userInfoProperty] as StructureValue; - if (userInfoStructure != null) + switch (userInfoPropertyValue) { - raygunMessage.Details.User = BuildUserInformationFromStructureValue(userInfoStructure); - } - else - { - var userInfoScalar = logEvent.Properties[_userInfoProperty] as ScalarValue; - if (userInfoScalar != null && userInfoScalar.Value is string) - { - raygunMessage.Details.User = ParseUserInformation((string) userInfoScalar.Value); - } + case StructureValue userInfoStructure: + raygunMessage.Details.User = BuildUserInformationFromStructureValue(userInfoStructure); + break; + case ScalarValue userInfoScalar when userInfoScalar.Value is string userInfo: + raygunMessage.Details.User = ParseUserInformation(userInfo); + break; } if (raygunMessage.Details.User != null) From 8036c74102185422439bc1a5d582c99c1189f870 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Sun, 30 Aug 2020 21:27:18 +1200 Subject: [PATCH 14/38] Attach current stack if exception is null --- .../Sinks/Raygun/RaygunSink.cs | 108 +++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index abe2c35..31fb290 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -14,8 +14,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Text; using Mindscape.Raygun4Net; #if NETSTANDARD2_0 using Mindscape.Raygun4Net.AspNetCore; @@ -114,7 +116,8 @@ public void Emit(LogEvent logEvent) { ClassName = logEvent.MessageTemplate.Text, Message = logEvent.MessageTemplate.Text, - Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()) + Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), + StackTrace = BuildStackTrace(new StackTrace()) }; // Add user when requested @@ -278,5 +281,108 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) return userIdentifier; } + + private static RaygunErrorStackTraceLineMessage[] BuildStackTrace(StackTrace stackTrace) + { + var lines = new List(); + + var frames = stackTrace.GetFrames(); + + if (frames == null || frames.Length == 0) + { + var line = new RaygunErrorStackTraceLineMessage { FileName = "none", LineNumber = 0 }; + lines.Add(line); + return lines.ToArray(); + } + + foreach (StackFrame frame in frames) + { + MethodBase method = frame.GetMethod(); + + if (method != null) + { + int lineNumber = frame.GetFileLineNumber(); + + if (lineNumber == 0) + { + lineNumber = frame.GetILOffset(); + } + + var methodName = GenerateMethodName(method); + + string file = frame.GetFileName(); + + string className = method.ReflectedType != null ? method.ReflectedType.FullName : "(unknown)"; + + var line = new RaygunErrorStackTraceLineMessage + { + FileName = file, + LineNumber = lineNumber, + MethodName = methodName, + ClassName = className + }; + + lines.Add(line); + } + } + + return lines.ToArray(); + } + + private static string GenerateMethodName(MethodBase method) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.Append(method.Name); + + bool first = true; + if (method is MethodInfo && method.IsGenericMethod) + { + Type[] genericArguments = method.GetGenericArguments(); + stringBuilder.Append("["); + for (int i = 0; i < genericArguments.Length; i++) + { + if (!first) + { + stringBuilder.Append(","); + } + else + { + first = false; + } + + stringBuilder.Append(genericArguments[i].Name); + } + + stringBuilder.Append("]"); + } + + stringBuilder.Append("("); + ParameterInfo[] parameters = method.GetParameters(); + first = true; + for (int i = 0; i < parameters.Length; ++i) + { + if (!first) + { + stringBuilder.Append(", "); + } + else + { + first = false; + } + + string type = ""; + if (parameters[i].ParameterType != null) + { + type = parameters[i].ParameterType.Name; + } + + stringBuilder.Append(type + " " + parameters[i].Name); + } + + stringBuilder.Append(")"); + + return stringBuilder.ToString(); + } } } From bad8f89ad306406059fcbb2f8a82cd96e98b3ce4 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Sun, 30 Aug 2020 21:28:32 +1200 Subject: [PATCH 15/38] Use formatted message instead of template when exception is null --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 31fb290..6620722 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -115,7 +115,7 @@ public void Emit(LogEvent logEvent) : new RaygunErrorMessage() { ClassName = logEvent.MessageTemplate.Text, - Message = logEvent.MessageTemplate.Text, + Message = logEvent.RenderMessage(_formatProvider), Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), StackTrace = BuildStackTrace(new StackTrace()) }; From 26960f67ce15bf08f78e12b76037793e634c2610 Mon Sep 17 00:00:00 2001 From: Benjamin Sampica Date: Sun, 30 Aug 2020 18:54:14 -0500 Subject: [PATCH 16/38] Modify sending to RayGun based on severity level. --- .../Sinks/Raygun/RaygunSink.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index abe2c35..16ad8ba 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -194,7 +194,14 @@ public void Emit(LogEvent logEvent) raygunMessage.Details.UserCustomData = properties; // Submit - _client.SendInBackground(raygunMessage); + if (logEvent.Level == LogEventLevel.Fatal) + { + _client.Send(raygunMessage); + } + else + { + _client.SendInBackground(raygunMessage); + } } private static RaygunIdentifierMessage BuildUserInformationFromStructureValue(StructureValue userStructure) @@ -236,39 +243,39 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) // This is a parse of the ToString implementation of RaygunIdentifierMessage which uses the format: // [RaygunIdentifierMessage: Identifier=X, IsAnonymous=X, Email=X, FullName=X, FirstName=X, UUID=X] - string[] properties = userInfo.Split(new[] {',', ']'}, StringSplitOptions.RemoveEmptyEntries); + string[] properties = userInfo.Split(new[] { ',', ']' }, StringSplitOptions.RemoveEmptyEntries); if (properties.Length == 6) { - string[] identifierSplit = properties[0].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] identifierSplit = properties[0].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (identifierSplit.Length == 2) { userIdentifier = new RaygunIdentifierMessage(identifierSplit[1]); - string[] isAnonymousSplit = properties[1].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] isAnonymousSplit = properties[1].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (isAnonymousSplit.Length == 2) { userIdentifier.IsAnonymous = "True".Equals(isAnonymousSplit[1]); } - string[] emailSplit = properties[2].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] emailSplit = properties[2].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (emailSplit.Length == 2) { userIdentifier.Email = emailSplit[1]; } - string[] fullNameSplit = properties[3].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] fullNameSplit = properties[3].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (fullNameSplit.Length == 2) { userIdentifier.FullName = fullNameSplit[1]; } - string[] firstNameSplit = properties[4].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] firstNameSplit = properties[4].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (firstNameSplit.Length == 2) { userIdentifier.FirstName = firstNameSplit[1]; } - string[] uuidSplit = properties[5].Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries); + string[] uuidSplit = properties[5].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (uuidSplit.Length == 2) { userIdentifier.UUID = uuidSplit[1]; From b5dc60afe3adbdee8e5ef547e0287c21ccf828b2 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Sun, 30 Aug 2020 21:27:18 +1200 Subject: [PATCH 17/38] Attach current stack if exception is null --- .../Sinks/Raygun/RaygunSink.cs | 108 +++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 16ad8ba..e2a061b 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -14,8 +14,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Text; using Mindscape.Raygun4Net; #if NETSTANDARD2_0 using Mindscape.Raygun4Net.AspNetCore; @@ -114,7 +116,8 @@ public void Emit(LogEvent logEvent) { ClassName = logEvent.MessageTemplate.Text, Message = logEvent.MessageTemplate.Text, - Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()) + Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), + StackTrace = BuildStackTrace(new StackTrace()) }; // Add user when requested @@ -285,5 +288,108 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) return userIdentifier; } + + private static RaygunErrorStackTraceLineMessage[] BuildStackTrace(StackTrace stackTrace) + { + var lines = new List(); + + var frames = stackTrace.GetFrames(); + + if (frames == null || frames.Length == 0) + { + var line = new RaygunErrorStackTraceLineMessage { FileName = "none", LineNumber = 0 }; + lines.Add(line); + return lines.ToArray(); + } + + foreach (StackFrame frame in frames) + { + MethodBase method = frame.GetMethod(); + + if (method != null) + { + int lineNumber = frame.GetFileLineNumber(); + + if (lineNumber == 0) + { + lineNumber = frame.GetILOffset(); + } + + var methodName = GenerateMethodName(method); + + string file = frame.GetFileName(); + + string className = method.ReflectedType != null ? method.ReflectedType.FullName : "(unknown)"; + + var line = new RaygunErrorStackTraceLineMessage + { + FileName = file, + LineNumber = lineNumber, + MethodName = methodName, + ClassName = className + }; + + lines.Add(line); + } + } + + return lines.ToArray(); + } + + private static string GenerateMethodName(MethodBase method) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.Append(method.Name); + + bool first = true; + if (method is MethodInfo && method.IsGenericMethod) + { + Type[] genericArguments = method.GetGenericArguments(); + stringBuilder.Append("["); + for (int i = 0; i < genericArguments.Length; i++) + { + if (!first) + { + stringBuilder.Append(","); + } + else + { + first = false; + } + + stringBuilder.Append(genericArguments[i].Name); + } + + stringBuilder.Append("]"); + } + + stringBuilder.Append("("); + ParameterInfo[] parameters = method.GetParameters(); + first = true; + for (int i = 0; i < parameters.Length; ++i) + { + if (!first) + { + stringBuilder.Append(", "); + } + else + { + first = false; + } + + string type = ""; + if (parameters[i].ParameterType != null) + { + type = parameters[i].ParameterType.Name; + } + + stringBuilder.Append(type + " " + parameters[i].Name); + } + + stringBuilder.Append(")"); + + return stringBuilder.ToString(); + } } } From a24999c6f77d6b5e657234955ec3a6d886c9da2e Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Sun, 30 Aug 2020 21:28:32 +1200 Subject: [PATCH 18/38] Use formatted message instead of template when exception is null --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index e2a061b..f648963 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -115,7 +115,7 @@ public void Emit(LogEvent logEvent) : new RaygunErrorMessage() { ClassName = logEvent.MessageTemplate.Text, - Message = logEvent.MessageTemplate.Text, + Message = logEvent.RenderMessage(_formatProvider), Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), StackTrace = BuildStackTrace(new StackTrace()) }; From fcdd09c27fddb6d1681ba072abd6f0ec8e92befe Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 29 Sep 2020 15:02:56 +1300 Subject: [PATCH 19/38] Use exposed BuildStackTrace method from Raygun4Net --- .../Sinks/Raygun/RaygunSink.cs | 105 +----------------- 1 file changed, 1 insertion(+), 104 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index f648963..63ac46b 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -117,7 +117,7 @@ public void Emit(LogEvent logEvent) ClassName = logEvent.MessageTemplate.Text, Message = logEvent.RenderMessage(_formatProvider), Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), - StackTrace = BuildStackTrace(new StackTrace()) + StackTrace = RaygunErrorMessageBuilder.BuildStackTrace(new StackTrace()) }; // Add user when requested @@ -288,108 +288,5 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) return userIdentifier; } - - private static RaygunErrorStackTraceLineMessage[] BuildStackTrace(StackTrace stackTrace) - { - var lines = new List(); - - var frames = stackTrace.GetFrames(); - - if (frames == null || frames.Length == 0) - { - var line = new RaygunErrorStackTraceLineMessage { FileName = "none", LineNumber = 0 }; - lines.Add(line); - return lines.ToArray(); - } - - foreach (StackFrame frame in frames) - { - MethodBase method = frame.GetMethod(); - - if (method != null) - { - int lineNumber = frame.GetFileLineNumber(); - - if (lineNumber == 0) - { - lineNumber = frame.GetILOffset(); - } - - var methodName = GenerateMethodName(method); - - string file = frame.GetFileName(); - - string className = method.ReflectedType != null ? method.ReflectedType.FullName : "(unknown)"; - - var line = new RaygunErrorStackTraceLineMessage - { - FileName = file, - LineNumber = lineNumber, - MethodName = methodName, - ClassName = className - }; - - lines.Add(line); - } - } - - return lines.ToArray(); - } - - private static string GenerateMethodName(MethodBase method) - { - var stringBuilder = new StringBuilder(); - - stringBuilder.Append(method.Name); - - bool first = true; - if (method is MethodInfo && method.IsGenericMethod) - { - Type[] genericArguments = method.GetGenericArguments(); - stringBuilder.Append("["); - for (int i = 0; i < genericArguments.Length; i++) - { - if (!first) - { - stringBuilder.Append(","); - } - else - { - first = false; - } - - stringBuilder.Append(genericArguments[i].Name); - } - - stringBuilder.Append("]"); - } - - stringBuilder.Append("("); - ParameterInfo[] parameters = method.GetParameters(); - first = true; - for (int i = 0; i < parameters.Length; ++i) - { - if (!first) - { - stringBuilder.Append(", "); - } - else - { - first = false; - } - - string type = ""; - if (parameters[i].ParameterType != null) - { - type = parameters[i].ParameterType.Name; - } - - stringBuilder.Append(type + " " + parameters[i].Name); - } - - stringBuilder.Append(")"); - - return stringBuilder.ToString(); - } } } From 75691b704f6fd8804980414c24a10df6c95b9b14 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 29 Sep 2020 15:03:27 +1300 Subject: [PATCH 20/38] Removed unrelated redundant Description from csproj --- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index 914937a..1f90a4d 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -6,7 +6,6 @@ Michiel van Oudheusden Serilog Serilog.Sinks.Raygun - Send log events to custom topics in Azure Event Grid Apache-2.0 http://serilog.net http://serilog.net/images/serilog-sink-nuget.png From 90b07881f76f91f3ab28bea6e142fee1a2a83913 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Wed, 30 Sep 2020 16:28:02 +1300 Subject: [PATCH 21/38] Deleted methods that appeared again from merging --- .../Sinks/Raygun/RaygunSink.cs | 103 ------------------ 1 file changed, 103 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 820ed74..63ac46b 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -288,108 +288,5 @@ private static RaygunIdentifierMessage ParseUserInformation(string userInfo) return userIdentifier; } - - private static RaygunErrorStackTraceLineMessage[] BuildStackTrace(StackTrace stackTrace) - { - var lines = new List(); - - var frames = stackTrace.GetFrames(); - - if (frames == null || frames.Length == 0) - { - var line = new RaygunErrorStackTraceLineMessage { FileName = "none", LineNumber = 0 }; - lines.Add(line); - return lines.ToArray(); - } - - foreach (StackFrame frame in frames) - { - MethodBase method = frame.GetMethod(); - - if (method != null) - { - int lineNumber = frame.GetFileLineNumber(); - - if (lineNumber == 0) - { - lineNumber = frame.GetILOffset(); - } - - var methodName = GenerateMethodName(method); - - string file = frame.GetFileName(); - - string className = method.ReflectedType != null ? method.ReflectedType.FullName : "(unknown)"; - - var line = new RaygunErrorStackTraceLineMessage - { - FileName = file, - LineNumber = lineNumber, - MethodName = methodName, - ClassName = className - }; - - lines.Add(line); - } - } - - return lines.ToArray(); - } - - private static string GenerateMethodName(MethodBase method) - { - var stringBuilder = new StringBuilder(); - - stringBuilder.Append(method.Name); - - bool first = true; - if (method is MethodInfo && method.IsGenericMethod) - { - Type[] genericArguments = method.GetGenericArguments(); - stringBuilder.Append("["); - for (int i = 0; i < genericArguments.Length; i++) - { - if (!first) - { - stringBuilder.Append(","); - } - else - { - first = false; - } - - stringBuilder.Append(genericArguments[i].Name); - } - - stringBuilder.Append("]"); - } - - stringBuilder.Append("("); - ParameterInfo[] parameters = method.GetParameters(); - first = true; - for (int i = 0; i < parameters.Length; ++i) - { - if (!first) - { - stringBuilder.Append(", "); - } - else - { - first = false; - } - - string type = ""; - if (parameters[i].ParameterType != null) - { - type = parameters[i].ParameterType.Name; - } - - stringBuilder.Append(type + " " + parameters[i].Name); - } - - stringBuilder.Append(")"); - - return stringBuilder.ToString(); - } } } From 30838c8fed8b2ab712780f8d7d9d8ad6b1f56935 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 2 Oct 2020 11:11:33 +1300 Subject: [PATCH 22/38] Update to latest version of Raygun4Net which includes the exposed BuildStackTrace method --- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index 1f90a4d..bf40ee0 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -20,15 +20,15 @@ - + - + - + From 49daf20911e686835481a945bae868fb2910b974 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 2 Oct 2020 11:24:10 +1300 Subject: [PATCH 23/38] Code comment tweaks --- .../LoggerConfigurationRaygunExtensions.cs | 4 ++-- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 4 ++-- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs index 6a7cd89..33db7d1 100644 --- a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs +++ b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs @@ -26,11 +26,11 @@ namespace Serilog public static class LoggerConfigurationRaygunExtensions { /// - /// Adds a sink that writes log events (defaults to error and up) to the Raygun.io webservice. Properties are being send as data and the level is used as a tag. + /// Adds a sink that writes log events (defaults to error and up) to the Raygun service. Properties and the log message are being attached as UserCustomData and the level is included as a Tag. /// Your message is part of the custom data. /// /// The logger configuration. - /// The application key as found on the Raygun.io website. + /// The application key as found on an application in your Raygun account. /// If you have common outer exceptions that wrap a valuable inner exception which you'd prefer to group by, you can specify these by providing a list. /// Specifies the property name to read the username from. By default it is UserName. Set to null if you do not want to use this feature. /// Specifies the property to use to retrieve the application version from. You can use an enricher to add the application version to all the log events. When you specify null, Raygun will use the assembly version. diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index bf40ee0..1ab9630 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -12,8 +12,8 @@ git https://github.com/serilog/serilog-sinks-raygun serilog sink raygun - Copyright © Serilog Contributors 2017-2019 - Serilog event sink that writes to the Raygun.io service. + Copyright © Serilog Contributors 2017-2020 + Serilog event sink that writes to the Raygun service. 4.0.1 4.0.0.0 4.0.0.0 diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 63ac46b..fb4ed55 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -31,7 +31,7 @@ namespace Serilog.Sinks.Raygun { /// - /// Writes log events to the Raygun.com service. + /// Writes log events to the Raygun service. /// public class RaygunSink : ILogEventSink { @@ -46,10 +46,10 @@ public class RaygunSink : ILogEventSink readonly RaygunClient _client; /// - /// Construct a sink that saves errors to the Raygun.io service. Properties are being send as userdata and the level is included as tag. The message is included inside the userdata. + /// Construct a sink that saves errors to the Raygun service. Properties and the log message are being attached as UserCustomData and the level is included as a Tag. /// /// Supplies culture-specific formatting information, or null. - /// The application key as found on the Raygun website. + /// The application key as found on an application in your Raygun account. /// If you have common outer exceptions that wrap a valuable inner exception which you'd prefer to group by, you can specify these by providing a list. /// Specifies the property name to read the username from. By default it is UserName. Set to null if you do not want to use this feature. /// Specifies the property to use to retrieve the application version from. You can use an enricher to add the application version to all the log events. When you specify null, Raygun will use the assembly version. @@ -92,7 +92,7 @@ public RaygunSink(IFormatProvider formatProvider, /// The log event to write. public void Emit(LogEvent logEvent) { - //Include the log level as a tag. + // Include the log level as a tag. var tags = _tags.Concat(new[] { logEvent.Level.ToString() }).ToList(); var properties = logEvent.Properties From 3b24b8b83b47146b5c44ed14f632915319bfa7cc Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 2 Oct 2020 11:24:52 +1300 Subject: [PATCH 24/38] Removed an unused directive --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index fb4ed55..63492e1 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -17,7 +17,6 @@ using System.Diagnostics; using System.Linq; using System.Reflection; -using System.Text; using Mindscape.Raygun4Net; #if NETSTANDARD2_0 using Mindscape.Raygun4Net.AspNetCore; From 4f8a58846a0ed1be7b228eaa3bf856c43bfa555a Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 16 Oct 2020 17:05:26 +1300 Subject: [PATCH 25/38] WIP experimenting with using the Raygun4Net client to build the message --- .../Sinks/Raygun/RaygunSink.cs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 63492e1..9afe9f7 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -83,6 +83,8 @@ public RaygunSink(IFormatProvider formatProvider, _client = new RaygunClient(applicationKey); if (wrapperExceptions != null) _client.AddWrapperExceptions(wrapperExceptions.ToArray()); + + _client.SendingMessage += OnSendingMessage; } /// @@ -160,22 +162,6 @@ public void Emit(LogEvent logEvent) properties.Remove(_applicationVersionProperty); } - // Build up the rest of the message -#if NETSTANDARD2_0 - raygunMessage.Details.Environment = RaygunEnvironmentMessageBuilder.Build(new RaygunSettings()); -#else - raygunMessage.Details.Environment = RaygunEnvironmentMessageBuilder.Build(); -#endif - raygunMessage.Details.Tags = tags; - raygunMessage.Details.MachineName = Environment.MachineName; - - raygunMessage.Details.Client = new RaygunClientMessage() - { - Name = "RaygunSerilogSink", - Version = new AssemblyName(this.GetType().Assembly.FullName).Version.ToString(), - ClientUrl = "https://github.com/serilog/serilog-sinks-raygun" - }; - // Add the custom group key when provided if (properties.TryGetValue(_groupKeyProperty, out var customKey)) { @@ -187,22 +173,34 @@ public void Emit(LogEvent logEvent) // Add additional custom tags if (properties.TryGetValue(_tagsProperty, out var eventTags) && eventTags is object[]) { - foreach (var tag in (object[])eventTags) - raygunMessage.Details.Tags.Add(tag.ToString()); + tags.AddRange(((object[]) eventTags).Select(t => t.ToString())); properties.Remove(_tagsProperty); } - raygunMessage.Details.UserCustomData = properties; - // Submit if (logEvent.Level == LogEventLevel.Fatal) { - _client.Send(raygunMessage); + //_client.Send(raygunMessage); + _client.Send(logEvent.Exception, tags, properties); } else { - _client.SendInBackground(raygunMessage); + //_client.SendInBackground(raygunMessage); + _client.SendInBackground(logEvent.Exception, tags, properties); + } + } + + private void OnSendingMessage(object sender, RaygunSendingMessageEventArgs e) + { + if (e.Message != null) + { + e.Message.Details.Client = new RaygunClientMessage() + { + Name = "RaygunSerilogSink", + Version = new AssemblyName(this.GetType().Assembly.FullName).Version.ToString(), + ClientUrl = "https://github.com/serilog/serilog-sinks-raygun" + }; } } From 8e71c7bcbb347145d4a8f2480c69b3f6fb380875 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Mon, 19 Oct 2020 15:24:47 +1300 Subject: [PATCH 26/38] move all property-driven features into the SendingMessage callback --- .../Sinks/Raygun/RaygunSink.cs | 172 +++++++++--------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 9afe9f7..0140feb 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -34,15 +34,18 @@ namespace Serilog.Sinks.Raygun /// public class RaygunSink : ILogEventSink { - readonly IFormatProvider _formatProvider; - readonly string _userNameProperty; - readonly string _applicationVersionProperty; - readonly IEnumerable _tags; - readonly IEnumerable _ignoredFormFieldNames; - readonly string _groupKeyProperty; - readonly string _tagsProperty; - readonly string _userInfoProperty; - readonly RaygunClient _client; + private const string RenderedLogMessageProperty = "RenderedLogMessage"; + private const string LogMessageTemplateProperty = "LogMessageTemplate"; + + private readonly IFormatProvider _formatProvider; + private readonly string _userNameProperty; + private readonly string _applicationVersionProperty; + private readonly IEnumerable _tags; + private readonly IEnumerable _ignoredFormFieldNames; + private readonly string _groupKeyProperty; + private readonly string _tagsProperty; + private readonly string _userInfoProperty; + private readonly RaygunClient _client; /// /// Construct a sink that saves errors to the Raygun service. Properties and the log message are being attached as UserCustomData and the level is included as a Tag. @@ -96,13 +99,11 @@ public void Emit(LogEvent logEvent) // Include the log level as a tag. var tags = _tags.Concat(new[] { logEvent.Level.ToString() }).ToList(); - var properties = logEvent.Properties - .Select(pv => new { Name = pv.Key, Value = RaygunPropertyFormatter.Simplify(pv.Value) }) - .ToDictionary(a => a.Name, b => b.Value); + var properties = logEvent.Properties.ToDictionary(kv => kv.Key, kv => kv.Value); - // Add the message - properties.Add("RenderedLogMessage", logEvent.RenderMessage(_formatProvider)); - properties.Add("LogMessageTemplate", logEvent.MessageTemplate.Text); + // Add the message and template to the properties + properties.Add(RenderedLogMessageProperty, new ScalarValue(logEvent.RenderMessage(_formatProvider))); + properties.Add(LogMessageTemplateProperty, new ScalarValue(logEvent.MessageTemplate.Text)); // Create new message var raygunMessage = new RaygunMessage @@ -110,70 +111,10 @@ public void Emit(LogEvent logEvent) OccurredOn = logEvent.Timestamp.UtcDateTime }; - // Add exception when available, else use the message template so events can be grouped - raygunMessage.Details.Error = logEvent.Exception != null - ? RaygunErrorMessageBuilder.Build(logEvent.Exception) - : new RaygunErrorMessage() - { - ClassName = logEvent.MessageTemplate.Text, - Message = logEvent.RenderMessage(_formatProvider), - Data = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString()), - StackTrace = RaygunErrorMessageBuilder.BuildStackTrace(new StackTrace()) - }; - - // Add user when requested - if (!string.IsNullOrWhiteSpace(_userInfoProperty) && - logEvent.Properties.TryGetValue(_userInfoProperty, out var userInfoPropertyValue) && - userInfoPropertyValue != null) - { - switch (userInfoPropertyValue) - { - case StructureValue userInfoStructure: - raygunMessage.Details.User = BuildUserInformationFromStructureValue(userInfoStructure); - break; - case ScalarValue userInfoScalar when userInfoScalar.Value is string userInfo: - raygunMessage.Details.User = ParseUserInformation(userInfo); - break; - } - - if (raygunMessage.Details.User != null) - { - properties.Remove(_userInfoProperty); - } - } - - if (raygunMessage.Details.User == null && - !string.IsNullOrWhiteSpace(_userNameProperty) && - logEvent.Properties.ContainsKey(_userNameProperty) && - logEvent.Properties[_userNameProperty] != null) - { - raygunMessage.Details.User = new RaygunIdentifierMessage(logEvent.Properties[_userNameProperty].ToString()); - - properties.Remove(_userNameProperty); - } - - // Add version when requested - if (!String.IsNullOrWhiteSpace(_applicationVersionProperty) && - logEvent.Properties.ContainsKey(_applicationVersionProperty) && - logEvent.Properties[_applicationVersionProperty] != null) - { - raygunMessage.Details.Version = logEvent.Properties[_applicationVersionProperty].ToString("l", null); - - properties.Remove(_applicationVersionProperty); - } - - // Add the custom group key when provided - if (properties.TryGetValue(_groupKeyProperty, out var customKey)) - { - raygunMessage.Details.GroupingKey = customKey.ToString(); - - properties.Remove(_groupKeyProperty); - } - // Add additional custom tags - if (properties.TryGetValue(_tagsProperty, out var eventTags) && eventTags is object[]) + if (properties.TryGetValue(_tagsProperty, out var eventTags) && eventTags is SequenceValue tagsSequence) { - tags.AddRange(((object[]) eventTags).Select(t => t.ToString())); + tags.AddRange(tagsSequence.Elements.Select(t => t.ToString("l", null))); properties.Remove(_tagsProperty); } @@ -181,26 +122,95 @@ public void Emit(LogEvent logEvent) // Submit if (logEvent.Level == LogEventLevel.Fatal) { - //_client.Send(raygunMessage); _client.Send(logEvent.Exception, tags, properties); } else { - //_client.SendInBackground(raygunMessage); _client.SendInBackground(logEvent.Exception, tags, properties); } } private void OnSendingMessage(object sender, RaygunSendingMessageEventArgs e) { - if (e.Message != null) + if (e?.Message?.Details != null) { - e.Message.Details.Client = new RaygunClientMessage() + var details = e.Message.Details; + + details.Client = new RaygunClientMessage { Name = "RaygunSerilogSink", Version = new AssemblyName(this.GetType().Assembly.FullName).Version.ToString(), ClientUrl = "https://github.com/serilog/serilog-sinks-raygun" }; + + if (details.UserCustomData is Dictionary properties) + { + // If an Exception has not been provided, then use the log message/template to fill in the details and attach the current execution stack + if (details.Error == null) + { + details.Error = new RaygunErrorMessage + { + ClassName = properties[LogMessageTemplateProperty].ToString("l", null), + Message = properties[RenderedLogMessageProperty].ToString("l", null), + StackTrace = RaygunErrorMessageBuilder.BuildStackTrace(new StackTrace()) + }; + } + + // Add user information if provided + if (!string.IsNullOrWhiteSpace(_userInfoProperty) && + properties.TryGetValue(_userInfoProperty, out var userInfoPropertyValue) && + userInfoPropertyValue != null) + { + switch (userInfoPropertyValue) + { + case StructureValue userInfoStructure: + details.User = BuildUserInformationFromStructureValue(userInfoStructure); + break; + case ScalarValue userInfoScalar when userInfoScalar.Value is string userInfo: + details.User = ParseUserInformation(userInfo); + break; + } + + if (details.User != null) + { + details.UserCustomData.Remove(_userInfoProperty); + } + } + + // If user information is not set, then use the user-name if provided + if (details.User == null && + !string.IsNullOrWhiteSpace(_userNameProperty) && + properties.ContainsKey(_userNameProperty) && + properties[_userNameProperty] != null) + { + details.User = new RaygunIdentifierMessage(properties[_userNameProperty].ToString("l", null)); + + properties.Remove(_userNameProperty); + } + + // Add version if provided + if (!string.IsNullOrWhiteSpace(_applicationVersionProperty) && + properties.ContainsKey(_applicationVersionProperty) && + properties[_applicationVersionProperty] != null) + { + details.Version = properties[_applicationVersionProperty].ToString("l", null); + + properties.Remove(_applicationVersionProperty); + } + + // Add the custom group key if provided + if (properties.TryGetValue(_groupKeyProperty, out var customKey)) + { + details.GroupingKey = customKey.ToString("l", null); + + properties.Remove(_groupKeyProperty); + } + + // Simplify the remaining properties to be used as user-custom-data + details.UserCustomData = properties + .Select(pv => new { Name = pv.Key, Value = RaygunPropertyFormatter.Simplify(pv.Value) }) + .ToDictionary(a => a.Name, b => b.Value); + } } } From 79e4c63f0288e03e7c38b37753729906b57cc54c Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Mon, 19 Oct 2020 15:45:21 +1300 Subject: [PATCH 27/38] Pass the desired OccurredOn date through to the SendingMessage callback via a property --- .../Sinks/Raygun/RaygunSink.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 0140feb..62791a9 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -36,6 +36,7 @@ public class RaygunSink : ILogEventSink { private const string RenderedLogMessageProperty = "RenderedLogMessage"; private const string LogMessageTemplateProperty = "LogMessageTemplate"; + private const string OccurredProperty = "RaygunSink_OccurredOn"; private readonly IFormatProvider _formatProvider; private readonly string _userNameProperty; @@ -102,14 +103,9 @@ public void Emit(LogEvent logEvent) var properties = logEvent.Properties.ToDictionary(kv => kv.Key, kv => kv.Value); // Add the message and template to the properties - properties.Add(RenderedLogMessageProperty, new ScalarValue(logEvent.RenderMessage(_formatProvider))); - properties.Add(LogMessageTemplateProperty, new ScalarValue(logEvent.MessageTemplate.Text)); - - // Create new message - var raygunMessage = new RaygunMessage - { - OccurredOn = logEvent.Timestamp.UtcDateTime - }; + properties[RenderedLogMessageProperty] = new ScalarValue(logEvent.RenderMessage(_formatProvider)); + properties[LogMessageTemplateProperty] = new ScalarValue(logEvent.MessageTemplate.Text); + properties[OccurredProperty] = new ScalarValue(logEvent.Timestamp.UtcDateTime); // Add additional custom tags if (properties.TryGetValue(_tagsProperty, out var eventTags) && eventTags is SequenceValue tagsSequence) @@ -156,6 +152,15 @@ private void OnSendingMessage(object sender, RaygunSendingMessageEventArgs e) }; } + if (properties.TryGetValue(OccurredProperty, out var occurredOnPropertyValue) && + occurredOnPropertyValue is ScalarValue occurredOnScalar && + occurredOnScalar.Value is DateTime occurredOn) + { + e.Message.OccurredOn = occurredOn; + + properties.Remove(OccurredProperty); + } + // Add user information if provided if (!string.IsNullOrWhiteSpace(_userInfoProperty) && properties.TryGetValue(_userInfoProperty, out var userInfoPropertyValue) && From 2df03dd22b0e12e438c18026b967d048429dbd17 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Mon, 19 Oct 2020 16:26:55 +1300 Subject: [PATCH 28/38] Wired up ignored form fields option --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 62791a9..e1b93ef 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -42,7 +42,6 @@ public class RaygunSink : ILogEventSink private readonly string _userNameProperty; private readonly string _applicationVersionProperty; private readonly IEnumerable _tags; - private readonly IEnumerable _ignoredFormFieldNames; private readonly string _groupKeyProperty; private readonly string _tagsProperty; private readonly string _userInfoProperty; @@ -79,7 +78,6 @@ public RaygunSink(IFormatProvider formatProvider, _userNameProperty = userNameProperty; _applicationVersionProperty = applicationVersionProperty; _tags = tags ?? new string[0]; - _ignoredFormFieldNames = ignoredFormFieldNames ?? Enumerable.Empty(); _groupKeyProperty = groupKeyProperty; _tagsProperty = tagsProperty; _userInfoProperty = userInfoProperty; @@ -88,6 +86,9 @@ public RaygunSink(IFormatProvider formatProvider, if (wrapperExceptions != null) _client.AddWrapperExceptions(wrapperExceptions.ToArray()); + if(ignoredFormFieldNames != null) + _client.IgnoreFormFieldNames(ignoredFormFieldNames.ToArray()); + _client.SendingMessage += OnSendingMessage; } From 15684188963c2611f0a1fd5b88a91a8fe16a52a0 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Mon, 19 Oct 2020 16:57:21 +1300 Subject: [PATCH 29/38] Removed null check on ApiKey --- .../LoggerConfigurationRaygunExtensions.cs | 3 --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs index 33db7d1..39b91ac 100644 --- a/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs +++ b/src/Serilog.Sinks.Raygun/LoggerConfigurationRaygunExtensions.cs @@ -58,9 +58,6 @@ public static LoggerConfiguration Raygun( { if (loggerConfiguration == null) throw new ArgumentNullException("loggerConfiguration"); - if (string.IsNullOrWhiteSpace(applicationKey)) - throw new ArgumentNullException("applicationKey"); - return loggerConfiguration.Sink( new RaygunSink(formatProvider, applicationKey, wrapperExceptions, userNameProperty, applicationVersionProperty, tags, ignoredFormFieldNames, groupKeyProperty, tagsProperty, userInfoProperty), restrictedToMinimumLevel); diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index e1b93ef..6a244d7 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -71,9 +71,6 @@ public RaygunSink(IFormatProvider formatProvider, string tagsProperty = "Tags", string userInfoProperty = null) { - if (string.IsNullOrEmpty(applicationKey)) - throw new ArgumentNullException("applicationKey"); - _formatProvider = formatProvider; _userNameProperty = userNameProperty; _applicationVersionProperty = applicationVersionProperty; @@ -82,7 +79,12 @@ public RaygunSink(IFormatProvider formatProvider, _tagsProperty = tagsProperty; _userInfoProperty = userInfoProperty; +#if NETSTANDARD2_0 _client = new RaygunClient(applicationKey); +#else + _client = string.IsNullOrWhiteSpace(applicationKey) ? new RaygunClient() : new RaygunClient(applicationKey); +#endif + if (wrapperExceptions != null) _client.AddWrapperExceptions(wrapperExceptions.ToArray()); From 1971773d60def873d24c3c8217f785da81c88839 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Wed, 21 Oct 2020 17:00:25 +1300 Subject: [PATCH 30/38] Adding some documentation to the readme about the available features you can get via Raygun4Net --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33b56ab..054bb68 100644 --- a/README.md +++ b/README.md @@ -107,4 +107,36 @@ var userInfo = new RaygunIdentifierMessage("12345") }; Log.ForContext("CustomUserInfoProperty", userInfo, true).Error(new Exception("random error"), "other information"); -``` \ No newline at end of file +``` + +## Raygun4Net features + +This sink wraps the [Raygun4Net](https://github.com/MindscapeHQ/raygun4net) provider to build a crash report from an Exception and send it to Raygun. This makes the following Raygun4Net features available to you. To use these features, you need to add RaygunSettings to your configuration as explained below which is separate to the Serilog configuration. + +*.NET Core* + +Add a RaygunSettings block to your appsettings.config file where you can populate the settings that you want to use. + +```json +"RaygunSettings": { + "Setting": "Value" +} +``` + +*.NET Framework* + +Add the following section within the configSections element of your app.config or web.config file. + +```xml +
+``` + +Then add a RaygunSettings element containing the desired settings somewhere within the configuration element of the app.config or web.config file. + +```xml + +``` + +### ThrowOnError + +This is false by default, which means that any exception that occur within Raygun4Net itself will be silently caught. Setting this to true will allow any exceptions occurring in Raygun4Net to be thrown, which can help debug issues in Raygun4Net if crash reports aren't showing up in Raygun. \ No newline at end of file From 58b23bb55820a6768682fe7e29ac33ac7ad680a4 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Thu, 22 Oct 2020 16:04:08 +1300 Subject: [PATCH 31/38] Don't use the default wrapper exceptions from Raygun4Net as it could be an unecessary breaking change --- src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs index 6a244d7..0a0635c 100644 --- a/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs +++ b/src/Serilog.Sinks.Raygun/Sinks/Raygun/RaygunSink.cs @@ -85,6 +85,9 @@ public RaygunSink(IFormatProvider formatProvider, _client = string.IsNullOrWhiteSpace(applicationKey) ? new RaygunClient() : new RaygunClient(applicationKey); #endif + // Raygun4Net adds these two wrapper exceptions by default, but as there is no way to remove them through this Serilog sink, we replace them entirely with the configured wrapper exceptions. + _client.RemoveWrapperExceptions(typeof(TargetInvocationException), Type.GetType("System.Web.HttpUnhandledException, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")); + if (wrapperExceptions != null) _client.AddWrapperExceptions(wrapperExceptions.ToArray()); From 64f954483b5baf59f5e3b2ea416b43a1e106c247 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Thu, 22 Oct 2020 17:03:39 +1300 Subject: [PATCH 32/38] More detail about the various settings --- README.md | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 054bb68..8dfca1c 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,20 @@ Log.Logger = new LoggerConfiguration() ``` ### Required #### applicationKey -`string` +`type: string` + +Each application you create in Raygun will have an API Key which you can pass in here to specify where the crash reports will be sent to. Although this is required, you can set this to null or empty string which would result in crash reports not being sent. This can be useful if you want to configure your local environment to not send crash reports to Raygun and then use config transforms or the like to provide an API key for other environments. ### Optional #### wrapperExceptions -`type: IEnumerable` +`type: IEnumerable` `default: null` +This is a list of wrapper exception types that you're not interested in logging to Raygun. Whenever an undesired wrapper exception is logged, it will be discarded and only the inner exception(s) will be logged. + +For example, you may not be interested in the details of an AggregateException, so you could include typeof(AggregateException) in this list of wrapperExceptions. All inner exceptions of any logged AggregateException will be sent to Raygun as separate crash reports. + #### userNameProperty `type: string` @@ -65,11 +71,19 @@ Log.ForContext("CustomAppVersionProperty", "1.2.11").Error(new Exception("random `default: null` +This is a list of global tags that will be included on every crash report sent with this Serilog sink. + #### ignoredFormFieldNames `type: IEnumerable` `default: null` +Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). This option lets you specify a list of form fields that you do not want to be sent to Raygun. + +Setting ignoredFormFieldNames to a list that only contains "*" will cause no form fields to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. + +Note that HTTP headers, query parameters, cookies, server variables and raw request data can also be filtered out. Configuration to do so is described in the RaygunSettings section further below. + #### groupKeyProperty `type: string` @@ -84,6 +98,8 @@ Log.ForContext("CustomGroupKeyProperty", "TransactionId-12345").Error(new Except `default: Tags` +This allows you to specify a key in the properties collection that contains a list of tags to include on crash reports. Note that these will be included in addition to any global tags (describe above). If you set a list of tags in the properties collection multiple times (e.g. at different logging scopes) then only the latest list of tags will be used. + ```csharp Log.ForContext("CustomTagsProperty", new[] {"tag1", "tag2"}).Error(new Exception("random error"), "other information"); Log.Error(new Exception("random error"), "other information {@CustomTagsProperty}", new[] {"tag3", "tag4"}); @@ -109,21 +125,21 @@ var userInfo = new RaygunIdentifierMessage("12345") Log.ForContext("CustomUserInfoProperty", userInfo, true).Error(new Exception("random error"), "other information"); ``` -## Raygun4Net features +## Raygun4Net features configured via RaygunSettings This sink wraps the [Raygun4Net](https://github.com/MindscapeHQ/raygun4net) provider to build a crash report from an Exception and send it to Raygun. This makes the following Raygun4Net features available to you. To use these features, you need to add RaygunSettings to your configuration as explained below which is separate to the Serilog configuration. -*.NET Core* +**.NET Core** Add a RaygunSettings block to your appsettings.config file where you can populate the settings that you want to use. -```json +``` "RaygunSettings": { "Setting": "Value" } ``` -*.NET Framework* +**.NET Framework** Add the following section within the configSections element of your app.config or web.config file. @@ -139,4 +155,13 @@ Then add a RaygunSettings element containing the desired settings somewhere with ### ThrowOnError -This is false by default, which means that any exception that occur within Raygun4Net itself will be silently caught. Setting this to true will allow any exceptions occurring in Raygun4Net to be thrown, which can help debug issues in Raygun4Net if crash reports aren't showing up in Raygun. \ No newline at end of file +This is false by default, which means that any exception that occur within Raygun4Net itself will be silently caught. Setting this to true will allow any exceptions occurring in Raygun4Net to be thrown, which can help debug issues with Raygun4Net if crash reports aren't showing up in Raygun. + +### IgnoreSensitiveFieldNames + +Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. + +Setting IgnoreSensitiveFieldNames to a list that only contains "*" will cause none of these things to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. + +Individual options are also available which function in the same way as IgnoreSensitiveFieldNames: IgnoreQueryParameterNames, IgnoreFormFieldNames, IgnoreHeaderNames, IgnoreCookieNames and IgnoreServerVariableNames. + From 509ac2b7392cd20e0b2c7998022e6e34bb99eab0 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 23 Oct 2020 12:23:08 +1300 Subject: [PATCH 33/38] Added raw data and local storage docs --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8dfca1c..35ad59a 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Crash reports sent to Raygun from this Serilog sink will include HTTP context de Setting ignoredFormFieldNames to a list that only contains "*" will cause no form fields to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. -Note that HTTP headers, query parameters, cookies, server variables and raw request data can also be filtered out. Configuration to do so is described in the RaygunSettings section further below. +Note that HTTP headers, query parameters, cookies, server variables and raw request data can also be filtered out. Configuration to do so is described in the [RaygunSettings](#raygun4net-features-configured-via-raygunsettings) section further below. #### groupKeyProperty `type: string` @@ -159,9 +159,22 @@ This is false by default, which means that any exception that occur within Raygu ### IgnoreSensitiveFieldNames -Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. +Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. Additionally, entries to this setting will be attempted to be stripped out of the raw request payload (more options for controlling this are listed below) Setting IgnoreSensitiveFieldNames to a list that only contains "*" will cause none of these things to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. Individual options are also available which function in the same way as IgnoreSensitiveFieldNames: IgnoreQueryParameterNames, IgnoreFormFieldNames, IgnoreHeaderNames, IgnoreCookieNames and IgnoreServerVariableNames. +The IgnoreFormFieldNames entries will also strip out specified values from the raw request payload if it is multipart/form-data. + +### IsRawDataIgnored + +By default, Raygun crash reports will capture the raw request payload of the current HTTP context if present. If you would not like to include raw request payloads on crash reports sent to Raygun, then you can set IsRawDataIgnored to true. + +If you do want to include the raw request payload, but want to filter out sensitive fields, then you can use the IgnoreSensitiveFieldNames options described above. You'll also need to specify how the fields should be stripped from the raw request payload. Set UseXmlRawDataFilter to true for XML payloads or/and set UseKeyValuePairRawDataFilter to true for payloads of the format "key1=value1&key2=value2". + +Setting IsRawDataIgnoredWhenFilteringFailed to true will cause the entire raw request payload to be ignored in cases where specified sensitive values fail to be stripped out. + +### CrashReportingOfflineStorageEnabled + +Only available in .NET Framework applications. This is true by default which will cause crash reports to be saved to isolated storage (if possible) in cases where they fail to be sent to Raygun. This option lets you disable this functionality by setting it to false. When enabled, a maximum of 64 crash reports can be saved. This limit can be set lower than 64 via the MaxCrashReportsStoredOffline option. From 2f8ee75a4099f39b7ecd83107bf1227ee31cfd7c Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 23 Oct 2020 12:52:07 +1300 Subject: [PATCH 34/38] sorting out some inconsistencies in the readme --- README.md | 61 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 35ad59a..055dbb0 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,15 @@ Log.Logger = new LoggerConfiguration() "CustomUserInfoProperty") .CreateLogger(); ``` -### Required -#### applicationKey + +### applicationKey `type: string` +`required` + Each application you create in Raygun will have an API Key which you can pass in here to specify where the crash reports will be sent to. Although this is required, you can set this to null or empty string which would result in crash reports not being sent. This can be useful if you want to configure your local environment to not send crash reports to Raygun and then use config transforms or the like to provide an API key for other environments. -### Optional -#### wrapperExceptions +### wrapperExceptions `type: IEnumerable` `default: null` @@ -38,7 +39,7 @@ This is a list of wrapper exception types that you're not interested in logging For example, you may not be interested in the details of an AggregateException, so you could include typeof(AggregateException) in this list of wrapperExceptions. All inner exceptions of any logged AggregateException will be sent to Raygun as separate crash reports. -#### userNameProperty +### userNameProperty `type: string` `default: UserName` @@ -47,7 +48,7 @@ For example, you may not be interested in the details of an AggregateException, Log.ForContext("CustomUserNameProperty", "John Doe").Error(new Exception("random error"), "other information"); ``` -#### applicationVersionProperty +### applicationVersionProperty `type: string` `default: ApplicationVersion` @@ -56,44 +57,48 @@ Log.ForContext("CustomUserNameProperty", "John Doe").Error(new Exception("random Log.ForContext("CustomAppVersionProperty", "1.2.11").Error(new Exception("random error"), "other information"); ``` -#### restrictedToMinimumLevel +### restrictedToMinimumLevel `type: LogEventLevel` `default: LogEventLevel.Error` -#### formatProvider +### formatProvider `type: IFormatProvider` `default: null` -#### tags +### tags `type: IEnumerable` `default: null` This is a list of global tags that will be included on every crash report sent with this Serilog sink. -#### ignoredFormFieldNames +### ignoredFormFieldNames `type: IEnumerable` `default: null` Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). This option lets you specify a list of form fields that you do not want to be sent to Raygun. -Setting ignoredFormFieldNames to a list that only contains "*" will cause no form fields to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. +Setting `ignoredFormFieldNames` to a list that only contains "*" will cause no form fields to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. Note that HTTP headers, query parameters, cookies, server variables and raw request data can also be filtered out. Configuration to do so is described in the [RaygunSettings](#raygun4net-features-configured-via-raygunsettings) section further below. -#### groupKeyProperty +The `ignoreFormFieldNames` entries will also strip out specified values from the raw request payload if it is multipart/form-data. + +### groupKeyProperty `type: string` `default: GroupKey` +Crash reports sent to Raygun will be grouped together based on stack trace and exception type information. The `groupKeyProperty` setting specifies a key in the logging properties collection where you can provide a grouping key. Crash reports containing a grouping key will not be grouped automatically by Raygun. Instead, crash reports with matching custom grouping keys will be grouped together. + ```csharp Log.ForContext("CustomGroupKeyProperty", "TransactionId-12345").Error(new Exception("random error"), "other information"); ``` -#### tagsProperty +### tagsProperty `type: string` `default: Tags` @@ -105,7 +110,7 @@ Log.ForContext("CustomTagsProperty", new[] {"tag1", "tag2"}).Error(new Exception Log.Error(new Exception("random error"), "other information {@CustomTagsProperty}", new[] {"tag3", "tag4"}); ``` -#### userInfoProperty +### userInfoProperty `type: string` `default: null` @@ -154,27 +159,39 @@ Then add a RaygunSettings element containing the desired settings somewhere with ``` ### ThrowOnError +`type: bool` + +`default: false` This is false by default, which means that any exception that occur within Raygun4Net itself will be silently caught. Setting this to true will allow any exceptions occurring in Raygun4Net to be thrown, which can help debug issues with Raygun4Net if crash reports aren't showing up in Raygun. ### IgnoreSensitiveFieldNames +`type: string[]` -Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. Additionally, entries to this setting will be attempted to be stripped out of the raw request payload (more options for controlling this are listed below) +`default: null` + +Crash reports sent to Raygun from this Serilog sink will include HTTP context details if present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. Additionally, entries in this setting will be attempted to be stripped out of the raw request payload (more options for controlling this are explained in the [IsRawDataIgnored](#israwdataignored) section below). -Setting IgnoreSensitiveFieldNames to a list that only contains "*" will cause none of these things to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. +Setting `IgnoreSensitiveFieldNames` to a list that only contains "*" will cause none of these things to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. -Individual options are also available which function in the same way as IgnoreSensitiveFieldNames: IgnoreQueryParameterNames, IgnoreFormFieldNames, IgnoreHeaderNames, IgnoreCookieNames and IgnoreServerVariableNames. +Individual options are also available which function in the same way as IgnoreSensitiveFieldNames: `IgnoreQueryParameterNames`, `IgnoreFormFieldNames`, `IgnoreHeaderNames`, `IgnoreCookieNames` and `IgnoreServerVariableNames`. -The IgnoreFormFieldNames entries will also strip out specified values from the raw request payload if it is multipart/form-data. +The `IgnoreFormFieldNames` entries will also strip out specified values from the raw request payload if it is multipart/form-data. ### IsRawDataIgnored +`type: bool` -By default, Raygun crash reports will capture the raw request payload of the current HTTP context if present. If you would not like to include raw request payloads on crash reports sent to Raygun, then you can set IsRawDataIgnored to true. +`default: false` -If you do want to include the raw request payload, but want to filter out sensitive fields, then you can use the IgnoreSensitiveFieldNames options described above. You'll also need to specify how the fields should be stripped from the raw request payload. Set UseXmlRawDataFilter to true for XML payloads or/and set UseKeyValuePairRawDataFilter to true for payloads of the format "key1=value1&key2=value2". +By default, Raygun crash reports will capture the raw request payload of the current HTTP context if present. (Currently only supported in .NET Framework applications). If you would not like to include raw request payloads on crash reports sent to Raygun, then you can set `IsRawDataIgnored` to true. -Setting IsRawDataIgnoredWhenFilteringFailed to true will cause the entire raw request payload to be ignored in cases where specified sensitive values fail to be stripped out. +If you do want to include the raw request payload, but want to filter out sensitive fields, then you can use the `IgnoreSensitiveFieldNames` options [described above](#ignoresensitivefieldnames). You'll also need to specify how the fields should be stripped from the raw request payload. Set `UseXmlRawDataFilter` to true for XML payloads or/and set `UseKeyValuePairRawDataFilter` to true for payloads of the format "key1=value1&key2=value2". + +Setting `IsRawDataIgnoredWhenFilteringFailed` to true will cause the entire raw request payload to be ignored in cases where specified sensitive values fail to be stripped out. ### CrashReportingOfflineStorageEnabled +`type: bool` + +`default: true` -Only available in .NET Framework applications. This is true by default which will cause crash reports to be saved to isolated storage (if possible) in cases where they fail to be sent to Raygun. This option lets you disable this functionality by setting it to false. When enabled, a maximum of 64 crash reports can be saved. This limit can be set lower than 64 via the MaxCrashReportsStoredOffline option. +Only available in .NET Framework applications. This is true by default which will cause crash reports to be saved to isolated storage (if possible) in cases where they fail to be sent to Raygun. This option lets you disable this functionality by setting it to false. When enabled, a maximum of 64 crash reports can be saved. This limit can be set lower than 64 via the `MaxCrashReportsStoredOffline` option. From e0e5e4bb9f9e0adb2117edb487fa2c365508165b Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 23 Oct 2020 14:37:13 +1300 Subject: [PATCH 35/38] minor edits --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 055dbb0..db03d41 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Each application you create in Raygun will have an API Key which you can pass in This is a list of wrapper exception types that you're not interested in logging to Raygun. Whenever an undesired wrapper exception is logged, it will be discarded and only the inner exception(s) will be logged. -For example, you may not be interested in the details of an AggregateException, so you could include typeof(AggregateException) in this list of wrapperExceptions. All inner exceptions of any logged AggregateException will be sent to Raygun as separate crash reports. +For example, you may not be interested in the details of an AggregateException, so you could include `typeof(AggregateException)` in this list of wrapperExceptions. All inner exceptions of any logged AggregateException would then be sent to Raygun as separate crash reports. ### userNameProperty `type: string` @@ -79,7 +79,7 @@ This is a list of global tags that will be included on every crash report sent w `default: null` -Crash reports sent to Raygun from this Serilog sink will include HTTP context details where present. (Currently only supported in .NET Framework applications). This option lets you specify a list of form fields that you do not want to be sent to Raygun. +Crash reports sent to Raygun from this Serilog sink will include HTTP context details if present. (Currently only supported in .NET Framework applications). This option lets you specify a list of form fields that you do not want to be sent to Raygun. Setting `ignoredFormFieldNames` to a list that only contains "*" will cause no form fields to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. @@ -92,7 +92,7 @@ The `ignoreFormFieldNames` entries will also strip out specified values from the `default: GroupKey` -Crash reports sent to Raygun will be grouped together based on stack trace and exception type information. The `groupKeyProperty` setting specifies a key in the logging properties collection where you can provide a grouping key. Crash reports containing a grouping key will not be grouped automatically by Raygun. Instead, crash reports with matching custom grouping keys will be grouped together. +Crash reports sent to Raygun will be automatically grouped together based on stack trace and exception type information. The `groupKeyProperty` setting specifies a key in the logging properties collection where you can provide a grouping key. Crash reports containing a grouping key will not be grouped automatically by Raygun. Instead, crash reports with matching custom grouping keys will be grouped together. ```csharp Log.ForContext("CustomGroupKeyProperty", "TransactionId-12345").Error(new Exception("random error"), "other information"); @@ -103,7 +103,7 @@ Log.ForContext("CustomGroupKeyProperty", "TransactionId-12345").Error(new Except `default: Tags` -This allows you to specify a key in the properties collection that contains a list of tags to include on crash reports. Note that these will be included in addition to any global tags (describe above). If you set a list of tags in the properties collection multiple times (e.g. at different logging scopes) then only the latest list of tags will be used. +This allows you to specify a key in the properties collection that contains a list of tags to include on crash reports. Note that these will be included in addition to any global tags [described above](#tags). If you set a list of tags in the properties collection multiple times (e.g. at different logging scopes) then only the latest list of tags will be used. ```csharp Log.ForContext("CustomTagsProperty", new[] {"tag1", "tag2"}).Error(new Exception("random error"), "other information"); @@ -170,7 +170,7 @@ This is false by default, which means that any exception that occur within Raygu `default: null` -Crash reports sent to Raygun from this Serilog sink will include HTTP context details if present. (Currently only supported in .NET Framework applications). IgnoreSensitiveFieldNames lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. Additionally, entries in this setting will be attempted to be stripped out of the raw request payload (more options for controlling this are explained in the [IsRawDataIgnored](#israwdataignored) section below). +Crash reports sent to Raygun from this Serilog sink will include HTTP context details if present. (Currently only supported in .NET Framework applications). `IgnoreSensitiveFieldNames` lets you specify a list of HTTP query parameters, form fields, headers, cookies and server variables that you do not want to be sent to Raygun. Additionally, entries in this setting will be attempted to be stripped out of the raw request payload (more options for controlling this are explained in the `IsRawDataIgnored` section below). Setting `IgnoreSensitiveFieldNames` to a list that only contains "*" will cause none of these things to be sent to Raygun. Placing * before, after or at both ends of an entry will perform an ends-with, starts-with or contains operation respectively. @@ -185,7 +185,7 @@ The `IgnoreFormFieldNames` entries will also strip out specified values from the By default, Raygun crash reports will capture the raw request payload of the current HTTP context if present. (Currently only supported in .NET Framework applications). If you would not like to include raw request payloads on crash reports sent to Raygun, then you can set `IsRawDataIgnored` to true. -If you do want to include the raw request payload, but want to filter out sensitive fields, then you can use the `IgnoreSensitiveFieldNames` options [described above](#ignoresensitivefieldnames). You'll also need to specify how the fields should be stripped from the raw request payload. Set `UseXmlRawDataFilter` to true for XML payloads or/and set `UseKeyValuePairRawDataFilter` to true for payloads of the format "key1=value1&key2=value2". +If you do want to include the raw request payload, but want to filter out sensitive fields, then you can use the `IgnoreSensitiveFieldNames` options described above. You'll also need to specify how the fields should be stripped from the raw request payload. Set `UseXmlRawDataFilter` to true for XML payloads or/and set `UseKeyValuePairRawDataFilter` to true for payloads of the format "key1=value1&key2=value2". Setting `IsRawDataIgnoredWhenFilteringFailed` to true will cause the entire raw request payload to be ignored in cases where specified sensitive values fail to be stripped out. From 4eb7f8e906a964df2e7b9f4b6094edef818a29f4 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Fri, 23 Oct 2020 14:56:20 +1300 Subject: [PATCH 36/38] Some further details about the application version option --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index db03d41..5ab26d6 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ Log.ForContext("CustomUserNameProperty", "John Doe").Error(new Exception("random `default: ApplicationVersion` +By default, crash reports sent to Raygun will have an ApplicationVersion field based on the version of the entry assembly for your application. If this is not being picked up correctly, or if you want to provide a different version, then you can do so by including the desired value in the logging properties collection. + +You can specify the property key that you place the version in by using this applicationVersionProperty setting. Otherwise the version will be read from the "ApplicationVersion" key. + ```csharp Log.ForContext("CustomAppVersionProperty", "1.2.11").Error(new Exception("random error"), "other information"); ``` From 13cfb5b51019461fee1d6fa43c7c432f2a62d9d2 Mon Sep 17 00:00:00 2001 From: QuantumNightmare Date: Tue, 27 Oct 2020 09:29:20 +1300 Subject: [PATCH 37/38] Version 5 --- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index 1ab9630..c2cb34b 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -14,9 +14,10 @@ serilog sink raygun Copyright © Serilog Contributors 2017-2020 Serilog event sink that writes to the Raygun service. - 4.0.1 - 4.0.0.0 - 4.0.0.0 + 5.0.0 + 5.0.0.0 + 5.0.0.0 + 5.0.0 From 7c7416c88e1d136d5c292150906dffc26882147c Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 27 Oct 2020 08:24:23 +1000 Subject: [PATCH 38/38] Fix versioning --- src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj index c2cb34b..757fdfb 100644 --- a/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj +++ b/src/Serilog.Sinks.Raygun/Serilog.Sinks.Raygun.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net46;net461 @@ -14,10 +14,7 @@ serilog sink raygun Copyright © Serilog Contributors 2017-2020 Serilog event sink that writes to the Raygun service. - 5.0.0 - 5.0.0.0 - 5.0.0.0 - 5.0.0 + 5.0.1