Как обрабатывать пустые значения, созданные средством визуализации макетов свойств всех событий NLog? - PullRequest
2 голосов
/ 24 мая 2019

Я настраиваю цель базы данных NLog для PostgreSQL и хочу использовать hstore столбец для хранения всех свойств события. Для этого я использую all-event-properties рендеринг макета .

Вот моя текущая целевая конфигурация:

<target name="database"
        xsi:type="Database"
        dbProvider="Npgsql.NpgsqlConnection, Npgsql"
        connectionString="Server=localhost;Port=5432;Database=db;User Id=postgres">
  <install-command>
    <text>
      CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public;
      CREATE TABLE IF NOT EXISTS logs (
      id bigserial PRIMARY KEY,
      moment timestamp NOT NULL,
      level text NOT NULL,
      message text NOT NULL,
      args hstore NOT NULL
      );
    </text>
  </install-command>
  <commandText>
    INSERT INTO logs (moment, level, message, args)
    VALUES (@moment::timestamp, @level, @message, @args::hstore);
  </commandText>
  <parameter name="@moment" layout="${longdate:universalTime=true}" />
  <parameter name="@level" layout="${level}" />
  <parameter name="@message" layout="${message}" />

  <!-- (!) Here's where the format of event properties adopted for hstore syntax (!)-->
  <parameter name="@args" layout="${all-event-properties:format=[key]=>[value]" />

</target>

Работает для журналов без параметров, но с параметрами генерируется следующий SQL:

INSERT INTO logs (moment, level, message, args) VALUES (
'2019-05-24 18:44:49.7494'::timestamp,
'Info',
'Message text here',
'a=>1, b=>2, c=>3, EventId_Id=>555, EventId_Name=>, EventId=>555'::hstore);
--                           no value here--------^

Это недопустимый синтаксис, потому что синтаксис PostgreSQL требует либо NULL ключевое слово для значения, либо не включать ключ вообще:

Вот ошибка:

ERROR:  Syntax error near 'E' at position 51

Что именно воспроизводит, когда я выполняю это вручную, и исчезает, когда я удаляю ключ EventId_Name=>,. Итак, я почти уверен, что мне нужно как-то пропустить / обработать этот пустой ключ, чтобы быть счастливым.

Я также в порядке с любым решением в SQL, но не могу найти простой и надежный подход для обработки этих значений.

Ответы [ 2 ]

1 голос
/ 24 мая 2019

Чтобы ответить на этот вопрос, я прочитал документацию по формату hstore :

Ключи и значения в двойных кавычках, включая пробелы, запятые, = s или> s. Чтобы включить двойную кавычку или обратную косую черту в ключ или значение, экранируйте их обратной косой чертой.

Не уверен, что такое =s и >s, и я решил все заключить в двойные кавычки, избегая двойных кавычек и обратной косой черты. Вот мое решение:

LayoutRenderer.Register("all-event-properties-hstore", e =>
{
    var sb = new StringBuilder();
    var first = true;
    var fp = e.FormatProvider ?? CultureInfo.InvariantCulture;
    string GetString(object o) =>
        Convert.ToString(o, fp).Replace("\\", "\\\\").Replace("\"", "\\\"");
    foreach (var (key, value) in e.Properties)
    {
        if (first)
            first = false;
        else
            sb.Append(",");
        sb.Append("\"");
        sb.Append(GetString(key));
        sb.Append("\"=>\"");
        sb.Append(GetString(value));
        sb.Append("\"");
    }
    return sb.ToString();
});
1 голос
/ 24 мая 2019

Я не совсем понимаю, какой синтаксис должен быть в этом случае, но вы можете все равно это исправить с помощью пользовательского макета макета

создать:

// register ${all-properties-postgresql}
LayoutRenderer.Register("all-properties-postgresql", 
                       (logEvent) => SerializeProps(logEvent.Properties));

Вам нужно написать SerializeProps для сериализации LogEventInfo.Properties - см. Документы API

...