public IRaygunMessageBuilder SetExceptionDetails(Exception exception)
        {
            if (exception != null)
            {
                _raygunMessage.Details.Error = RaygunErrorMessageBuilder.Build(exception);
            }

            var error = exception as RaygunWebApiHttpException;

            if (error != null)
            {
                _raygunMessage.Details.Response = new RaygunResponseMessage
                {
                    StatusCode        = (int)error.StatusCode,
                    StatusDescription = error.ReasonPhrase,
                    Content           = error.Content,
                };
            }

            var responseException = exception as HttpResponseException;

            if (responseException != null)
            {
                string content = RaygunSettings.Settings.IsResponseContentIgnored ? null : responseException.Response.Content.ReadAsString();
                _raygunMessage.Details.Response = new RaygunResponseMessage
                {
                    StatusCode        = (int)responseException.Response.StatusCode,
                    StatusDescription = responseException.Response.ReasonPhrase,
                    Content           = content
                };
            }

            return(this);
        }
        //public IActionResult Index()
        //{
        //    throw new Exception("Yikes an Error!!!");
        //    //return View();
        //}

        public async Task <IActionResult> Index()
        {
            try
            {
                throw new Exception("Yikes an Error!!!");
                //return View();
            }
            catch (Exception ex)
            {
                var msg = new RaygunMessage();

                msg.Details = new RaygunMessageDetails
                {
                    User    = RayGunUtils.BuildRayGunIdentifierMessage(HttpContext.User),
                    Error   = RaygunErrorMessageBuilder.Build(ex),
                    Request = await RaygunAspNetCoreRequestMessageBuilder.Build(HttpContext, new RaygunRequestMessageOptions())
                };

                var rgClient = _rgProvider.GetClient(new RaygunSettings(), HttpContext);
                await rgClient.SendInBackground(msg);

                return(View());
                //return new JsonResult(new ExceptionResponse
                //{
                //    ErrorId = Guid.NewGuid(),
                //    Message = ex.Message
                //}); ;
            }
        }
Пример #3
0
        public void FormatStacktraceWithDebugSymbolsTest()
        {
            string stackTraceStr = @" at XamarinIOSSingleViewTest.AppDelegate+<Bar>d__8.MoveNext () [0x000ad] in C:\Dev\Tests\XamarinIOSTestApplication\XamarinIOSSingleViewTest\AppDelegate.cs:68 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Library/Frameworks/Xamarin.iOS.framework/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Library/Frameworks/Xamarin.iOS.framework/system/runtime/compilerservices/TaskAwaiter.cs:187 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Library/Frameworks/Xamarin.iOS.framework/system/runtime/compilerservices/TaskAwaiter.cs:156 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Library/Frameworks/Xamarin.iOS.framework/system/runtime/compilerservices/TaskAwaiter.cs:128 
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/system/runtime/compilerservices/TaskAwaiter.cs:113 
  at XamarinIOSSingleViewTest.AppDelegate+<Foo>d__7.MoveNext () [0x000cf] in C:\Dev\Tests\XamarinIOSTestApplication\XamarinIOSSingleViewTest\AppDelegate.cs:58";

            MyTestException exception = new MyTestException("Exception test message", stackTraceStr);
            var             message   = RaygunErrorMessageBuilder.Build(exception);

            foreach (var line in message.StackTrace)
            {
                Console.WriteLine(line.ToString() + "\n");
            }

            Assert.IsNotEmpty(message.ClassName);
            Assert.IsNotNull(message.StackTrace);
            Assert.IsNotEmpty(message.StackTrace);

            var lineOne = message.StackTrace.FirstOrDefault();

            Assert.IsNotNullOrEmpty(lineOne.ClassName);
            Assert.IsNotNullOrEmpty(lineOne.MethodName);
        }
