Pouvez-vous configurer log4net dans le code au lieu d'utiliser un fichier de configuration?

136

Je comprends pourquoi log4net utilise des app.configfichiers pour configurer la journalisation - vous pouvez donc facilement modifier la façon dont les informations sont journalisées sans avoir à recompiler votre code. Mais dans mon cas, je ne veux pas emballer un app.configfichier avec mon exécutable. Et je n'ai aucun désir de modifier ma configuration de journalisation.

Existe-t-il un moyen pour moi de configurer le code de connexion plutôt que d'utiliser le app.config?

Voici mon fichier de configuration simple:

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

ÉDITER:

Pour être tout à fait clair: mon objectif est de ne pas avoir de fichier XML. Pas même en tant que ressource embarquée que je transforme en flux. Mon objectif était de définir l'enregistreur complètement par programmation. Je suis juste curieux de savoir si c'est possible et si oui où je pourrais trouver un exemple de syntaxe.

Michael Mankus
la source

Réponses:

223

SOLUTION FINALE: 1

Pour tous ceux qui pourraient tomber sur cela à l'avenir, voici ce que j'ai fait. J'ai créé la classe statique ci-dessous:

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

Et puis tout ce que j'avais à faire était de remplacer le code où j'ai appelé le fichier XML par l'appel suivant:

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

1 (cette réponse a été modifiée dans la question par l'OP, j'ai pris la liberté d'en faire une réponse communautaire, voyez ici pourquoi )

Philipp M
la source
2
Juste une note si vous utilisez des variables dans votre chaîne roller.File, vous pouvez utiliser la classe log4net.Util.PatternString pour la formater avant d'attribuer le résultat à foller.File.
Eric Scherrer
1
J'ai fini par obtenir des entrées de journal en double en utilisant cette méthode. Je l'ai résolu en ajoutant "hierarchy.Root.RemoveAllAppenders ();" au début de la configuration ().
Philip Bergström
4
À partir de tout cela, comment obtenir l'ILog?
Mickey Perlstein
3
Cela ne fonctionne pas pour moi à moins que j'appelle BasicConfigurator.Configure(hierarchy);au lieu de simplement régler hierarchy.Configured = true;.
Eivind Gussiås Løkseth
3
Assurez-vous que le processus que vous prévoyez d'écrire dans le fichier journal dispose des autorisations d'écriture dans le dossier dans lequel vous souhaitez que le fichier journal soit écrit. Pour diagnostiquer les problèmes de log4net, ajoutez log4net.Util.LogLog.InternalDebugging = true;avant tout autre appel log4net, puis exécutez sous le débogueur et inspectez la sortie. log4net vous dira où les choses vont mal.
Manfred
12

Vous pouvez également échapper complètement à XML, j'ai écrit un exemple avec une configuration programmatique minimale ici .

En un mot, voici ce dont vous avez besoin

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
la source
6
à quoi sert la classe Hiérarchie?
user20358
11

Oui, vous pouvez configurer log4net en appelant:

log4net.Config.XmlConfigurator.Configure(XmlElement element)

Consultez la documentation de log4net .

Joe
la source
Link est maintenant mort
Toby Smith
@TobySmith - corrigé.
Joe
4

Vous pouvez également créer un attribut personnalisé qui hérite de log4net.Config.ConfiguratorAttribute et coder en dur que vous configurez ici:

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

Ajoutez ensuite ce qui suit à un fichier .cs:

[assembly: ConsoleApplication1.MyConfigurator]
Jas
la source
1

Pour ceux qui ne veulent pas ajouter un appender à l'enregistreur racine, mais à l'enregistreur actuel / autre:

//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
la source
0

La réponse acceptée fonctionne après avoir trouvé deux mises en garde:

  • Cela ne fonctionnait pas pour moi au début, mais après avoir utilisé un chemin absolu complet pour la roller.Filepropriété, cela a commencé à fonctionner.
  • J'ai dû l'utiliser en F # (dans un script fsx), j'ai donc eu quelques problèmes lors de la conversion à partir de C #. Si vous êtes intéressé par le résultat final (y compris un moyen de télécharger le package log4net nuget), voir ci-dessous:

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
la source