private EventInfo CreateEventInfoBase(Event errorData)
        {
            var appInfo = new AppInfo
            {
                Version = Config.AppVersion,
                ReleaseStage = Config.ReleaseStage,
            };

            var userInfo = new UserInfo
            {
                Id = errorData.UserId,
                Email = errorData.UserEmail,
                Name = errorData.UserName
            };

            var eventInfo = new EventInfo
            {
                App = appInfo,
                Device = Config.DeviceInfo,
                Severity = errorData.Severity,
                //User = userInfo,
                Context = errorData.Context,
                GroupingHash = errorData.GroupingHash,
                Exceptions = new List<ExceptionInfo>()
            };
            return eventInfo;
        }
        public Notification CreateFromError(Event error)
        {
            var notification = CreateNotificationBase();
            var eventInfo = CreateEventInfoBase(error);
            RecursiveAddExceptionInfo(error, error.Exception, error.CallTrace, eventInfo);
            if (eventInfo == null)
                return null;

            notification.Events.Add(eventInfo);
            return notification;
        }
        /// <summary>
        /// Starting with an exception, will recursively add exception infos to event infos.
        /// If an aggregate exception is encountered, all inner exceptions will be added
        /// </summary>
        /// <param name="error">The error to create new event infos</param>
        /// <param name="exp">The exception to add to the current event</param>
        /// <param name="callStack">The stack of notify call</param>
        /// <param name="currentEvent">The current event info to add the exception to</param>
        private void RecursiveAddExceptionInfo(Event error,
                                               Exception exp,
                                               string callStack,
                                               EventInfo currentEvent)
        {
            // If we have no more exceptions, return the generated event info
            if (exp == null) return;

            // Parse the exception and add it to the current event info stack
            var expInfo = ExceptionParser.GenerateExceptionInfo(exp, callStack, Config);
            if (expInfo != null)
                currentEvent.Exceptions.Add(expInfo);

            // If the exception has no inner exception, then we are finished. Generate metadata for the last exception
            // and set the final metadata for the event info
            if (exp.InnerException == null)
            {
                FinaliseEventInfo(currentEvent, error, exp);
            }
            else
            {
                // Check if the current exception contains more than 1 inner exception
                // if it does, then recurse through them seperately
                var aggExp = exp as AggregateException;
                if (aggExp != null && aggExp.InnerExceptions.Count > 1)
                {
                    foreach (var inner in aggExp.InnerExceptions)
                    {
                        RecursiveAddExceptionInfo(error, inner, callStack, currentEvent);
                    }
                }
                else
                {
                    // Otherwise just move to the next inner exception
                    RecursiveAddExceptionInfo(error, exp.InnerException, callStack, currentEvent);
                }           
            }
        }
        /// <summary>
        /// Finalises the event info by adding final metadata 
        /// </summary>
        /// <param name="eventInfo">The event info to finalise</param>
        /// <param name="error">The responsible event</param>
        /// <param name="lastException">The root exception of the event info</param>
        private void FinaliseEventInfo(EventInfo eventInfo, Event error, Exception lastException)
        {
            var expMetaData = new Metadata();

            expMetaData.AddToTab(ExpDetailsTabName, "runtimeEnding", error.IsRuntimeEnding);

            if (lastException.HelpLink != null)
                expMetaData.AddToTab(ExpDetailsTabName, "helpLink", lastException.HelpLink);

            if (lastException.Source != null)
                expMetaData.AddToTab(ExpDetailsTabName, "source", lastException.Source);

            var metaData = Metadata.CombineMetadata(Config.Metadata, error.Metadata, expMetaData);
            metaData.FilterEntries(Config.IsEntryFiltered);
            eventInfo.Metadata = metaData.MetadataStore;
        }
 /// <summary>
 /// Runs all the before notify callbacks with the supplied error.
 /// </summary>
 /// <param name="errorEvent">The error that will be sent to Bugsnag</param>
 /// <returns>True if all callbacks returned true, false otherwise</returns>
 internal bool RunBeforeNotifyCallbacks(Event errorEvent)
 {
     // Do nothing if the before notify action indicates we should ignore the error event
     foreach (Func<Event, bool> callback in BeforeNotifyCallbacks)
     {
         try
         {
             if (!callback(errorEvent))
                 return false;
         }
         catch (Exception exp)
         {
             // If the callback exceptions, we will try to send the notification anyway, to give the
             // best possible chance of reporting the error
             Logger.Warning("[Before Notify] Exception : " + exp.ToString());
         }
     }
     return true;
 }
 /// <summary>
 /// Copy into the Event the information from the config.
 /// </summary>
 /// <param name="errorEvent">The event to add the info to</param>
 internal void AddConfigToEvent(Event errorEvent)
 {
     if (!String.IsNullOrEmpty(Context)) errorEvent.Context = Context;
     if (!String.IsNullOrEmpty(UserId)) errorEvent.UserId = UserId;
     if (!String.IsNullOrEmpty(UserName)) errorEvent.UserName = UserName;
     if (!String.IsNullOrEmpty(UserEmail)) errorEvent.UserEmail = UserEmail;
 }
 /// <summary>
 /// Runs the internal before notify callbacks which are configured by the notifier itself
 /// to add some default values.
 /// </summary>
 /// <param name="errorEvent">The event that will be sent to bugsnag</param>
 internal void RunInternalBeforeNotifyCallbacks(Event errorEvent)
 {
     // Do nothing if the before notify action indicates we should ignore the error event
     foreach (Action<Event> callback in InternalBeforeNotifyCallbacks)
     {
         try
         {
             callback(errorEvent);
         }
         catch (Exception exp)
         {
             // If the callback exceptions, we will try to send the notification anyway, to give the
             // best possible chance of reporting the error
             Logger.Warning("[Before Notify] Exception : " + exp.ToString());
         }
     }
 }
 public void Send(Event errorEvent)
 {
     var notification = Factory.CreateFromError(errorEvent);
     if (notification != null)
         Send(notification);
 }