Wie protokolliere ich Trace-Nachrichten mit log4net?

75

Ich verwende log4net, um eine Protokollnachricht in eine fortlaufende Protokolldatei zu schreiben.

Jetzt würde ich auch alle Ablaufverfolgungsnachrichten von System.Diagnostics.Tracedieser Protokolldatei umleiten . Wie kann ich das konfigurieren? Ich habe versucht, etwas darüber in der log4net-Dokumentation zu finden, aber ohne Erfolg. Ist das überhaupt möglich?

Der Grund, warum ich das tun möchte, ist, dass ich an den Trace-Nachrichten einer Bibliothek eines Drittanbieters interessiert bin.

<log4net>
    <appender name="R1" type="log4net.Appender.RollingFileAppender">
      <file value="C:\Logs\MyService.log" />
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <maxSizeRollBackups value="10" />
      <datePattern value="yyyyMMdd" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>
</log4net>
Dirk Vollmar
quelle

Antworten:

73

Nach Runes Vorschlag habe ich einen grundlegenden TraceListener implementiert, der an log4net ausgegeben wird:

public class Log4netTraceListener : System.Diagnostics.TraceListener
{
    private readonly log4net.ILog _log;

    public Log4netTraceListener()
    {
        _log = log4net.LogManager.GetLogger("System.Diagnostics.Redirection");
    }

    public Log4netTraceListener(log4net.ILog log)
    {
        _log = log;
    }

    public override void Write(string message)
    {
        if (_log != null)
        {
            _log.Debug(message);
        }
    }

    public override void WriteLine(string message)
    {
        if (_log != null)
        {
            _log.Debug(message);
        }
    }
}
Dirk Vollmar
quelle
14
+1 für die Antwort oben. Ich wäre vorsichtig, wenn log4net auch so eingerichtet ist, dass es in einen TraceAppender schreibt. Ich habe dies nicht wirklich getestet, aber Sie könnten in eine Situation geraten, in der Trace in log4net schreibt und log4net in Trace schreibt, was zu einer Endlosschleife führt. Anhand des obigen Beispiels können Sie dies beispielsweise abmildern, indem Sie den TraceAppender nicht in die Appender für den Logger 'System.Diagnostics.Redirection' aufnehmen.
Jimit
1
Da dies ein Trace-Listener ist, sollten Sie Try / Catch-Blöcke in den Write-Methoden implementieren, um sicherzustellen, dass ein Schreibversuch den Host niemals fehlschlägt. Ich habe Code-Änderungen eingereicht, die die Objektkonstruktion korrigieren und den Code lesbarer machen und weniger wahrscheinlich fehlschlagen.
Shaun Wilson
@JYL Hier ist ein aktualisierter Link zu diesem Blog-Beitrag . Es sieht jedoch so aus, als wären einige Dinge beim Umzug verloren gegangen. Der XML-Code in diesem Beitrag ist jetzt falsch und der Link zum Log4netTraceListener funktioniert nicht. Hoffentlich wird der Autor den Code wiederbeleben.
Jon-Eric
3
Gibt es in log4net einen integrierten Listener, der das Trace-Ereignis abhören kann?
Manjay_TBAG
4
Schauen Sie sich die Quelle für die Klasse log4net.Util.LogLog an. Dies protokolliert standardmäßig bei Trace, und @Jimit ist größtenteils richtig - Sie werden festgefahren, wenn ein Appender-Fehler auftritt. In Ihrer Implementierung von TraceListener würde ich sicherstellen, dass log4net.Util.LogLog.EmitInternalMessages = false im Konstruktor Ihrer Implementierung festgelegt ist, und möglicherweise das Ereignis LogLog.LogReceived behandeln und diese Nachrichten auf andere Weise protokollieren. Das Traurige daran ist, dass einige Appender-Fehler aufgrund dieser Einstellung nicht protokolliert werden. Die Quelle ist dein Freund hier.
Steven Bone
26

Ich weiß nicht, ob log4net dies unterstützt, aber Sie könnten Ihren eigenen Trace-Listener implementieren, der dies getan hat.

Der TraceListener verfügt nicht über zu viele Methoden, die implementiert werden müssen. Sie müssen lediglich die Werte an log4net weiterleiten, damit dies einfach sein kann.

Um einen benutzerdefinierten Trace-Listener hinzuzufügen, ändern Sie entweder Ihre app.config / web.config oder fügen Sie sie mit Code hinzu Trace.Listeners.Add(new Log4NetTraceListener());

Rune Grimstad
quelle
1

Gemäß den obigen Antworten gibt es hier eine Implementierung (dieser Link ist flockig, aber ich habe den Quellcode gefunden):

https://code.google.com/archive/p/cavity/

Um das Problem (beschrieben in den Kommentaren zu einer früheren Antwort) der internen log4net-Ablaufverfolgung, die von der LogLog-Klasse ausgegeben wird, grob zu behandeln, habe ich überprüft, ob diese Klasse die Quelle der Ablaufverfolgung ist, indem ich den Stapelrahmen überprüft habe (was diese Implementierung bereits getan hat) und Ignorieren dieser Ablaufverfolgungsnachrichten:

    public override void WriteLine(object o, string category)
    {
        // hack to prevent log4nets own diagnostic trace getting fed back
        var method = GetTracingStackFrame(new StackTrace()).GetMethod();
        var declaringType = method.DeclaringType;
        if (declaringType == typeof(LogLog))
        {
            return;
        }
        /* rest of method writes to log4net */
    }

Die Verwendung eines TraceAppender führt weiterhin zu den in den obigen Kommentaren beschriebenen Problemen.

Neil Dodson
quelle
1

Vielen Dank,

Ich ging mit Dirks Antwort etwas abgespeckter.

public class Log4netTraceListener : System.Diagnostics.TraceListener
{
    private readonly log4net.ILog _log;

    public Log4netTraceListener()
        : this(log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType))
    {

    }

    public Log4netTraceListener(log4net.ILog log)
    {
        _log = log;
    }

    public override void Write(string message) => _log?.Debug(message);

    public override void WriteLine(string message) => _log?.Debug(message);
}
Billy Jake O'Connor
quelle