Настройка времени записи трассировки стека в NLog - PullRequest
0 голосов
/ 02 ноября 2018

Я пишу собственную цель NLog, полученную из TargetWithLayout, и я бы хотел, чтобы она дополнительно записывала трассировку стека, в зависимости от конкретного события журнала. Я определил вложенный макет как этот (синтаксис может быть неправильным):

Layout layout = "${when:${event-properties:StackTraceEnabled}==true:${stacktrace}}";

И я буду создавать такие события:

var logEventInfo = new NLog.LogEventInfo(NLog.LogLevel.Error, "Test", "Test")
{
    Properties =
    {
        { "StackTraceEnabled", true },
    }
};

Однако, это не работает, и, кажется, идет вразрез с дизайном NLog. Из всего, что я видел, NLog оценивает GetStackTraceUsage() по своим зарегистрированным целям, а затем либо всегда генерирует трассировку стека, либо никогда не генерирует. Это правильно? Есть ли способ настроить генерацию трассировки стека на уровне события?

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Подтверждение принятого ответа: внутренний метод NLog.LoggerImpl.Write захватывает трассировку стека, если какой-либо цели NLog требует трассировку стека для любого сообщения (независимо от фильтров), и если экземпляр LogEventInfo еще не имеет стека след. За LoggerImpl.cs :

internal static class LoggerImpl
{
    internal static void Write([NotNull] Type loggerType, TargetWithFilterChain targets, LogEventInfo logEvent, LogFactory factory)
    {
        if (targets == null)
            return;

        StackTraceUsage stu = targets.GetStackTraceUsage();
        if (stu != StackTraceUsage.None && !logEvent.HasStackTrace)
        {
            var stackTrace = new StackTrace(StackTraceSkipMethods, stu == StackTraceUsage.WithSource);
            var stackFrames = stackTrace.GetFrames();
            int? firstUserFrame = FindCallingMethodOnStackTrace(stackFrames, loggerType);
            int? firstLegacyUserFrame = firstUserFrame.HasValue ? SkipToUserStackFrameLegacy(stackFrames, firstUserFrame.Value) : (int?)null;
            logEvent.GetCallSiteInformationInternal().SetStackTrace(stackTrace, firstUserFrame ?? 0, firstLegacyUserFrame);
        }

        // ...
    }
}

Приведенный выше метод будет воздерживаться от захвата фактической трассировки стека, если она уже была явно задана, даже если это просто заполнитель. Таким образом, явная установка трассировки стека в качестве заполнителя - это самый простой способ предотвратить создание трассировкой стека NLog для этих конкретных записей журнала.

0 голосов
/ 02 ноября 2018

Одно из решений состоит в том, чтобы использовать два целевых экземпляра и просто использовать имя регистратора, чтобы контролировать, должен ли он использовать целевой объект, настроенный для записи StackTrace:

<logger name="StackTraceEnabled" writeTo="target1_stacktrace" final="true">
<logger name="*" writeTo="target2_default" />

Сейчас NLog решает только на основе Logger-name, должен ли он включать StackTrace (или нет). Он находит все правила ведения журнала, соответствующие имени средства ведения журнала, и если один из них включает цель с помощью трассировки стека, будет произведен захват (независимо от того, есть ли у правила фильтры условий)

Должно быть легко исправить NLog, поэтому он также проверяет условия фильтра, прежде чем пытаться захватить StackTrace (разрешить оптимизацию фильтра для других вещей, кроме имени логгера).

...