目录
在本教程中,我们将学习如何在ASP.NET Core Web API中使用Serilog实现日志记录,我们将使用Serilog库将日志写入滚动文件,并了解如何将日志记录实例注入到API项目的不同类中,以帮助我们开始写入日志。我们还将学习如何编写自己的自定义接收器。
日志记录是开发中最重要和最关键的功能之一,它允许开发人员和产品所有者对应用程序错误进行故障排除和分析。使用Serilog或任何其他日志记录提供程序,每当应用程序写入全面而广泛的日志时,您将能够跟踪发生的任何错误或问题,这将极大地帮助找到问题的解决方案。
在本教程中,我们将学习如何在ASP.NET Core Web API中使用Serilog实现日志记录。
在ASP.NET Core Web API中使用Serilog引入日志记录非常简单直接。事实上,Serilog有一个特定的NuGet包,它是为ASP.NET Core项目量身定制的。
因此,让我们从教程开始。
创建ASP.NET Core Web API项目
打开Visual Studio 2022,并在ASP.NET Core Web API中创建新项目。给它起一个名字,比如:LoggingWithSerilog
。
选择.NET 6,然后按“创建”。
加载模板项目后,右键单击解决方案资源管理器中的项目名称,然后选择“管理NuGet包”,搜索“Serilog”,然后选择“安装 Serilog.AspNetCore
”。
此NuGet包将Serilog接收器(包括调试、控制台和文件)的依赖项捆绑在一起。在本教程中,我们主要对文件接收器感兴趣,因为我们将在滚动文件中转储日志。
Serilog配置
现在打开您的appsettings.json文件并添加以下部分:
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Error",
"System": "Debug"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "C:\\Web Apis\\Logs\\LoggingWithSerilog\\RestApiLog.log",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}
[{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}",
"rollOnFileSizeLimit": true,
"fileSizeLimitBytes": 4194304,
"retainedFileCountLimit": 15,
"rollingInterval": "Minute"
}
}
]
}
在Program.cs文件中,添加以下代码:
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);
现在,为了能够从控制器内部写入日志,我们需要使用注入到控制器构造函数的记录器实例。
打开WeatherController
,在构造函数中,您会注意到已经有一个注入的记录器参数。
private readonly ILogger<weatherforecastcontroller> logger;
public WeatherForecastController(ILogger<weatherforecastcontroller> logger)
{
this.logger = logger;
}
现在在此GetWeatherForecast
端点中,将模板代码替换为以下行:
logger.LogDebug("Inside GetWeatherForecast endpoint");
var response = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
logger.LogDebug($"The response for the get weather forecast is
{JsonConvert.SerializeObject(response)}");
return response;
请注意,这是 Newtonsoft.json 包中使用的JsonConvert
类,因此如果您执行快速操作或Ctrl+.,您将获得建议安装所需NuGet包的菜单,您可以选择安装它:
现在我们已经设置好了Serilog并准备开始编写日志,让我们运行一个快速测试以查看它是否有效。
按 F5,将显示默认浏览器并呈现API的Swagger UI页面。
日志记录异常
日志记录最重要的用例是跟踪和排除错误和异常,一旦记录了异常详细信息,您将更容易知道错误发生的时间、地点和原因,这将导致更快地解决问题,尤其是当此类问题在您的生产应用程序上时。
要在整个API项目中进行适当的异常处理,建议您添加一个处理异常的中间件,并在内部注入记录器实例并实现日志记录代码。
此中间件将拦截在端点执行期间发生的任何异常,将返回带有响应的正确http状态代码,然后它将记录异常详细信息。
所以在你的项目中,让我们添加一个名为 Middleware 的文件夹,在其中,让我们创建一个名为的ExceptionHandlingMiddleware
新类。
using Newtonsoft.Json;
using System.Net;
namespace LoggingWithSerilog.Middleware
{
public class ExceptionHandlingMiddleware
{
public RequestDelegate requestDelegate;
private readonly ILogger<ExceptionHandlingMiddleware> logger;
public ExceptionHandlingMiddleware
(RequestDelegate requestDelegate, ILogger<ExceptionHandlingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await requestDelegate(context);
}
catch (Exception ex)
{
await HandleException(context, ex);
}
}
private Task HandleException(HttpContext context, Exception ex)
{
logger.LogError(ex.ToString());
var errorMessageObject =
new { Message = ex.Message, Code = "system_error" };
var errorMessage = JsonConvert.SerializeObject(errorMessageObject);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return context.Response.WriteAsync(errorMessage);
}
}
}
此中间件将执行两个任务:处理在任何端点执行期间可能发生的任何异常,并返回包含错误代码和消息的通用响应,第二个任务将记录使用配置的日志记录提供程序(Serilog)发生的异常。
现在这里唯一剩下的就是将新的中间件注入到应用程序的管道中,所以打开你的Program.cs文件,让我们在builder.Build()
方法调用后添加以下行:
app.UseMiddleware(typeof(ExceptionHandlingMiddleware));
接下来,让我们通过在端点内部抛出任意异常来使GetWeatherForecast
端点失败:
throw new Exception("Failed to retrieve data");
运行应用程序并测试调用Get WeatherForecast
终结点:
现在让我们看看Serilog是否有效并将日志记录详细信息添加到文件接收器中:
打开文件以查看转储的日志:
Serilog接收器
Serilog将接收器作为插件的概念,捆绑了许多预定义的接收器,您可以配置并直接使用这些接收器开始写入日志。
此类接收器的范围从简单的接收器(如控制台或文件)到更高级的接收器(如ElasticSearch)或可以直接连接日志并将其转储到SQL Server,MongoDB等数据库或Azure Analytics,Amazon CloudWatch等云日志记录服务或Azure Cosmos DB或Aws Dynamo DB等云数据库的接收器,甚至您可以找到将日志转储到Windows的事件日志中的接收器等等其他选项。
在本教程中,我们学习了如何将ASP.NET Core Web API与Serilog连接,你可以尝试不同类型的Serilog接收器。
查看以下链接以查看提供的Serilog接收器的完整列表。
自定义Serilog接收器
在某些情况下,您可能需要编写自己的接收器,Serilog使您能够通过在自己的类中实现ILogEventSink
并在Emit
方法中编写所需的自定义日志记录代码来实现此目的。
让我们创建一个自定义接收器,添加一个名为 Sinks 的文件夹,并创建一个名称为CustomSink
的新类。
using Serilog.Core;
using Serilog.Events;
namespace LoggingWithSerilog.Sinks
{
public class CustomSink : ILogEventSink
{
public void Emit(LogEvent logEvent)
{
var result = logEvent.RenderMessage();
Console.ForegroundColor = logEvent.Level switch
{
LogEventLevel.Debug => ConsoleColor.Green,
LogEventLevel.Information => ConsoleColor.Blue,
LogEventLevel.Error => ConsoleColor.Red,
LogEventLevel.Warning => ConsoleColor.Yellow,
_ => ConsoleColor.White,
};
Console.WriteLine($"{logEvent.Timestamp} - {logEvent.Level}: {result}");
}
}
}
在上面的示例中,我们根据日志的级别更改控制台文本颜色。
为了能够将应用程序配置为使用新的自定义接收器,我们必须为新的自定义接收器定义扩展方法。
using Serilog;
using Serilog.Configuration;
namespace LoggingWithSerilog.Sinks
{
public static class CustomSinkExtensions
{
public static LoggerConfiguration CustomSink(
this LoggerSinkConfiguration loggerConfiguration)
{
return loggerConfiguration.Sink(new CustomSink());
}
}
}
现在,最后一部分是通过在Serilog日志记录配置中引入新的自定义接收器,将Program.cs中的组件粘合在一起。
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.WriteTo.CustomSink()
.Enrich.FromLogContext()
.CreateLogger();
如上所示,我们使用了两个接收器,一个来自配置(文件接收器),另一个使用使用WriteTo自定义接收器扩展方法定义的自定义接收器。
现在让我们运行并在正在运行的控制台上查看结果:
如果打开日志文件夹,仍可以看到文件接收器将日志写入滚动文件:
总结
在本教程中,我们学习了如何在Core Web API中使用Serilog ASP.NET日志记录。此外,我们还学习了如何编写中间件来处理所有异常以及如何使用Serilog记录它们。
此外,我们还介绍了提供的不同Serilog接收器,我们设法创建了一个新的自定义接收器,该接收器将写入控制台并根据日志级别更改颜色。
我希望本教程向您正确介绍Serilog。请随时给我留下评论,并与您的网络和同事分享教程。
您可以在我的 GitHub帐户中找到源代码。
本文最初发表于 Logging with Serilog in ASP.NET Core Web API - Coding Sonata
https://www.codeproject.com/Articles/5344667/Logging-with-Serilog-in-ASP-NET-Core-Web-API