¿Se puede configurar log4net en código en lugar de utilizar un archivo de configuración?

136

Entiendo por qué log4net usa app.configarchivos para configurar el registro, por lo que puede cambiar fácilmente cómo se registra la información sin necesidad de volver a compilar su código. Pero en mi caso no quiero empaquetar un app.configarchivo con mi ejecutable. Y no deseo modificar mi configuración de registro.

¿Hay alguna manera de configurar el código de inicio de sesión en lugar de usar el app.config?

Aquí está mi archivo de configuración 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>

EDITAR:

Para ser completamente claro: mi objetivo es no tener un archivo XML. Ni siquiera como un recurso incrustado que convierto en una secuencia. Mi objetivo era definir el registrador completamente mediante programación. Solo tengo curiosidad por saber si es posible y si es así, dónde podría encontrar un ejemplo de la sintaxis.

Michael Mankus
fuente

Respuestas:

223

SOLUCIÓN FINAL: 1

Para cualquiera que pueda tropezar con esto en el futuro, esto es lo que hice. Hice la clase estática a continuación:

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

Y luego todo lo que tuve que hacer fue reemplazar el código donde llamé al archivo XML con la siguiente llamada:

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

1 (esta respuesta fue editada en la pregunta por el OP, me tomé la libertad de hacerla una respuesta comunitaria, vea aquí por qué )

Philipp M
fuente
2
Solo una nota si usa variables en su rodillo. Cadena de archivos puede usar la clase log4net.Util.PatternString para formatearla antes de asignar el resultado a foller.File.
Eric Scherrer
1
Terminé recibiendo entradas de registro duplicadas usando este método. Lo resolví agregando "hierarchy.Root.RemoveAllAppenders ();" al comienzo de la Configuración ().
Philip Bergström
44
De todo esto, ¿cómo obtengo el ILog?
Mickey Perlstein
3
No funciona para mí a menos que llame en BasicConfigurator.Configure(hierarchy);lugar de solo configurar hierarchy.Configured = true;.
Eivind Gussiås Løkseth
3
Asegúrese de que el proceso que espera escribir en el archivo de registro tenga permisos de escritura en la carpeta en la que desea que se escriba el archivo de registro. Para diagnosticar problemas de log4net, agregue log4net.Util.LogLog.InternalDebugging = true;antes de cualquier otra llamada de log4net, luego ejecute bajo depurador e inspeccione la salida. log4net te dirá dónde van las cosas mal.
Manfred
12

También puede escapar completamente de XML, escribí una muestra con una configuración programática mínima aquí .

En pocas palabras, esto es lo que necesitas

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
fuente
66
¿Para qué es la clase Jerarquía?
user20358
11

Sí, puede configurar log4net llamando a:

log4net.Config.XmlConfigurator.Configure(XmlElement element)

Consulte la documentación de log4net .

Joe
fuente
Link ahora está muerto
Toby Smith
@TobySmith - arreglado.
Joe
4

Alternativamente, podría crear un atributo personalizado que herede de log4net.Config.ConfiguratorAttribute y codifique su configuración allí:

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

Luego agregue lo siguiente a un archivo .cs:

[assembly: ConsoleApplication1.MyConfigurator]
Jas
fuente
1

Para aquellos que no desean agregar un agregado al registrador raíz, sino al registrador actual / otro:

//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
fuente
0

La respuesta aceptada funciona después de encontrar dos advertencias:

  • Al principio no funcionaba para mí, pero después de usar una ruta absoluta absoluta para roller.File propiedad, comenzó a funcionar.
  • Tuve que usar esto en F # (en un script fsx), por lo que tuve algunos problemas al convertirlo de C #. Si está interesado en el resultado final (incluida una forma de descargar el paquete log4net nuget), consulte a continuación:

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
fuente