Пример #4
0
        public void FormatStacktraceWithoutDebugSymbolsTest()
        {
            string stackTraceStr = @"  at RaygunXamarinTest.Net.HttpApiClient+<EnsureSuccessAsync>c__async7.MoveNext () <0xc2b59c + 0x00670> in <06b44c3216694065a06dc13af99a121f#a65e7e6904709cacfd8634d732fe31fb>
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0x47ec74 + 0x00118> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0x47ebac + 0x000bf> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () <0x47eb68 + 0x0001f> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at RaygunXamarinTest.Net.HttpApiClient+<GetClientResponse>c__async6.MoveNext () <0xb89040 + 0x00407> in <06b44c3216694065a06dc13af99a121f#a65e7e6904709cacfd8634d732fe31fb>
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0x47ec74 + 0x00118> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0x47ebac + 0x000bf> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () <0x47ee98 + 0x0002f> in <15e850188d9f425bbeae90f0bbc51e17#a65e7e6904709cacfd8634d732fe31fb>
  at RaygunXamarinTest.Net.HttpApiClient+<PostJsonAsync>c__async2.MoveNext () <0xb88598 + 0x0019b> in <06b44c3216694065a06dc13af99a121f#a65e7e6904709cacfd8634d732fe31fb>";

            MyTestException exception = new MyTestException("Exception test message", stackTraceStr);
            var             message   = RaygunErrorMessageBuilder.Build(exception);

            foreach (var line in message.StackTrace)
            {
                Console.WriteLine(line.ToString() + "\n");
            }

            Assert.IsNotEmpty(message.ClassName);
            Assert.IsNotNull(message.StackTrace);
            Assert.IsNotEmpty(message.StackTrace);

            var lineOne = message.StackTrace.FirstOrDefault();

            Assert.IsNotNullOrEmpty(lineOne.ClassName);
            Assert.IsNotNullOrEmpty(lineOne.MethodName);
        }
Пример #5
0
        /// <summary>
        /// Emit the provided log event to the sink.
        /// </summary>
        /// <param name="logEvent">The log event to write.</param>
        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);

            // Add the message
            properties.Add("RenderedLogMessage", logEvent.RenderMessage(_formatProvider));
            properties.Add("LogMessageTemplate", logEvent.MessageTemplate.Text);

            // Create new message
            var raygunMessage = new RaygunMessage
            {
                OccurredOn = logEvent.Timestamp.UtcDateTime
            };

            // Add exception when available
            if (logEvent.Exception != null)
            {
                raygunMessage.Details.Error = RaygunErrorMessageBuilder.Build(logEvent.Exception);
            }

            // Add user when requested
            if (!String.IsNullOrWhiteSpace(_userNameProperty) &&
                logEvent.Properties.ContainsKey(_userNameProperty) &&
                logEvent.Properties[_userNameProperty] != null)
            {
                raygunMessage.Details.User = new RaygunIdentifierMessage(logEvent.Properties[_userNameProperty].ToString());
            }

            // Add version when requested
            if (!String.IsNullOrWhiteSpace(_applicationVersionProperty) &&
                logEvent.Properties.ContainsKey(_applicationVersionProperty) &&
                logEvent.Properties[_applicationVersionProperty] != null)
            {
                raygunMessage.Details.Version = logEvent.Properties[_applicationVersionProperty].ToString();
            }

            // 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;

            if (HttpContext.Current != null)
            {
                // Request message is built here instead of raygunClient.Send so RequestMessageOptions have to be constructed here
                var requestMessageOptions = new RaygunRequestMessageOptions(_ignoredFormFieldNames, Enumerable.Empty <string>(), Enumerable.Empty <string>(), Enumerable.Empty <string>());
                raygunMessage.Details.Request = RaygunRequestMessageBuilder.Build(HttpContext.Current.Request, requestMessageOptions);
            }

            // Submit
            //_client.SendInBackground(raygunMessage);
            _client.Send(raygunMessage);
        }
