Проблема с конфигурацией БД NLog для PostgreSql

avatar
Vedat Baysal
9 августа 2021 в 06:35
170
1
0

Я использую nlog, он хорошо работает с файлом журнала, но я также хочу добавить информацию журнала в базу данных. Но это не работает для меня. Я не мог найти свою проблему. Я использую postgresql в качестве базы данных. Я использую .NET5 NLog 4.7.10

nlog.config:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  
  <targets>
    <target name="allfile" xsi:type="File"
            fileName="D:\BEBKA.JobTracking.logs\${shortdate}.log"/>
    
    <target xsi:type="Database" name="db" dbProvider="Npgsql.NpgsqlConnection, Npgsql" connectionstring="Server=127.0.0.1;Port=5432;Database=BEBKAJobTracking;User Id=postgres;Password=123;">
      <commandText>
        INSERT INTO public."Logs"("Type", "Method", "StatusCode", "StackTrace", "MethodName", "Message", "RequestData", "ResponseData", "Ip", "CreatedDate", "CreatedId")
        VALUES (@Type, @Method, @StatusCode, @StackTrace, @MethodName, @Message, @RequestData, @ResponseData, @Ip, @CreatedDate, @CreatedId);
      </commandText>
      <parameter name="@Type" layout="${type}"/>
      <parameter name="@Method" layout="${method}"/>
      <parameter name="@StatusCode" layout="${statusCode}"/>
      <parameter name="@StackTrace" layout="${stackTrace}"/>
      <parameter name="@MethodName" layout="${methodName}"/>
      <parameter name="@Message" layout="${message}"/>
      <parameter name="@RequestData" layout="${requestData}"/>
      <parameter name="@ResponseData" layout="${responseData}"/>
      <parameter name="@Ip" layout="${ip}"/>
      <parameter name="@CreatedDate" layout="${createdDate}"/>
      <parameter name="@CreatedId" layout="${createdId}"/>
    </target>
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" writeTo="allfile" />
    <logger name="db" minlevel="Trace" writeTo="db" />
  </rules>
</nlog> 

Моя служба регистратора

using BEBKA.Infrastructure.Abstractions.Core;
using BEBKA.Infrastructure.Abstractions.Loggger.Interfaces;
using NLog;

namespace BEBKA.Infrastructure.Services
{
    public class LoggerService : ILoggerService
    {
        private static readonly ILogger logger = LogManager.GetCurrentClassLogger();

        public void LogDebug(ILog log)
        {
            logger.Debug(log.Message);
        }

        public void LogDebug(string message)
        {
            logger.Debug(message);
        }

        public void LogError(ILog log)
        {
            logger.Error(log.Message);
        }

        public void LogError(string message)
        {
            logger.Error(message);
        }

        public void LogInfo(ILog log)
        {
            //TODO: Need Bugfix
            LogEventInfo theEvent = new(LogLevel.Info, "db", log.Message);
            SetLogEventInfo(theEvent, log);
            logger.Log(theEvent);

            //logger.Info("{message}",log.Message);   
        }

        public void LogInfo(string message)
        {
            logger.Info(message);
        }

        public void LogWarn(ILog log)
        {
            logger.Warn(log.Message);
        }

        public void LogWarn(string message)
        {

            logger.Warn(message);
        }
        private static void SetLogEventInfo(LogEventInfo theEvent, ILog
    data)
        {
            theEvent.Properties["Type"] = data.Type;
            theEvent.Properties["Method"] = data.Method;
            theEvent.Properties["StatusCode"] = data.StatusCode;
            theEvent.Properties["StackTrace"] = data.StackTrace;
            theEvent.Properties["MethodName"] = data.MethodName;
            theEvent.Properties["Message"] = data.Message;
            theEvent.Properties["RequestData"] = data.RequestData;
            theEvent.Properties["ResponseData"] = data.ResponseData;
            theEvent.Properties["Ip"] = data.Ip;
            theEvent.Properties["CreatedDate"] = data.CreatedDate;
            theEvent.Properties["CreatedId"] = data.CreatedId;
        }
    }
}

................................................... ................................................. ................................................. ................................................. ................................................. ..........

Источник
Rolf Kristensen
9 августа 2021 в 17:01
0

Возможно дубликат: coderhelper.com/questions/42202137/…

Rolf Kristensen
9 августа 2021 в 17:02
0

Вы проверили github.com/NLog/NLog/wiki/Internal-Logging на наличие ошибок?

Rolf Kristensen
16 августа 2021 в 17:01
0

См. также: github.com/NLog/NLog/issues/4512

Ответы (1)

avatar
Rolf Kristensen
16 августа 2021 в 17:16
0

У вас есть несколько проблем:

  1. Event-Properties должны отображаться с помощью ${event-properties}
      <parameter name="@Type" layout="${event-properties:type}"/>
      <parameter name="@Method" layout="${event-properties:method}"/>
      <parameter name="@StatusCode" layout="${event-properties:statusCode}"/>
      <parameter name="@StackTrace" layout="${event-properties:stackTrace}"/>
      <parameter name="@MethodName" layout="${event-properties:methodName}"/>
      <parameter name="@Message" layout="${event-properties:message}"/>
      <parameter name="@RequestData" layout="${event-properties:requestData}"/>
      <parameter name="@ResponseData" layout="${event-properties:responseData}"/>
      <parameter name="@Ip" layout="${event-properties:ip}"/>
      <parameter name="@CreatedDate" layout="${event-properties:createdDate}"/>
      <parameter name="@CreatedId" layout="${event-properties:createdId}"/>
  1. Имя регистратора никогда не должно назначаться, но должно быть пустым, чтобы работала фильтрация
    public class LoggerService : ILoggerService
    {
        private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
        private static readonly ILogger Dblogger = LogManager.GetLogger("db");

        public void LogInfo(ILog log)
        {
            LogEventInfo theEvent = new(LogLevel.Info, null, log.Message);
            SetLogEventInfo(theEvent, log);
            Dblogger.Log(theEvent); // DbLogger matches <logger name="db" minlevel="Trace" writeTo="db" />
        }

Это немного сбивает с толку, что все конструкторы LogEventInfo принимают Logger-name в качестве входного параметра, но его никогда не следует назначать. Пытался улучшить это, но мой запрос на включение был отклонен: https://github.com/NLog/NLog/issues/4086

Обратите внимание, что можно также регистрировать ILog как отдельный объект, например Dblogger.Info("{payload}", data), и извлекать отдельные свойства следующим образом: ${eventproperties:payload:objectpath=CreatedId}

Vedat Baysal
16 августа 2021 в 21:37
0

Кажется, это работает для меня, но требует небольших изменений. У меня появилась новая ошибка в моем внутреннем файле журнала: SqlState: 42804 MessageText: столбец «Тип» имеет целочисленный тип, но выражение имеет текстовый тип. Подсказка: вам нужно будет переписать или привести выражение. На самом деле я отправляю правильный тип, но каждый параметр меняется как строка, как я могу это исправить.

Rolf Kristensen
16 августа 2021 в 21:41
0

@VedatBaysal Вы можете указать dbType="Int32" для соответствующего <parameter>. См. также github.com/nlog/NLog/wiki/Database-target