È possibile configurare log4net nel codice anziché utilizzare un file di configurazione?


136

Capisco perché log4net utilizza i app.configfile per impostare la registrazione, in modo da poter cambiare facilmente la modalità di registrazione delle informazioni senza dover ricompilare il codice. Ma nel mio caso non voglio comprimere un app.configfile con il mio eseguibile. E non desidero modificare la mia configurazione di registrazione.

Esiste un modo per impostare il codice di accesso anziché utilizzare il app.config?

Ecco il mio semplice file di configurazione:

<?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>

MODIFICARE:

Per essere completamente chiari: il mio obiettivo è non avere un file XML. Nemmeno come risorsa integrata che trasformo in flusso. Il mio obiettivo era quello di definire il logger in modo completamente programmatico. Sono solo curioso di sapere se è possibile e se sì, dove potrei trovare un esempio della sintassi.

Risposte:


223

SOLUZIONE FINALE: 1

Per chiunque possa inciampare su questo in futuro, ecco cosa ho fatto. Ho creato la classe statica di seguito:

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;
        }
    }
}

E poi tutto quello che dovevo fare era sostituire il codice in cui avevo chiamato il file XML con la seguente chiamata:

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

1 (questa risposta è stata inserita nella domanda dall'OP, mi sono preso la libertà di renderla una risposta della comunità, vedi qui perché )


2
Solo una nota se usi le variabili nella stringa roller.File puoi usare la classe log4net.Util.PatternString per formattarla prima di assegnare il risultato a foller.File.
Eric Scherrer,

1
Ho finito per ottenere voci di registro duplicate utilizzando questo metodo. Ho risolto aggiungendo "hierarchy.Root.RemoveAllAppenders ();" all'inizio dell'installazione ().
Philip Bergström,

4
Da tutto ciò, come posso ottenere ILog?
Mickey Perlstein,

3
Non funziona per me a meno che non chiami BasicConfigurator.Configure(hierarchy);invece di impostare hierarchy.Configured = true;.
Eivind Gussiås Løkseth,

3
Assicurarsi che il processo che si prevede di scrivere nel file di registro disponga delle autorizzazioni di scrittura nella cartella in cui si desidera scrivere il file di registro. Per diagnosticare i problemi di log4net aggiungere log4net.Util.LogLog.InternalDebugging = true;prima di qualsiasi altra chiamata log4net, quindi eseguire il debugger e controllare l'output. log4net ti dirà dove le cose vanno male.
Manfred,

12

Puoi anche sfuggire completamente a XML, ho scritto un esempio con una configurazione programmatica minima qui .

In breve, ecco di cosa hai bisogno

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;

6
a cosa serve la classe della Gerarchia?
user20358


4

In alternativa, è possibile creare un attributo personalizzato che eredita da log4net.Config.ConfiguratorAttribute e dall'hard-code che si configura lì:

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;
        }
    }
}

Quindi aggiungere quanto segue a un file .cs:

[assembly: ConsoleApplication1.MyConfigurator]

1

Per coloro che non vogliono aggiungere appender al logger principale, ma al logger corrente / altro:

//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);

0

La risposta accettata funziona dopo che ho trovato due avvertenze:

  • All'inizio non funzionava per me, ma dopo aver usato un percorso assoluto assoluto per la roller.Fileproprietà, ha iniziato a funzionare.
  • Ho dovuto usarlo in F # (in uno script fsx), quindi ho avuto dei problemi durante la conversione da C #. Se sei interessato al risultato finale (incluso un modo per scaricare il pacchetto nuget log4net), vedi sotto:

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"))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.