Пример #6
0
        public void ParseStackTraceLine_MemoryAddressInAngledBrackets_ClassMethodFileAndLineNumberAreObtained()
        {
            string stackTraceLine = "at Raygun.Trigger.Pull () <0x00000> in Raygun.Trigger.cs:15";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Raygun.Trigger", message.ClassName);
            Assert.AreEqual("Pull()", message.MethodName);
            Assert.AreEqual("Raygun.Trigger.cs", message.FileName);
            Assert.AreEqual(15, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #7
0
        public void ParseStackTraceLine_AsyncMethod_MethodIsObtainedFromAngledBrackets()
        {
            string stackTraceLine = "at Raygun.Trigger+<PullAsync>d__7.MoveNext () in Raygun.Trigger.cs:15";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Raygun.Trigger", message.ClassName);
            Assert.AreEqual("PullAsync()", message.MethodName);
            Assert.AreEqual("Raygun.Trigger.cs", message.FileName);
            Assert.AreEqual(15, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #8
0
        public void ParseStackTraceLine_FileAndNumberInBrackets_FileAndLineNumberAreObtained()
        {
            string stackTraceLine = "at Raygun.Trigger.Pull(Raygun.Trigger.cs:15)";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Raygun.Trigger", message.ClassName);
            Assert.AreEqual("Pull", message.MethodName);
            Assert.AreEqual("Raygun.Trigger.cs", message.FileName);
            Assert.AreEqual(15, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #9
0
        public void ParseStackTraceLine_GenericMethod_GenericParameterIsIncludedInMethodName()
        {
            string stackTraceLine = "at Raygun.Trigger.Pull[T] () in Raygun.Trigger.cs:15";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Raygun.Trigger", message.ClassName);
            Assert.AreEqual("Pull[T]()", message.MethodName);
            Assert.AreEqual("Raygun.Trigger.cs", message.FileName);
            Assert.AreEqual(15, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #10
0
        public void ParseStackTraceLine_Constructor_MethodNameStartsWithPeriod()
        {
            string stackTraceLine = "at Raygun..ctor () in Raygun.cs:7";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Raygun", message.ClassName);
            Assert.AreEqual(".ctor()", message.MethodName);
            Assert.AreEqual("Raygun.cs", message.FileName);
            Assert.AreEqual(7, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #11
0
        public void ParseStackTraceLine_AsyncMethodMultipleAngleBrackets_MethodIsObtainedFromAngledBrackets()
        {
            string stackTraceLine = "at Android.App.SyncContext+<Post>c__AnonStorey0.<>m__0 () [0x00000] in <2e3d0b54edd14877b2091b405b48598f>:0";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("Android.App.SyncContext", message.ClassName);
            Assert.AreEqual("Post()", message.MethodName);
            Assert.AreEqual("<2e3d0b54edd14877b2091b405b48598f>", message.FileName);
            Assert.AreEqual(0, message.LineNumber);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #12
0
        public void ParseStackTraceLine_OnlyClassAndMethod_FileAndLineNumberIsNull()
        {
            string stackTraceLine = "at Raygun.Trigger.Pull(int count)";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.IsNull(message.FileName);
            Assert.IsNull(message.LineNumber);

            Assert.AreEqual("Raygun.Trigger", message.ClassName);
            Assert.AreEqual("Pull(int count)", message.MethodName);
            Assert.AreEqual(stackTraceLine, message.Raw);
        }
Пример #13
0
        public void ParseStackTraceLine_ArbitraryText_LineIsLoggedInRawProperty()
        {
            string stackTraceLine = "--- End of managed Java.Lang.ReflectiveOperationException stack trace ---";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("--- End of managed Java.Lang.ReflectiveOperationException stack trace ---", message.Raw);

            Assert.IsNull(message.ClassName);
            Assert.IsNull(message.MethodName);
            Assert.IsNull(message.FileName);
            Assert.IsNull(message.LineNumber);
        }
Пример #14
0
        public void ParseStackTraceLine_WrapperDynamicMethod_LineIsLoggedInRawProperty()
        {
            string stackTraceLine = "at (wrapper dynamic-method) System.Object:6b4f2c61-c425-4660-9dd5-ef82ab5b5664 (intptr,intptr)";

            var message = RaygunErrorMessageBuilder.ParseStackTraceLine(stackTraceLine);

            Assert.AreEqual("at (wrapper dynamic-method) System.Object:6b4f2c61-c425-4660-9dd5-ef82ab5b5664 (intptr,intptr)", message.Raw);

            Assert.IsNull(message.ClassName);
            Assert.IsNull(message.MethodName);
            Assert.IsNull(message.FileName);
            Assert.IsNull(message.LineNumber);
        }
Пример #15
0
        public IRaygunMessageBuilder SetExceptionDetails(Exception exception)
        {
            if (exception != null)
            {
                _raygunMessage.Details.Error = RaygunErrorMessageBuilder.Build(exception);
            }

            if (exception != null && exception.GetType().FullName == "System.Web.HttpException")
            {
                var    code        = (int)ReflectionHelpers.RunInstanceMethod(exception, "GetHttpCode");
                string description = null;

                if (Enum.IsDefined(typeof(HttpStatusCode), code))
                {
                    description = ((HttpStatusCode)code).ToString();
                }

                _raygunMessage.Details.Response = new RaygunResponseMessage {
                    StatusCode = code, StatusDescription = description
                };
            }

            var webError = exception as WebException;

            if (webError != null)
            {
                if (webError.Status == WebExceptionStatus.ProtocolError && webError.Response is HttpWebResponse)
                {
                    var response = (HttpWebResponse)webError.Response;
                    _raygunMessage.Details.Response = new RaygunResponseMessage {
                        StatusCode = (int)response.StatusCode, StatusDescription = response.StatusDescription
                    };
                }
                else if (webError.Status == WebExceptionStatus.ProtocolError && webError.Response is FtpWebResponse)
                {
                    var response = (FtpWebResponse)webError.Response;
                    _raygunMessage.Details.Response = new RaygunResponseMessage {
                        StatusCode = (int)response.StatusCode, StatusDescription = response.StatusDescription
                    };
                }
                else
                {
                    _raygunMessage.Details.Response = new RaygunResponseMessage {
                        StatusDescription = webError.Status.ToString()
                    };
                }
            }

            return(this);
        }
        public void ReflectionTypeLoadExceptionSupport()
        {
            FileNotFoundException       ex1     = new FileNotFoundException();
            OutOfMemoryException        ex2     = new OutOfMemoryException();
            ReflectionTypeLoadException wrapper = new ReflectionTypeLoadException(new Type[] { typeof(FakeRaygunClient), typeof(WrapperException) }, new Exception[] { ex1, ex2 });

            RaygunErrorMessage message = RaygunErrorMessageBuilder.Build(wrapper);

            Assert.AreEqual(2, message.InnerErrors.Count());
            Assert.AreEqual("System.IO.FileNotFoundException", message.InnerErrors[0].ClassName);
            Assert.AreEqual("System.OutOfMemoryException", message.InnerErrors[1].ClassName);

            Assert.IsTrue(message.InnerErrors[0].Data["Type"].ToString().Contains("FakeRaygunClient"));
            Assert.IsTrue(message.InnerErrors[1].Data["Type"].ToString().Contains("WrapperException"));
        }
Пример #17
0
        public void ExceptionBuilds()
        {
            Exception exception = null;

            try
            {
                ExceptionallyCrappyMethod <string, int>("bogus");
            }
            catch (Exception e)
            {
                exception = e;
            }

            Assert.That(() => RaygunErrorMessageBuilder.Build(exception), Throws.Nothing);
        }
        public IRaygunMessageBuilder SetExceptionDetails(Exception exception)
        {
            if (exception != null)
            {
                _raygunMessage.Details.Error = RaygunErrorMessageBuilder.Build(exception);
            }

            var error = exception as RaygunWebApiHttpException;

            if (error != null)
            {
                _raygunMessage.Details.Response = new RaygunResponseMessage
                {
                    StatusCode        = (int)error.StatusCode,
                    StatusDescription = error.ReasonPhrase
                };
            }

            var responseException = exception as HttpResponseException;

            if (responseException != null)
            {
                try
                {
                    var task = responseException.Response.Content.ReadAsStringAsync();
                    task.Wait();
                    responseException.Data["Content"] = task.Result;
                }
                catch (Exception) {}

                _raygunMessage.Details.Response = new RaygunResponseMessage
                {
                    StatusCode        = (int)responseException.Response.StatusCode,
                    StatusDescription = responseException.Response.ReasonPhrase
                };
            }

            return(this);
        }
        /// <summary>
        /// Emit the provided log event to the sink.
        /// </summary>
        /// <param name="logEvent">The log event to write.</param>
        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);

            // Add the message
            properties.Add("RenderedLogMessage", logEvent.RenderMessage(_formatProvider));
            properties.Add("LogMessageTemplate", logEvent.MessageTemplate.Text);

            // Create new message
            var raygunMessage = new RaygunMessage
            {
                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.MessageTemplate.Text,
                Data      = logEvent.Properties.ToDictionary(k => k.Key, v => v.Value.ToString())
            };

            // Add user when requested
            if (!string.IsNullOrWhiteSpace(_userNameProperty) &&
                logEvent.Properties.ContainsKey(_userNameProperty) &&
                logEvent.Properties[_userNameProperty] != null)
            {
                raygunMessage.Details.User = new RaygunIdentifierMessage(logEvent.Properties[_userNameProperty].ToString());
            }

            // 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);
            }

            // 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();
            }

            // 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());
                }
            }

            // Submit
            _client.SendInBackground(raygunMessage);
        }
Пример #20
0
 public void ExceptionBuilds()
 {
     Assert.That(() => RaygunErrorMessageBuilder.Build(_exception), Throws.Nothing);
 }
Пример #21
0
        public void ErrorMessageHasInnerError()
        {
            var errorMessage = RaygunErrorMessageBuilder.Build(_exception);

            Assert.That(errorMessage.InnerError, Is.Not.Null);
        }
Пример #22
0
        public void FormatGenericExceptionClassName()
        {
            var message = RaygunErrorMessageBuilder.Build(new GenericException <Dictionary <string, List <object> > >());

            Assert.AreEqual("Mindscape.Raygun4Net.Tests.Model.GenericException<Dictionary<String,List<Object>>>", message.ClassName);
        }
Пример #23
0
        public void IncludeNamespaceInExceptionClassName()
        {
            var message = RaygunErrorMessageBuilder.Build(new InvalidOperationException());

            Assert.AreEqual("System.InvalidOperationException", message.ClassName);
        }
Пример #24
0
        private void OnCustomGroupingKey(object sender, RaygunCustomGroupingKeyEventArgs e)
        {
            if (e?.Message?.Details != null)
            {
                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 <string, LogEventPropertyValue> 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 (e.Exception is NullException nullException)
                    {
                        details.Error = new RaygunErrorMessage
                        {
                            ClassName  = properties[LogMessageTemplateProperty].AsString(),
                            Message    = properties[RenderedLogMessageProperty].AsString(),
                            StackTrace = RaygunErrorMessageBuilder.BuildStackTrace(nullException.CodeExecutionStackTrace)
                        };
                    }

                    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) &&
                        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].AsString());

                        properties.Remove(_userNameProperty);
                    }

                    // Add version if provided
                    if (!string.IsNullOrWhiteSpace(_applicationVersionProperty) &&
                        properties.ContainsKey(_applicationVersionProperty) &&
                        properties[_applicationVersionProperty] != null)
                    {
                        details.Version = properties[_applicationVersionProperty].AsString();

                        properties.Remove(_applicationVersionProperty);
                    }

                    // Add the custom group key if provided
                    if (properties.TryGetValue(_groupKeyProperty, out var customKey))
                    {
                        details.GroupingKey = customKey.AsString();

                        properties.Remove(_groupKeyProperty);
                    }

#if NETSTANDARD2_0
                    // Add Http request/response messages if present and not already set
                    if (details.Request == null &&
                        properties.TryGetValue(RaygunClientHttpEnricher.RaygunRequestMessagePropertyName, out var requestMessageProperty) &&
                        requestMessageProperty is StructureValue requestMessageValue)
                    {
                        details.Request = BuildRequestMessageFromStructureValue(requestMessageValue);
                        properties.Remove(RaygunClientHttpEnricher.RaygunRequestMessagePropertyName);
                    }

                    if (details.Response == null &&
                        properties.TryGetValue(RaygunClientHttpEnricher.RaygunResponseMessagePropertyName, out var responseMessageProperty) &&
                        responseMessageProperty is StructureValue responseMessageValue)
                    {
                        details.Response = BuildResponseMessageFromStructureValue(responseMessageValue);
                        properties.Remove(RaygunClientHttpEnricher.RaygunResponseMessagePropertyName);
                    }
#endif

                    // 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);
                }
            }
        }