<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using System.Text.RegularExpressions;

using Serilog.Configuration;
using Serilog.Core;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Settings.Configuration.Assemblies;

namespace Serilog.Settings.Configuration
{
    class ConfigurationReader : IConfigurationReader
    {
        const string LevelSwitchNameRegex = @"^\$[A-Za-z]+[A-Za-z0-9]*$";

        readonly IConfigurationSection _section;
        readonly IReadOnlyCollection<Assembly> _configurationAssemblies;
        readonly ResolutionContext _resolutionContext;

        public ConfigurationReader(IConfigurationSection configSection, AssemblyFinder assemblyFinder, IConfiguration configuration = null)
        {
            _section = configSection ?? throw new ArgumentNullException(nameof(configSection));
            _configurationAssemblies = LoadConfigurationAssemblies(_section, assemblyFinder);
            _resolutionContext = new ResolutionContext(configuration);
        }

        // Used internally for processing nested configuration sections -- see GetMethodCalls below.
        internal ConfigurationReader(IConfigurationSection configSection, IReadOnlyCollection<Assembly> configurationAssemblies, ResolutionContext resolutionContext)
        {
            _section = configSection ?? throw new ArgumentNullException(nameof(configSection));
            _configurationAssemblies = configurationAssemblies ?? throw new ArgumentNullException(nameof(configurationAssemblies));
            _resolutionContext = resolutionContext ?? throw new ArgumentNullException(nameof(resolutionContext));
        }

        public void Configure(LoggerConfiguration loggerConfiguration)
        {
            ProcessLevelSwitchDeclarations();
            ProcessFilterSwitchDeclarations();

            ApplyMinimumLevel(loggerConfiguration);
            ApplyEnrichment(loggerConfiguration);
            ApplyFilters(loggerConfiguration);
            ApplyDestructuring(loggerConfiguration);
            ApplySinks(loggerConfiguration);
            ApplyAuditSinks(loggerConfiguration);
        }

        void ProcessFilterSwitchDeclarations()
        {
            var filterSwitchesDirective = _section.GetSection("FilterSwitches");

            foreach (var filterSwitchDeclaration in filterSwitchesDirective.GetChildren())
            {
                var filterSwitch = LoggingFilterSwitchProxy.Create();
                if (filterSwitch == null)
                {
                    SelfLog.WriteLine($"FilterSwitches section found, but Serilog.Filters.Expressions isn't referenced.");
                    break;
                }

                var switchName = filterSwitchDeclaration.Key;
                // switchName must be something like $switch to avoid ambiguities
                if (!IsValidSwitchName(switchName))
                {
                    throw new FormatException($"\"{switchName}\" is not a valid name for a Filter Switch declaration. Filter switch must be declared with a '$' sign, like \"FilterSwitches\" : {{\"$switchName\" : \"{{FilterExpression}}\"}}");
                }

                SetFilterSwitch(throwOnError: true);
                SubscribeToFilterExpressionChanges();<commit_msg>selflog message fix<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using System.Text.RegularExpressions;

using Serilog.Configuration;
using Serilog.Core;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Settings.Configuration.Assemblies;

namespace Serilog.Settings.Configuration
{
    class ConfigurationReader : IConfigurationReader
    {
        const string LevelSwitchNameRegex = @"^\$[A-Za-z]+[A-Za-z0-9]*$";

        readonly IConfigurationSection _section;
        readonly IReadOnlyCollection<Assembly> _configurationAssemblies;
        readonly ResolutionContext _resolutionContext;

        public ConfigurationReader(IConfigurationSection configSection, AssemblyFinder assemblyFinder, IConfiguration configuration = null)
        {
            _section = configSection ?? throw new ArgumentNullException(nameof(configSection));
            _configurationAssemblies = LoadConfigurationAssemblies(_section, assemblyFinder);
            _resolutionContext = new ResolutionContext(configuration);
        }

        // Used internally for processing nested configuration sections -- see GetMethodCalls below.
        internal ConfigurationReader(IConfigurationSection configSection, IReadOnlyCollection<Assembly> configurationAssemblies, ResolutionContext resolutionContext)
        {
            _section = configSection ?? throw new ArgumentNullException(nameof(configSection));
            _configurationAssemblies = configurationAssemblies ?? throw new ArgumentNullException(nameof(configurationAssemblies));
            _resolutionContext = resolutionContext ?? throw new ArgumentNullException(nameof(resolutionContext));
        }

        public void Configure(LoggerConfiguration loggerConfiguration)
        {
            ProcessLevelSwitchDeclarations();
            ProcessFilterSwitchDeclarations();

            ApplyMinimumLevel(loggerConfiguration);
            ApplyEnrichment(loggerConfiguration);
            ApplyFilters(loggerConfiguration);
            ApplyDestructuring(loggerConfiguration);
            ApplySinks(loggerConfiguration);
            ApplyAuditSinks(loggerConfiguration);
        }

        void ProcessFilterSwitchDeclarations()
        {
            var filterSwitchesDirective = _section.GetSection("FilterSwitches");

            foreach (var filterSwitchDeclaration in filterSwitchesDirective.GetChildren())
            {
                var filterSwitch = LoggingFilterSwitchProxy.Create();
                if (filterSwitch == null)
                {
                    SelfLog.WriteLine($"FilterSwitches section found, but neither Serilog.Expressions nor Serilog.Filters.Expressions is referenced.");
                    break;
                }

                var switchName = filterSwitchDeclaration.Key;
                // switchName must be something like $switch to avoid ambiguities
                if (!IsValidSwitchName(switchName))
                {
                    throw new FormatException($"\"{switchName}\" is not a valid name for a Filter Switch declaration. Filter switch must be declared with a '$' sign, like \"FilterSwitches\" : {{\"$switchName\" : \"{{FilterExpression}}\"}}");
                }

                SetFilterSwitch(throwOnError: true);
                SubscribeToFilterExpressionChanges();
{'fraction_non_alphanumeric': 0.07350600491969324, 'fraction_numerical': 0.0005787874403125452, 'mean_word_length': 3.0634920634920637, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3754322', 'n_tokens_mistral': 1558, 'n_tokens_neox': 1490, 'n_words': 350}