2012-04-10 33 views
0

Ist es möglich, die npgsql-Protokollausgabe an einen log4net-Logger umzuleiten? Aus dem Quellcode von npgsql sieht es so aus, als würde es direkt in stdout/stderr oder einer bestimmten Datei (unter Verwendung der statischen Eigenschaften unter NpgsqlEventLog) loggen. Gibt es eine Möglichkeit, diese Protokollierung in log4net zu routen?Wie umleiten npgsql Log-Ausgabe zu einem log4net Logger?

Antwort

1

Ich weiß nichts über npgsql, aber wenn Sie die Quelle haben und dürfen es ändern, dann sollte es einfacher sein, es zu ändern, um log4net zu unterstützen.

Wenn Sie die Quelle nicht haben, dann wäre es nicht einfach und möglicherweise nicht einmal möglich. Da log4net die Ausgabe von anderen Quellen nicht abfängt, wäre die einzige Möglichkeit, dies zu tun, ein Hintergrund-Thread zu haben, der die Datei überwacht, für die npgsql ausgegeben wird, und wenn sich die Datei ändert, müssten Sie diese Datei lesen und analysieren Sie die Informationen und rufen Sie dann log4net mit diesen Informationen auf.

Sie haben immer noch das Problem, dass Log4net denkt, dass jeder Aufruf von Ihrer Routine kommt und nicht npgsql und Stack-Spuren durcheinander kommen. Würde auch nur funktionieren, wenn npgsql jedes Mal, wenn ein Protokolleintrag erstellt wurde, die Datei sperrt, öffnet, schreibt und schließt.

1

Erste log4net zu Ihrer Lösung hinzuzufügen, der einfache Weg ist nuget zu verwenden: so tun Sie dies: installieren-Paket log4net dann müssen Sie Npgsql installieren: installieren-Paket Npgsql

in Ihrem Web .config Datei Sie fügen diese Elemente hinzu: (Sie müssen App verwenden.Konfiguration für nicht Web-Lösung)

In der configSection printf ("% d \ n", 42);/*

//the most important thing is to ensure that the type on your parameter   //section is correct. otherwise, no error will be returned, and no data will be   inserted. 

//now, at your code you can use this function: 

     protected void LogInfo(string message, params object[] args) 
     { 
      log4net.ILog log =  log4net.LogManager.GetLogger("postgreSqlLogAppender"); 
      log4net.ThreadContext.Properties["UserId"] = args.[0]; 
      log4net.ThreadContext.Properties["EntityId"] = args.[1]; 
      log.Info(string.Format("{0}: {1}",  this.GetType().Name.Replace("Controller", ""), string.Format(message, args))); 
      log4net.ThreadContext.Properties.Remove("UserId"); 
      log4net.ThreadContext.Properties.Remove("EntityId"); 
     } 


//to call your function 
    void test() 
{ 
    LogInfo("My message",15,326) 
} 


//in my case 15 is my current user_id and 326 is the my class_object. 
    */ 
2

Dies ist, wie ich es getan habe und es scheint recht gut zu funktionieren. Beachten Sie, dass ich den Befehl am Aufspalten abzumelden an einen separaten appender, weil es ziemlich ausführliche bekommt ...

Zuerst diese hinzufügen, bevor Sie irgendwelche anderen Anrufe Npgsql machen:

NpgsqlLogManager.Provider = new Log4NetNpgsqlLoggingProvider("NpgsqlDefaultLogger") 
{ 
    CommandLoggerName = "NpgsqlCommandLogger" 
}; 

Jetzt müssen Sie hinzufügen in der Logging-Provider-Klasse:

using System; 
using Npgsql.Logging; 

namespace Util.Npgsql 
{ 
    public class Log4NetNpgsqlLoggingProvider : INpgsqlLoggingProvider 
    { 
     public string DefaultLoggerName { get; } 
     public string CommandLoggerName { get; set; } 

     public Log4NetNpgsqlLoggingProvider(string defaultLoggerName) 
     { 
      if (defaultLoggerName == null) throw new ArgumentNullException(nameof(defaultLoggerName)); 
      DefaultLoggerName = defaultLoggerName; 
     } 

     public NpgsqlLogger CreateLogger(string name) 
     { 
      switch (name) 
      { 
       case "Npgsql.NpgsqlCommand": 
        return new Log4NetNpgsqlLogger(CommandLoggerName ?? DefaultLoggerName); 
       default: 
        return new Log4NetNpgsqlLogger(DefaultLoggerName); 
      } 
     } 
    } 
} 

Und Sie müssen auch die tatsächliche Logger Klasse:

using System; 
using log4net; 
using log4net.Core; 
using Npgsql.Logging; 

namespace Util.Npgsql 
{ 
    public class Log4NetNpgsqlLogger : NpgsqlLogger 
    { 
     private readonly ILog _log; 

     public Log4NetNpgsqlLogger(string name) 
     { 
      _log = LogManager.GetLogger(name); 
     } 

     public override bool IsEnabled(NpgsqlLogLevel level) 
     { 
      return _log.Logger.IsEnabledFor(GetLog4NetLevelFromNpgsqlLogLevel(level)); 
     } 

     public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null) 
     { 
      _log.Logger.Log(typeof(NpgsqlLogger), GetLog4NetLevelFromNpgsqlLogLevel(level), connectorId + ": " + msg, exception); 
     } 

     protected Level GetLog4NetLevelFromNpgsqlLogLevel(NpgsqlLogLevel level) 
     { 
      switch (level) 
      { 
       case NpgsqlLogLevel.Trace: 
       case NpgsqlLogLevel.Debug: 
        return Level.Debug; 
       case NpgsqlLogLevel.Info: 
        return Level.Info; 
       case NpgsqlLogLevel.Warn: 
        return Level.Warn; 
       case NpgsqlLogLevel.Error: 
        return Level.Error; 
       case NpgsqlLogLevel.Fatal: 
        return Level.Fatal; 
       default: 
        throw new Exception("Unknown Npgsql Log Level: " + level); 
      } 
     } 
    } 
} 
+0

beachten Sie auch, dass in Npgsql 3.2.0: "Npgsql benutzerdefinierte Protokollierung wurde mit [Microsoft.Extensions.Logging]" ersetzt. In 3.2.2 wurde es jedoch rückgängig gemacht: "Aufgrund der vielen Beschwerden wurde die Verwendung von Microsoft.Extensions.Logging durch Npgsql 3.2 gelöscht, und die Protokollierung funktioniert jetzt wie in Npgsql 3.1". Referenzen: https://github.com/npgsql/Npgsql/releases –

Verwandte Themen