Дублирующее имя при настройке нескольких файлов журнала в соответствии с уровнем журнала в appSettings.json - PullRequest
0 голосов
/ 27 марта 2019

Недавно я использую Serilog в проекте asp.net core 2.1, конфигурация настроена в файле appsettings.json, я хотел бы разделить журналы в разных файлах журналов в соответствии с уровнем журнала, поэтому я попытался выполнить следующее безуспешно:

appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "..."
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Error",
        "System": "Warning"
      }
    },
    "WriteTo": {
      "Console-Sink-1": {
        "Name": "Console",
        "Args": {
          "restrictedToMinimumLevel": "Debug",
          "outputTemplate": "===> {Timestamp:HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
        }
      },
      "File-Sink-1": {
        "Name": "RollingFile",
        "Args": {
          "restrictedToMinimumLevel": "Debug",
          "pathFormat": "D:\\SicotX\\Log-debug-{Date}.txt",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}|[{Level}]|{Message}{NewLine}{Exception}"
        }
      },
      "File-Sink-2": {
        "Name": "RollingFile",
        "Args": {
          "restrictedToMinimumLevel": "Information",
          "pathFormat": "D:\\SicotX\\Log-info-{Date}.txt",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}|[{Level}]|{Message}{NewLine}{Exception}"
        }
      },
      "File-Sink-3": {
        "Name": "RollingFile",
        "Args": {
          "restrictedToMinimumLevel": "Error",
          "pathFormat": "D:\\SicotX\\Log-error-{Date}.txt",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}|[{Level}]|{Message}{NewLine}{Exception}"
        }
      }
    }
  },
  "AllowedHosts": "*",
  "CustomSettings": {
    "Cultura": "es-ES",
    "ReportServer": "http://192.168.10.169:888"
  },
  "EmailSettings": {
    "Status": "0",
    "Host": "smtp.mail.yahoo.com",
    "Port": "587",
    "User": "myUser",
    "Password": "",
    "From": "myUser@yahoo.com",
    "To": "myUser@yahoo.com",
    "CC": ""
  }
}

appsettings.Development.json:

{
}

Следующие пакеты nuget, установленные для выполнения serilog:

enter image description here

Конфигурация в program.cs:

public class Program
{
    private static string _environmentName;

    public static void Main(string[] args)
    {
        var webHost = CreateWebHost(args);

        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{_environmentName}.json", optional: true)
                    .Build();

        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .CreateLogger();

        webHost.Run();
    }

    public static IWebHost CreateWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureLogging((hostingContext, config) =>
            {
                config.ClearProviders();
                _environmentName = hostingContext.HostingEnvironment.EnvironmentName;
            })
            .UseSetting("https_port", "8080")
            .UseStartup<Startup>()
            .UseSerilog()
            .Build();
}

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders()
                .AddErrorDescriber<IdentityErrorMessageDescriber>();

        services.Configure<IdentityOptions>(options =>
        {
            options.Lockout.AllowedForNewUsers = false;
            options.Lockout.MaxFailedAccessAttempts = 5;
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1440);
            options.Password.RequireDigit = true;
            options.Password.RequireLowercase = true;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = true;
            options.Password.RequiredLength = 8;
            options.Password.RequiredUniqueChars = 1;
            options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        });

        services.AddAuthentication(); // Como se gestiona a través de Cookies, por defecto (esto se puede cambiar), el nombre del esquema de la cookie es .AspNetCore.Cookies
        services.AddAuthorization(options =>
        {
            options.AddPolicy(nameof(RolePolicy.Administradores),
                                     policy => policy.RequireRole(
                                               nameof(RoleAuthorization.SuperUsuario), 
                                               nameof(RoleAuthorization.Administrador)
                                     )
                             );
        });

        services.ConfigureApplicationCookie(options =>
        {
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
            options.LoginPath = new PathString("/Identity/Account/Login");
            options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
            options.AccessDeniedPath = new PathString("/Identity/Account/AccessDenied");
            options.LogoutPath = new PathString("/Identity/Account/Logout");
            options.SlidingExpiration = true;
        });

        // Servicio de Correo Electrónico
        services.Configure<EmailOptions>(Configuration.GetSection("EmailSettings"));
        // Servicios de Localización y Globalización (Idiomas)
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo(Configuration.GetSection("CustomSettings")["Cultura"]),
                new CultureInfo("en-US")
            };
            options.DefaultRequestCulture = new RequestCulture(supportedCultures[0]);
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
            options.RequestCultureProviders = new List<IRequestCultureProvider>() { new CookieRequestCultureProvider() };
        });
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddSingleton<MenuLocalizer>();
        services.AddSingleton<SharedLocalizer>();
        services.AddTransient<IEmailSender, EmaileSender>();
        services.AddAutoMapper(options => options.ValidateInlineMaps = false);
        services.AddMvc(options =>
                {
                    options.CacheProfiles.Add("DefaultNoCache",
                                                new CacheProfile()
                                                {
                                                    Duration = 0,
                                                    Location = ResponseCacheLocation.None,
                                                    NoStore = true
                                                }
                    );

                    var policy = new AuthorizationPolicyBuilder()
                                        .RequireAuthenticatedUser()
                                        .Build();
                    options.Filters.Add(new AuthorizeFilter(policy));
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                .AddViewLocalization(options => options.ResourcesPath = "Resources")
                .AddDataAnnotationsLocalization()
                .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
                .AddFluentValidation(options => {
                    options.RegisterValidatorsFromAssemblyContaining<Startup>();
                    options.RegisterValidatorsFromAssemblyContaining<SharedLocalizer>();
                });

        services.AddKendo();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/error/500");
            app.UseHsts();
        }

        app.Use(async (ctx, next) =>
        {
            await next();

            if (ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
            {
                //Re-execute the request so the user gets the error page
                string originalPath = ctx.Request.Path.Value;
                ctx.Items["originalPath"] = originalPath;
                ctx.Request.Path = "/error/404";
                await next();
            }
        });

        var locOpt = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
        app.UseRequestLocalization(locOpt.Value);
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "areas",
                template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
            );
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}"
            );
        });
    }
}

Ошибка: элемент с таким же ключом уже добавлен. Ключ: RollingFile

Трассировка стека:

at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Serilog.Settings.Configuration.ConfigurationReader.GetMethodCalls(IConfigurationSection directive)
   at Serilog.Settings.Configuration.ConfigurationReader.ApplySinks(LoggerConfiguration loggerConfiguration, Assembly[] configurationAssemblies)
   at Serilog.Configuration.LoggerSettingsConfiguration.Settings(ILoggerSettings settings) in C:\projects\serilog\src\Serilog\Configuration\LoggerSettingsConfiguration.cs:line 44
   at SicotX.Program.Main(String[] args) in E:\Projects\Repositories\SicotX\Frontend\SicotX\Program.cs:line 42

Буду признателен за любую подсказку.

...