Fri*_*z45 4 asp.net-web-api serilog asp.net-core .net-6.0
我设置了一个 .Net 6 Core Minimal API,以使用 SeriLog 登录到 MS SQL Server。在我的类库中,仅当我修改类库中的构造函数时,我才能够使用 SeriLog 进行日志记录。我试图避免修改类库类或方法的构造函数。
根据我使用控制台应用程序的经验,如果我在主 Program.cs 中设置 SeriLog,那么我可以在类库中的任何类中使用日志记录,而无需将记录器传递给构造函数。因此,我可以在类库中的任何位置使用 Log.Information("my message") 并且它可以工作。我试图在 .Net 6 最小 API 项目中使用我的 Program.cs 实现相同的目标。
我觉得通过查看有关该主题的其他问题应该可以做到。特别是这个,其中的答案指出:
您无需在类库中执行任何操作。只有主应用程序具有组合根(应用程序生命周期中可以设置对象图的最早点)。
因此,根据上面的内容,在我的 API Program.CS 中,我有以下代码(我已在注释中指出了哪些有效,哪些无效):
//Configure SeriLog
builder.Logging.ClearProviders();
var appSettings = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var logDB =
builder.Configuration.GetSection("ConnectionStrings:Default").Value;
var sinkOpts = new MSSqlServerSinkOptions { TableName = "Logs" };
var columnOptions = new ColumnOptions();
var logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft",
Serilog.Events.LogEventLevel.Information)
.WriteTo.MSSqlServer(
connectionString: logDB,
sinkOptions: sinkOpts,
columnOptions: columnOptions,
appConfiguration: appSettings
).CreateLogger();
builder.Logging.AddSerilog(logger);
//Depency injection for Class Library method
//LoggerTestClass is a class in my Class Library project
builder.Services.AddScoped<ILoggerTestClass, LoggerTestClass>();
var app = builder.Build();
app.ConfigureTestAPI();
Run Code Online (Sandbox Code Playgroud)
方法“ConfigureTestAPI()”位于扩展类中,如下所示:
public static class API_Test
{
public static void ConfigureTestAPI(this WebApplication app)
//Extension method for app
{
app.MapGet("/test/", GetTest);
}
private static async Task<IResult> GetTest(int id,
ILogger<LoggerTestClass> logger, ILoggerTestClass testClass)
{
try
{
try
{
//This works
logger.LogInformation("Starting test now");
//This does NOT work
Log.Information("Using Log. directly");
testClass.Test(); //Call to class library method
logger.LogInformation("Test finished"); //Also works
return Results.Ok("OK");
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后这是我的类库中带有测试方法的类:
namespace TestingLib.Testing;
public class LoggerTestClass : ILoggerTestClass
{
private Microsoft.Extensions.Logging.ILogger _logger;
public LoggerTestClass(ILogger<LoggerTestClass> logger)
{
_logger = logger;
}
public void Test()
{
try
{
//Does not work
Log.Information("Test logging from class library using Log.");
//Does not work
Log.Logger.Information("In Test Class in DLL. Trying loging with [Log.Logger.Information]");
//This works
_logger.LogInformation("In Test Class in DLL. Trying loging with [_logger.LogInformation]");
}
catch (Exception ex)
{
Log.Error("An error in class library");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发现问题出在我的 API Program.cs 文件中缺少一行代码。我需要添加:“Log.Logger = logger;” 设置 SeriLog 记录器后。
工作解决方案的代码如下。
在我的 .NET6 API Program.cs 文件中,我有以下内容:
var builder = WebApplication.CreateBuilder(args);
//Configure SeriLog
builder.Logging.ClearProviders();
var appSettings = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var logDB = builder.Configuration.GetSection("ConnectionStrings:Default").Value;
var sinkOpts = new MSSqlServerSinkOptions { TableName = "Logs" };
var columnOptions = new ColumnOptions
{
AdditionalColumns = new Collection<SqlColumn>
{
new SqlColumn("UserID", SqlDbType.Int),
new SqlColumn("RunTag", SqlDbType.NVarChar),
new SqlColumn("CustomType", SqlDbType.NVarChar)
}
};
var logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Information)
.WriteTo.MSSqlServer(
connectionString: logDB,
sinkOptions: sinkOpts,
columnOptions: columnOptions,
appConfiguration: appSettings
).CreateLogger();
builder.Logging.AddSerilog(logger);
//NOTE that this is not needed
//builder.Services.AddScoped<TestingLib.Testing.ILoggerTestClass, TestingLib.Testing.LoggerTestClass>();
Run Code Online (Sandbox Code Playgroud)
然后在这个文件的下方我有这个:
Log.Logger = logger; //This was the line I was missing!
var app = builder.Build();
Run Code Online (Sandbox Code Playgroud)
我调用类库的 API Get 方法现在看起来像这样(如果与问题中的原始方法相比,您将看到不再需要传递 ILogger):
private static async Task<IResult> GetTest(int id)
{
try
{
try
{
string runTag = "In API GetTest(id)";
string custom = "Calling from API method";
Log.Information("{Message}-{RunTag}-{CustomType}", "Message logging in API method", runTag, custom);
//Call to Class Library Method - no need to pass ILogger
LoggerTestClass testClass = new LoggerTestClass();
testClass.Test();
return Results.Ok("OK");
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
最后,这是我的类库中的完整测试类。类库包含对 SeriLog 的引用:
using Serilog;
namespace TestingLib.Testing;
public class LoggerTestClass //: ILoggerTestClass
{
public LoggerTestClass()
{
//No need to pass in ILogger to class
}
public void Test()
{
try
{
string runTag = "In Class Library Method)";
string custom = "Calling class library method Test()";
Log.Information("{Message}-{RunTag}-{CustomType}", "Message logging in Class Library", runTag, custom);
}
catch (Exception ex)
{
Log.Error("An error in class library");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发现这非常适合我的项目。类库中的日志记录直接进入我的 SQL 数据库,其中包含自定义列等。
| 归档时间: |
|
| 查看次数: |
5922 次 |
| 最近记录: |