簡體   English   中英

自定義NLog LayoutRenderer,帶有使用依賴注入的構造函數

[英]Custom NLog LayoutRenderer with constructor using Dependency Injection

我正在嘗試編寫一個自定義的LayoutRenderer來記錄從對象讀取的數據,但似乎NLog在依賴注入時無法正常工作。

這是我的CustomLayoutRenderer:

[LayoutRenderer("custom-value")]
public class CustomLayoutRenderer : LayoutRenderer
{
    private readonly RequestContext _context;

    public CustomLayoutRenderer(RequestContext context)
    {
        _context = context;
    }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(_context.CustomValue);
    }
}

它正在使用此RequestContext對象:

public class RequestContext
{
    public string CustomValue { get; set; } = "Valid custom value";
}

我也在連接DI,配置NLog並在Startup.cs中注冊我的LayoutRenderer:

    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddScoped<RequestContext>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        LayoutRenderer.Register<CustomLayoutRenderer>("custom-value");

        loggerFactory.AddNLog();
        app.AddNLogWeb();
        env.ConfigureNLog("nlog.config");
        // ...
    }

然后我嘗試在nlog.config中使用我的${custom-value} ,但是我在AddNLog()調用時遇到錯誤:

2017-02-03 13:08:08.0284錯誤解析[project-folder] \\ bin \\ Debug \\ net452 \\ win7-x64 \\ NLog.config中的配置失敗。 例外:NLog.NLogConfigurationException:解析[project-folder] \\ bin \\ Debug \\ net452 \\ win7-x64 \\ NLog.config時出現異常。 NLog.NLogConfigurationException:無法訪問類型為:ATest.CustomLayoutRenderer的構造函數。 是否已獲得所需的許可? 在NLog.Internal.FactoryHelper.CreateInstance(Type t)...

筆記

我之所以這樣做是因為我想記錄一些只能從控制器訪問的信息(比如TraceIdentifier,URL的一部分,以及一些特定於請求的自定義內容)。 RequestContext中的值將在獲取請求時由控制器設置。

以下渲染器按預期工作,這讓我覺得這是一個依賴注入問題:

[LayoutRenderer("custom-value")]
public class CustomLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append("Hello, World!");
    }
}

我確實看到了這個NLog錯誤,但它現在被標記為已修復,這就是我在這里而不是在那里發布的原因。

為了完整起見,這是我添加到我的project.json

"dependencies": {
    ...
    "NLog.Extensions.Logging": "1.0.0-*",
    "NLog.Web.AspNetCore": "4.3.0"
},

兩種方法:

1)DI意識到

你可以讓NLog DI知道。 添加到您的startup.cs:

ConfigurationItemFactory.Default.CreateInstance = (Type type) =>
{ 
    // your custom target. Could be a better check ;)
    if(type == typeof(CustomLayoutRenderer))
      return new CustomLayoutRenderer(...); // TODO get RequestContext
    else
      return Activator.CreateInstance(type); //default
};

這是一種更通用的方法。

2)AspNetMvcLayoutRendererBase

或者,從AspNetMvcLayoutRendererBase (NLog.Web.AspNetCore)覆蓋並使用HttpContextAccessor?.HttpContext?.TryGetRequest()並且不添加構造函數。

這僅在需要HttpContext

[LayoutRenderer("custom-value")]
public class MyCustomRenderer : AspNetLayoutRendererBase
{
    protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
    {
        var httpRequest = HttpContextAccessor?.HttpContext?.TryGetRequest();

        if (httpRequest == null)
            return;


        builder.Append(httpRequest.Something); //TODO

    }
}

查看FactoryHelper的NLog源代碼。 看起來您必須提供默認構造函數。

您可能還想考慮使用NLog.Web包中的布局渲染。 有幾個可以獲取特定於請求的信息。 甚至可以選擇使用${aspnet-Item}布局從HttpContext記錄內容

如果這不適合您,也許“有狀態”記錄器將像我在這里給出的答案一樣: https//stackoverflow.com/a/32857908/1289052

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM