NLog LogEventInfo.Message равно {0} вместо нуля или пусто в пользовательском LayoutRenderer - PullRequest
1 голос
/ 20 января 2020

У меня есть пользовательский LayoutRenderer.

Если я вызываю следующее утверждение, тогда я всегда получаю LogEventInfo.Message = {0} вместо null или "". Я что-то не так понял?

try
{
    int a = 1;
    int b = 0;
    var c = a / b;
}
catch (Exception e)
{
    var logger = LogManager.GetCurrentClassLogger();

    logger.Error(e);
}

public class HtLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        // logEvent.Message is {0} instead of being null or empty ""
    }
}

enter image description here

Обновление 1 - добавлен полный пример кода

Я опубликовал только очень маленький пример.

У меня есть два пользовательских Exceptions: HtReturnStatus и HtExceptions. Оба они имеют тип Exception. HtReturnStatus может содержать HtExceptions. HtLayoutRenderer - распаковка объектов и создание удобного макета регистрации. Не должно иметь значения, какой тип класса / объекта предоставляется.

Моя проблема - {0}. Когда это нормальное поведение , тогда я проверю, является ли logEvent.Message {0}, и проигнорирую его.

try
{
    int a = 1;
    int b = 0;
    var c = a / b;
}
catch (Exception e)
{
    LayoutRenderer.Register<HtLayoutRenderer>("htmessage");

    TraceTarget target = new TraceTarget();
    target.Name = "console";
    target.Layout = Layout.FromString("${longdate} | ${level:uppercase=true} | ${logger} | ${htmessage}");
    LogManager.Configuration = new LoggingConfiguration();
    LogManager.Configuration.AddTarget(target);
    LogManager.Configuration.LoggingRules.Insert(0, new LoggingRule("*", LogLevel.FromString("Trace"), target));
    LogManager.ReconfigExistingLoggers();

    var logger = LogManager.GetCurrentClassLogger();

    logger.Error("1");
    logger.Error(e);
    logger.Error("2");
    logger.Error(e, "Hello World");
    logger.Error("");
    logger.Error("3");
    logger.Error(HtReturnStatus.Failed(e), "Lorem Ipsum");
    logger.Error("");
    logger.Error("4");
    logger.Error(HtReturnStatus.Failed(e, "Error on division"));
    logger.Error("");
    logger.Error("5");
    logger.Error(HtReturnStatus.Failed(HtErrorCode.OPC_BAD_CERTIFICATE_INVALID));
    logger.Error("");
    logger.Error("6");
    logger.Error(HtReturnStatus.Failed(HtErrorCode.OPC_BAD_UNEXPECTED_ERROR, "Error on division #2"));

    logger.Error("");
    logger.Error("7");
    logger.Error(new HtException(HtErrorCode.CODE_READER_DMC_MultipleMatches));
    logger.Error("");
    logger.Error("8");
    logger.Error(new HtException(HtErrorCode.CODE_READER_DMC_MultipleMatches, "hello world"));
    logger.Error("");
    logger.Error("9");
    logger.Error(new HtException(HtErrorCode.CODE_READER_DMC_MultipleMatches, "lorem ipsum", e));
}
testhost Error: 0 : 2020-01-21 10:14:01.1168 | ERROR | Haprotec.Error.NLogOutputTest | 1
testhost Error: 0 : 2020-01-21 10:14:01.1383 | ERROR | Haprotec.Error.NLogOutputTest | {0} - Attempted to divide by zero. - System.DivideByZeroException: Attempted to divide by zero.
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.1572 | ERROR | Haprotec.Error.NLogOutputTest | 2
testhost Error: 0 : 2020-01-21 10:14:01.1572 | ERROR | Haprotec.Error.NLogOutputTest | Hello World - Attempted to divide by zero. - System.DivideByZeroException: Attempted to divide by zero.
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.1572 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.1572 | ERROR | Haprotec.Error.NLogOutputTest | 3
testhost Error: 0 : 2020-01-21 10:14:01.1742 | ERROR | Haprotec.Error.NLogOutputTest | Lorem Ipsum - System.DivideByZeroException: Attempted to divide by zero.
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.1742 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.1742 | ERROR | Haprotec.Error.NLogOutputTest | 4
testhost Error: 0 : 2020-01-21 10:14:01.1742 | ERROR | Haprotec.Error.NLogOutputTest | {0} - Error on division - System.DivideByZeroException: Attempted to divide by zero.
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.1905 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.1905 | ERROR | Haprotec.Error.NLogOutputTest | 5
testhost Error: 0 : 2020-01-21 10:14:01.2166 | ERROR | Haprotec.Error.NLogOutputTest | {0} - Haprotec.Error.HtException: 563021 (OPC_BAD_CERTIFICATE_INVALID)
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.2204 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.2204 | ERROR | Haprotec.Error.NLogOutputTest | 6
testhost Error: 0 : 2020-01-21 10:14:01.2204 | ERROR | Haprotec.Error.NLogOutputTest | {0} - Error on division #2 - Haprotec.Error.HtException: 563001 (OPC_BAD_UNEXPECTED_ERROR)
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.2204 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.2204 | ERROR | Haprotec.Error.NLogOutputTest | 7
testhost Error: 0 : 2020-01-21 10:14:01.2374 | ERROR | Haprotec.Error.NLogOutputTest | {0} - Haprotec.Error.HtException: 500251 (CODE_READER_DMC_MultipleMatches)
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.2374 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.2374 | ERROR | Haprotec.Error.NLogOutputTest | 8
testhost Error: 0 : 2020-01-21 10:14:01.2374 | ERROR | Haprotec.Error.NLogOutputTest | {0} - hello world - Haprotec.Error.HtException: 500251 (CODE_READER_DMC_MultipleMatches)
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26
testhost Error: 0 : 2020-01-21 10:14:01.2374 | ERROR | Haprotec.Error.NLogOutputTest | 
testhost Error: 0 : 2020-01-21 10:14:01.2506 | ERROR | Haprotec.Error.NLogOutputTest | 9
testhost Error: 0 : 2020-01-21 10:14:01.2506 | ERROR | Haprotec.Error.NLogOutputTest | {0} - lorem ipsum - System.DivideByZeroException: Attempted to divide by zero.
StackTrace:    at Haprotec.Error.NLogOutputTest.HtReturnStatusOutputTest() in D:\Repositories\gitlab.haprotec\dotNet\HtCore\src\HtCore.Tests\Error\NLogOutputTest.cs:line 26

1 Ответ

2 голосов
/ 20 января 2020

Это полностью намеренно. Вы вызываете этот метод логгера, где регистрируется случайный объект:

Logger.Error<T>(T value);

Это сокращение для этого, которое гарантирует, что string.Format будет работать:

Logger.Error("{0}", value);

Но вы вероятно, заметили, что для Exception была реализована специальная обработка. NLog выполняет дополнительную проверку для захвата параметра Exception для ${exception}, но не изменяет строку формата.

В вашем HtLayoutRenderer вы можете распознать его следующим образом:

public class HtLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
       if ( logevent.Exception != null
         && logevent.Message == "{0}"
         && logevent.Parameters?.Length == 1
         && ReferenceEquals(logevent.Exception, logevent.Parameters[0])
       {
          // Exception given as single parameter without any message
       }
    }
}

Обратите внимание, что есть разница между LogEventInfo.Message и LogEventInfo.FormattedMessage

...