У меня есть метод расширения для поддержки дополнительных уровней журнала, подобный этому:
public static void Duration(this ILogger source, string message)
{
var logEventInfo = new LogEventInfo(LogLevel.Warn, source.Name, message);
logEventInfo.Properties.Add("specialLevel", "Duration");
source.Log(logEventInfo);
}
Есть одна проблема с этим.
Мой $ {CallSite} теперь всегда сообщает Duration.Есть ли способ повысить уровень стека вызовов на единицу, чтобы получить метод, который вызывает Duration, или мне нужен собственный рендерер для этого?
Что я пробовал до сих пор:
logEventInfo.Properties.Add("skipFrames", 1);
и
layout="${formattedDate} ${callsite:skipFrames=${event-properties:item=skipFrames}} ${message}"
Уродливый обходной путь:
[LayoutRenderer("customCallSite")]
public class CustomCallSiteLayoutRenderer : CallSiteLayoutRenderer
{
private readonly CallSiteLayoutRenderer DefaultRenderer = new CallSiteLayoutRenderer();
/// <inheritdoc />
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
if (!logEvent.HasProperties)
{
builder.Append(DefaultRenderer.Render(logEvent));
return;
}
if (logEvent.Properties["skipFrames"] is int skipFrames)
{
builder.Append(GetRenderer(skipFrames).Render(logEvent));
}
else
{
builder.Append(logEvent.Level);
}
}
private static readonly ConcurrentDictionary<int, CallSiteLayoutRenderer> Renderers = new ConcurrentDictionary<int, CallSiteLayoutRenderer>();
private CallSiteLayoutRenderer GetRenderer(int skipFrames)
{
return Renderers.GetOrAdd(skipFrames, f => new CallSiteLayoutRenderer() {SkipFrames = skipFrames});
}
}