首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从.NET 6最小API调用的类库方法的Serilog日志记录

从.NET 6最小API调用的类库方法的Serilog日志记录
EN

Stack Overflow用户
提问于 2022-02-23 01:40:48
回答 1查看 3.1K关注 0票数 1

我设置了一个.Net 6来使用SeriLog登录到。在类库中,只有在修改类库中的构造函数时,我才能使用SeriLog进行日志记录。我试图避免修改类库类或方法的构造函数。

在我使用控制台应用程序的经验中,如果我在我的主Program.cs中设置了Program.cs,那么我可以在类库中的任何类中使用日志记录,而无需将记录器传递给构造函数。因此,我可以在类库中的任何地方使用Log.Information(“我的消息”),它可以工作。我正试图在我的Program.cs 6最小API项目中实现同样的目标。

我觉得从这个题目上看其他问题是可以做到的。特别是this one,其中的答案指出:

,您不必在类库中做任何事情。只有主应用程序有一个组合根(应用程序生命周期中的最早点,您可以设置对象图)。

因此,在我的API Program.CS中,我有下面的代码(我已经指出了哪些可以工作,哪些不在注释中):

代码语言:javascript
复制
    //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();

方法"ConfigureTestAPI()“位于扩展类中,如下所示:

代码语言:javascript
复制
    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);
        }
     }
    }

最后,这里是类库中带有测试方法的类:

代码语言:javascript
复制
        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");
            }
        }
    
    }
EN

回答 1

Stack Overflow用户

发布于 2022-02-23 21:44:20

我发现问题在于我的API Program.cs文件中缺少一行代码。我需要在设置Log.Logger记录器之后添加:“SeriLog = logger;”。

工作解决方案的代码如下。

在我的.NET6 API Program.cs文件中,我有以下内容:

代码语言:javascript
复制
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>();

在这个文件中,我有这样一个:

代码语言:javascript
复制
Log.Logger = logger; //This was the line I was missing!

var app = builder.Build();

调用类库的API Get方法现在如下所示(如果与问题中的原始方法相比,您将看到不再需要传递ILogger ):

代码语言:javascript
复制
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);
        }
    }

最后,这里是我的类库中的完整测试类。类库包含对SeriLog的引用:

代码语言:javascript
复制
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");
        }
    }

}

我发现这个很适合我的项目。类库中的日志直接通过自定义列进入我的SQL数据库,等等。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71230390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档