internal void Populate(ExceptionalSettings settings)
            {
                var s = settings.Store;

                s.Type = Type;
                if (Path.HasValue())
                {
                    s.Path = Path;
                }
                if (ConnectionString.HasValue())
                {
                    s.ConnectionString = ConnectionString;
                }
                if (ConnectionStringName.HasValue())
                {
                    s.ConnectionString = ConfigurationManager.ConnectionStrings[ConnectionStringName]?.ConnectionString
                                         ?? throw new ConfigurationErrorsException("A connection string was not found for the connection string name provided: " + ConnectionStringName);
                }
                if (Size.HasValue)
                {
                    s.Size = Size.Value;
                }
                if (RollupSeconds.HasValue)
                {
                    s.RollupPeriod = TimeSpan.FromSeconds(RollupSeconds.Value);
                }
                if (BackupQueueSize.HasValue)
                {
                    s.BackupQueueSize = BackupQueueSize.Value;
                }
            }
        /// <summary>
        /// Binds an <see cref="IConfiguration"/> to an <see cref="ExceptionalSettings"/> object.
        /// This happens with a normal .Bind() followed by the complex type mappings manually.
        /// </summary>
        /// <param name="config">The <see cref="IConfigurationSection"/> to bind.</param>
        /// <param name="settings">The <see cref="ExceptionalSettings"/> to bind to.</param>
        public static void Bind(this IConfiguration config, ExceptionalSettings settings)
        {
            // Bind the simple types (almost everything)
            ConfigurationBinder.Bind(config, settings); // because we overrode .Bind() here

            // Now, explicitly bind the complex types
            var dataIncludePattern = config.GetValue <string>(nameof(ExceptionalSettings.DataIncludeRegex));

            if (!string.IsNullOrEmpty(dataIncludePattern))
            {
                settings.DataIncludeRegex = new Regex(dataIncludePattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
            }

            var ignoreRegexes = config.GetSection(nameof(ExceptionalSettings.Ignore))
                                .GetSection(nameof(ExceptionalSettingsBase.IgnoreSettings.Regexes))
                                .AsEnumerable();

            foreach (var ir in ignoreRegexes)
            {
                if (ir.Value != null)
                {
                    settings.Ignore.Regexes.Add(new Regex(ir.Value, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline));
                }
            }
            // If email is configured, hook it up
            if (settings.Email.ToAddress.HasValue())
            {
                settings.Register(new EmailNotifier(settings.Email));
            }
        }
 static Exceptional()
 {
     if (Settings == null)
     {
         Settings = new ExceptionalSettings();
     }
 }
        /// <summary>
        /// Asynchronously logs an exception to the configured error store, or the in-memory default store if none is configured.
        /// </summary>
        /// <param name="ex">The exception to log.</param>
        /// <param name="context">The HTTPContext to record variables from.  If this isn't a web request, pass <see langword="null" /> in here.</param>
        /// <param name="category">The category to associate with this exception.</param>
        /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine.</param>
        /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use.</param>
        /// <param name="applicationName">If specified, the application name to log with, if not specified the name in <see cref="ErrorStoreSettings.ApplicationName"/> is used.</param>
        /// <returns>The Error created, if one was created and logged, null if nothing was logged.</returns>
        /// <remarks>
        /// When dealing with a non web requests, pass <see langword="null" /> in for context.
        /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter.
        /// </remarks>
        public static Task <Error> LogAsync(
            this Exception ex,
            HttpContext context,
            string category      = null,
            bool rollupPerServer = false,
            Dictionary <string, string> customData = null,
            string applicationName = null)
        {
            if (Statics.IsLoggingEnabled)
            {
                ExceptionalSettings settings = null;
                try
                {
                    // If context is null, still log with a fallback...this is far better than going boom.
                    settings = context?.RequestServices.GetRequiredService <IOptions <ExceptionalSettings> >().Value ?? Exceptional.Settings;
                    // If we should be ignoring this exception, skip it entirely.
                    // Otherwise create the error itself, populating CustomData with what was passed-in.
                    var error = ex.GetErrorIfNotIgnored(settings, category, applicationName, rollupPerServer, customData);

                    if (error != null)
                    {
                        // Get everything from the HttpContext
                        error.SetProperties(context);

                        return(LogAsyncCore(error));
                    }
                }
                catch (Exception e)
                {
                    settings?.OnLogFailure?.Invoke(e);
                    Trace.WriteLine(e);
                }
            }
            return(Task.FromResult <Error>(null));
        }
Esempio n. 5
0
 private static void EnsureInit()
 {
     if (!(Settings is ExceptionalSettings))
     {
         Settings = new ExceptionalSettings();
     }
 }
 /// <summary>
 /// Configures existing settings (creating them if missing), also making them available for use globally.
 /// </summary>
 /// <param name="configSettings">The settings object to set for background settings.</param>
 public static void Configure(Action <ExceptionalSettings> configSettings)
 {
     _ = configSettings ?? throw new ArgumentNullException(nameof(configSettings));
     if (Settings == null)
     {
         Statics.Settings = Settings = new ExceptionalSettings();
     }
     configSettings?.Invoke(Settings);
 }
            internal void Populate(ExceptionalSettings settings)
            {
                var s = settings.LogFilters;

                foreach (LogFilter f in FormFilters)
                {
                    s.Form[f.Name] = f.ReplaceWith;
                }
                foreach (LogFilter c in CookieFilters)
                {
                    s.Cookie[c.Name] = c.ReplaceWith;
                }
            }
            /// <summary>
            /// Runs after deserialization, to populate <see cref="ExceptionalSettingsBase.Ignore"/>.
            /// </summary>
            /// <param name="settings">The <see cref="ExceptionalSettings"/> to populate.</param>
            internal void Populate(ExceptionalSettings settings)
            {
                var s = settings.Ignore;

                foreach (IgnoreRegex r in Regexes)
                {
                    if (r.Pattern.HasValue())
                    {
                        s.Regexes.Add(new Regex(r.Pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline));
                    }
                }
                foreach (IgnoreType t in Types)
                {
                    s.Types.Add(t.Type);
                }
            }
            internal void Populate(ExceptionalSettings settings)
            {
                var s = settings.Email;

                if (ToAddress.HasValue())
                {
                    s.ToAddress = ToAddress;
                }
                if (FromAddress.HasValue())
                {
                    s.FromAddress = FromAddress;
                }
                if (FromDisplayName.HasValue())
                {
                    s.FromDisplayName = FromDisplayName;
                }
                if (SMTPHost.HasValue())
                {
                    s.SMTPHost = SMTPHost;
                }
                if (SMTPPort.HasValue)
                {
                    s.SMTPPort = SMTPPort;
                }
                if (SMTPUserName.HasValue())
                {
                    s.SMTPUserName = SMTPUserName;
                }
                if (SMTPPassword.HasValue())
                {
                    s.SMTPPassword = SMTPPassword;
                }
                if (SMTPEnableSSL.HasValue)
                {
                    s.SMTPEnableSSL = SMTPEnableSSL.Value;
                }
                if (PreventDuplicates.HasValue)
                {
                    s.PreventDuplicates = PreventDuplicates.Value;
                }

                if (s.ToAddress.HasValue())
                {
                    settings.Register(new EmailNotifier(s));
                }
            }
        /// <summary>
        /// Trigger deserialization, which loads settings from the .config file.
        /// </summary>
        public static void LoadSettings()
        {
            if (Interlocked.CompareExchange(ref _loaded, 1, 0) == 0)
            {
                var settings = new ExceptionalSettings();
                var config   = ConfigurationManager.GetSection("Exceptional") as Settings;

                if (config.DataIncludePattern.HasValue())
                {
                    settings.DataIncludeRegex = new Regex(config.DataIncludePattern, RegexOptions.Singleline | RegexOptions.Compiled);
                }

                config.ErrorStore?.Populate(settings);
                config.Ignore?.Populate(settings);
                config.LogFilters?.Populate(settings);
                config.Email?.Populate(settings);
                settings.Store.ApplicationName = config.ApplicationName;

                Exceptional.Configure(settings);
            }
        }
Esempio n. 11
0
            internal void Populate(ExceptionalSettings settings)
            {
                var s = settings.LogFilters;

                foreach (LogFilter f in FormFilters)
                {
                    s.Form[f.Name] = f.ReplaceWith;
                }
                foreach (LogFilter c in CookieFilters)
                {
                    s.Cookie[c.Name] = c.ReplaceWith;
                }
                foreach (LogFilter h in HeaderFilters)
                {
                    s.Header[h.Name] = h.ReplaceWith;
                }
                foreach (LogFilter h in QueryStringFilters)
                {
                    s.QueryString[h.Name] = h.ReplaceWith;
                }
            }
        /// <summary>
        /// Logs an exception to the configured error store, or the in-memory default store if none is configured.
        /// </summary>
        /// <param name="ex">The exception to log.</param>
        /// <param name="context">The HTTPContext to record variables from.  If this isn't a web request, pass <see langword="null" /> in here.</param>
        /// <param name="category">The category to associate with this exception.</param>
        /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine.</param>
        /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use.</param>
        /// <param name="applicationName">If specified, the application name to log with, if not specified the name in <see cref="ErrorStoreSettings.ApplicationName"/> is used.</param>
        /// <returns>The Error created, if one was created and logged, null if nothing was logged.</returns>
        /// <remarks>
        /// When dealing with a non web requests, pass <see langword="null" /> in for context.
        /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter.
        /// </remarks>
        public static Error Log(
            this Exception ex,
            HttpContext context,
            string category      = null,
            bool rollupPerServer = false,
            Dictionary <string, string> customData = null,
            string applicationName = null)
        {
            if (Statics.IsLoggingEnabled)
            {
                ExceptionalSettings settings = null;
                try
                {
                    settings = context.RequestServices.GetRequiredService <IOptions <ExceptionalSettings> >().Value;
                    // If we should be ignoring this exception, skip it entirely.
                    // Otherwise create the error itself, populating CustomData with what was passed-in.
                    var error = ex.GetErrorIfNotIgnored(settings, category, applicationName, rollupPerServer, customData);

                    if (error != null)
                    {
                        // Get everything from the HttpContext
                        error.SetProperties(context);

                        if (error.LogToStore())
                        {
                            return(error);
                        }
                    }
                }
                catch (Exception e)
                {
                    settings?.OnLogFailure?.Invoke(e);
                    Trace.WriteLine(e);
                }
            }
            return(null);
        }
 /// <summary>
 /// Saves the given <paramref name="settings"/> as the global <see cref="Settings"/> available for use globally.
 /// These are intended to be used by global/background handlers where normal context access isn't available.
 /// </summary>
 /// <param name="settings">The settings object to set for background settings.</param>
 public static void Configure(ExceptionalSettings settings) =>
 Statics.Settings = Settings = settings ?? throw new ArgumentNullException(nameof(settings));