使用数据库在 ASP.NET Core 5.0 应用程序中使用 Serilog 实现日志记录

Implement Logging Using Serilog In ASP.NET Core 5.0 Application With Database

在我的 asp.net 核心 5.0 应用程序中,每当我尝试使用 serilog 执行日志记录并将日志保存到我的数据库时。但是,当我 运行 api 时,它告诉我:

System.TypeInitializationException HResult=0x80131534 Message=The type initializer for 'PaymentService.API.Program' threw an exception. Source=PaymentService.API StackTrace: at PaymentService.API.Program.get_Configuration() in API\Program.cs:line 21 at PaymentService.API.Program.Main(String[] args) in API\Program.cs:line 34

This exception was originally thrown at this call stack: [External Code]

Inner Exception 1: FormatException: Could not parse the JSON file.

Inner Exception 2: JsonReaderException: Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 7 | BytePositionInLine: 1.

第21行是:

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
                            .SetBasePath(Directory.GetCurrentDirectory())
                            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
                            .Build();

第 34 行是:

string connectionString = Configuration.GetConnectionString("Default");

我是新手,但我是否必须对“ASPNETCORE_ENVIRONMENT”进行任何配置?

之后,我尝试将自定义列添加到名为 CorrelationId 的数据库中,并将 CorrelationId 发送到其特定列。我是按照这个 tutorial 来这样做的,但是我卡在了他们想要捕获用户以获取日志的步骤上。我想做同样的事情,但对日志使用 CorrelationId

Program.cs:

public class Program
    {

        public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
                            .SetBasePath(Directory.GetCurrentDirectory())
                            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
                            .Build();

        public static void Main(string[] args)
        {
            

            string connectionString = Configuration.GetConnectionString("Default");

            var columnOptions = new ColumnOptions
            {
                AdditionalColumns = new Collection<SqlColumn>
                {
                    new SqlColumn("CorrelationId", SqlDbType.NVarChar)
                }
            }; // through this columnsOptions we can dynamically add custom columns which we want to add in the db

            Log.Logger = new LoggerConfiguration()
                .Enrich.FromLogContext()
                .WriteTo.MSSqlServer(connectionString, sinkOptions: new MSSqlServerSinkOptions { TableName = "PaymentLogs" }
                , null, null, LogEventLevel.Information, null, columnOptions: columnOptions, null, null)
                .CreateLogger();

            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>().UseSerilog();
                });
    }

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.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "PaymentService.API", Version = "v1" });
            });

            services.AddHttpContextAccessor();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

            app.UseMiddleware<LogHeaderMiddleware>();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PaymentService.API v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

  /*          app.Use(async (httpContext, next) => 
            {
                var correlationId = httpContext.Session. // need to find a way to map correlationId and send it to the logs
            })*/

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

appsettings.json

{
  "ConnectionStrings": {
    "Default": "Data Source=.\SQLExpress;Database=ElasticSearchService;Trusted_Connection=True;"
  },
  "Serilog": {
    "MinimumLevel": "Information",
  "AllowedHosts": "*"
}

PaymentController

[Route("api/[controller]")]
    [ApiController]
    public class PaymentController : ControllerBase
    {

        private readonly ILogger<PaymentServicesController> _logger;

        public PaymentServicesController(ILogger<PaymentServicesController> logger)
        {
            _logger = logger;
        }

        // GET: api/<PaymentServices>
        [HttpGet]
        [Route("payment")]
        public void MakePayment()
        {

            _logger.LogInformation("PAYMENT METHOD INVOLKED!!!");


        }
       
    }

此处 header 将保存我需要的 correlationId,以便我可以将其发送到数据库。

public class LogHeaderMiddleware
    {
        private readonly RequestDelegate _next;

        public LogHeaderMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var header = context.Request.Headers["CorrelationId"];

            if (header.Count > 0)
            {
                var logger = context.RequestServices.GetRequiredService<ILogger<LogHeaderMiddleware>>();

                using (logger.BeginScope("{@CorrelationId}", header[0]))
                {
                    await _next(context);
                }
            }
            else
            {
                await _next(context);
            }
        }
    }

您的 JSON 文件中缺少 Serilog 对象的右大括号,导致格式不正确 JSON。因此出现异常:内部异常 1:FormatException:无法解析 JSON 文件。