Können Sie log4net im Code konfigurieren, anstatt eine Konfigurationsdatei zu verwenden?

136

Ich verstehe, warum log4net app.configDateien zum Einrichten der Protokollierung verwendet. So können Sie die Protokollierung von Informationen leicht ändern, ohne Ihren Code neu kompilieren zu müssen. In meinem Fall möchte ich jedoch keine app.configDatei mit meiner ausführbaren Datei packen . Und ich habe keine Lust, mein Protokollierungssetup zu ändern.

Gibt es eine Möglichkeit für mich, den Anmeldecode einzurichten, anstatt den zu verwenden app.config?

Hier ist meine einfache Konfigurationsdatei:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Logs\EventLog.txt" />
      <appendToFile value="false" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="1GB" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
      </layout>
    </appender>
    <appender name="MemoryAppender" type="log4net.Appender.MemoryAppender">
    </appender>
    <root>
      <level value="Info" />
      <appender-ref ref="RollingLogFileAppender" />
      <appender-ref ref="MemoryAppender" />
    </root>
  </log4net>
</configuration>

BEARBEITEN:

Um ganz klar zu sein: Es ist mein Ziel, keine XML-Datei zu haben. Nicht einmal als eingebettete Ressource, die ich in einen Stream verwandle. Mein Ziel war es, den Logger vollständig programmgesteuert zu definieren. Nur neugierig, ob es möglich ist und wenn ja, wo ich ein Beispiel für die Syntax finden könnte.

Michael Mankus
quelle

Antworten:

222

SCHLUSSLÖSUNG: 1

Für alle, die in Zukunft darauf stoßen könnten, habe ich Folgendes getan. Ich habe die folgende statische Klasse erstellt:

using log4net;
using log4net.Repository.Hierarchy;
using log4net.Core;
using log4net.Appender;
using log4net.Layout;

namespace Spectrum.Logging
{
    public class Logger
    {
        public static void Setup()
        {
            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%date [%thread] %-5level %logger - %message%newline";
            patternLayout.ActivateOptions();

            RollingFileAppender roller = new RollingFileAppender();
            roller.AppendToFile = false;
            roller.File = @"Logs\EventLog.txt";
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.MaximumFileSize = "1GB";
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;            
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            MemoryAppender memory = new MemoryAppender();
            memory.ActivateOptions();
            hierarchy.Root.AddAppender(memory);

            hierarchy.Root.Level = Level.Info;
            hierarchy.Configured = true;
        }
    }
}

Und dann musste ich nur noch den Code, in dem ich die XML-Datei aufgerufen hatte, durch den folgenden Aufruf ersetzen:

//XmlConfigurator.Configure(new FileInfo("app.config")); // Not needed anymore
Logger.Setup();

1 (Diese Antwort wurde vom OP in die Frage umgewandelt. Ich habe mir erlaubt, daraus eine Community-Antwort zu machen. Siehe hier, warum. )

Philipp M.
quelle
2
Nur eine Anmerkung, wenn Sie Variablen in Ihrer Zeichenfolge roller.File verwenden, können Sie sie mit der Klasse log4net.Util.PatternString formatieren, bevor Sie das Ergebnis foller.File zuweisen.
Eric Scherrer
1
Mit dieser Methode erhielt ich doppelte Protokolleinträge. Ich habe es gelöst, indem ich "hierarchy.Root.RemoveAllAppenders ();" zum Anfang des Setups ().
Philip Bergström
4
Wie bekomme ich aus all dem den ILog?
Mickey Perlstein
3
Funktioniert bei mir nur, wenn ich anrufe, BasicConfigurator.Configure(hierarchy);anstatt nur einzustellen hierarchy.Configured = true;.
Eivind Gussiås Løkseth
3
Stellen Sie sicher, dass der Prozess, den Sie in die Protokolldatei schreiben möchten, über Schreibberechtigungen in dem Ordner verfügt, in den die Protokolldatei geschrieben werden soll. Um log4net-Probleme zu diagnostizieren, fügen Sie diese log4net.Util.LogLog.InternalDebugging = true;vor jedem anderen log4net-Aufruf hinzu, führen Sie sie dann unter Debugger aus und überprüfen Sie die Ausgabe. log4net zeigt Ihnen, wo etwas schief geht.
Manfred
12

Sie können auch XML vollständig entweichen, schrieb ich eine Probe mit minimaler programmatischer Konfiguration hier .

Kurz gesagt, hier ist was Sie brauchen

var tracer = new TraceAppender();
var hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Root.AddAppender(tracer);
var patternLayout = new PatternLayout {ConversionPattern = "%m%n"};
patternLayout.ActivateOptions();
tracer.Layout = patternLayout;
hierarchy.Configured = true;
oleksii
quelle
6
Wofür ist die Hierarchieklasse?
user20358
11

Ja, Sie können log4net konfigurieren, indem Sie Folgendes aufrufen:

log4net.Config.XmlConfigurator.Configure(XmlElement element)

Siehe die log4net-Dokumentation .

