[英]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"
},
兩種方法:
你可以讓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
};
這是一種更通用的方法。
或者,從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.