Joe
quelle
Link ist jetzt tot
Toby Smith
@TobySmith - behoben.
Joe
4

Alternativ können Sie ein benutzerdefiniertes Attribut erstellen, das von log4net.Config.ConfiguratorAttribute erbt und Ihre Konfiguration dort fest codiert:

using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Repository;
using log4net.Repository.Hierarchy;
using System;
using System.Reflection;

namespace ConsoleApplication1
{
    [AttributeUsage(AttributeTargets.Assembly)]
    public class MyConfiguratorAttribute : ConfiguratorAttribute
    {
        public MyConfiguratorAttribute()
            : base(0)
        {
        }

        public override void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository)
        {
            var hierarchy = (Hierarchy)targetRepository;
            var patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%date [%thread] %-5level %logger - %message%newline";
            patternLayout.ActivateOptions();

            var roller = new RollingFileAppender();
            roller.AppendToFile = false;
            roller.File = @"Logs\EventLog.txt";
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.MaximumFileSize = "1GB";
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            hierarchy.Root.Level = Level.Info;
            hierarchy.Configured = true;
        }
    }
}

Fügen Sie dann einer CS-Datei Folgendes hinzu:

[assembly: ConsoleApplication1.MyConfigurator]
Jas
quelle
1

Für diejenigen, die dem Root-Logger keinen Appender hinzufügen möchten, sondern dem aktuellen / anderen Logger:

//somewhere you've made a logger
var logger = LogManager.GetLogger("MyLogger");

// now add appender to it
var appender = BuildMyAppender();
((log4net.Repository.Hierarchy.Logger)logger).AddAppender(appender);

logger.Debug("MyLogger with MyAppender must work now");

// and remove it later if this code executed multiple times (loggers are cached, so you'll get logger with your appender attached next time "MyLogger")
((log4net.Repository.Hierarchy.Logger)logger).RemoveAppender(sbAppender);
Vladislav Kostenko
quelle
0

Die akzeptierte Antwort funktioniert, nachdem ich zwei Einschränkungen gefunden habe:

  • Es funktionierte zunächst nicht für mich, aber nachdem ich einen vollständigen absoluten Pfad für die roller.FileImmobilie verwendet hatte, begann es zu arbeiten.
  • Ich musste dies in F # (in einem fsx-Skript) verwenden, hatte also einige Probleme beim Konvertieren von C #. Wenn Sie am Endergebnis interessiert sind (einschließlich einer Möglichkeit zum Herunterladen des log4net-Nuget-Pakets), siehe unten:

nuget_log4net.fsx:

#!/usr/bin/env fsharpi

open System
open System.IO
open System.Net

#r "System.IO.Compression.FileSystem"
open System.IO.Compression

type DummyTypeForLog4Net () =
    do ()

module NetTools =

    let DownloadNuget (packageId: string, packageVersion: string) =
    use webClient = new WebClient()
    let fileName = sprintf "%s.%s.nupkg" packageId packageVersion

    let pathToUncompressTo = Path.Combine("packages", packageId)
    if (Directory.Exists(pathToUncompressTo)) then
        Directory.Delete(pathToUncompressTo, true)
    Directory.CreateDirectory(pathToUncompressTo) |> ignore
    let fileToDownload = Path.Combine(pathToUncompressTo, fileName)

    let nugetDownloadUri = Uri (sprintf "https://www.nuget.org/api/v2/package/%s/%s" packageId packageVersion)
    webClient.DownloadFile (nugetDownloadUri, fileToDownload)

    ZipFile.ExtractToDirectory(fileToDownload, pathToUncompressTo)

let packageId = "log4net"
let packageVersion = "2.0.5"
NetTools.DownloadNuget(packageId, packageVersion)

let currentDirectory = Directory.GetCurrentDirectory()

// https://stackoverflow.com/a/19538654/6503091
#r "packages/log4net/lib/net45-full/log4net"

open log4net
open log4net.Repository.Hierarchy
open log4net.Core
open log4net.Appender
open log4net.Layout
open log4net.Config

let patternLayout = PatternLayout()
patternLayout.ConversionPattern <- "%date [%thread] %-5level %logger - %message%newline";
patternLayout.ActivateOptions()

let roller = RollingFileAppender()
roller.AppendToFile <- true
roller.File <- Path.Combine(currentDirectory, "someLog.txt")
roller.Layout <- patternLayout
roller.MaxSizeRollBackups <- 5
roller.MaximumFileSize <- "1GB"
roller.RollingStyle <- RollingFileAppender.RollingMode.Size
roller.StaticLogFileName <- true
roller.ActivateOptions ()

let hierarchy = box (LogManager.GetRepository()) :?> Hierarchy
hierarchy.Root.AddAppender (roller)

hierarchy.Root.Level <- Level.Info
hierarchy.Configured <- true
BasicConfigurator.Configure(hierarchy)

let aType = typedefof<DummyTypeForLog4Net>
let logger = LogManager.GetLogger(aType)

logger.Error(new Exception("exception test"))
ympostor
quelle