c# - studio - log4net structured logging
incapaz de hacer que log4net funcione con el servicio.net windows (10)
Después de verificar y volver a verificar ... :-)
Todo lo que necesita es llamar a XmlConfigurator.Configure();
antes de crear el registrador (solo una vez).
Encantado de ayudarle,
Ofir
Tengo un servicio de Windows con un app.config
y un log4net.config
.
app.config
:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net configSource="log4net.config" />
log4net.config
:
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="D:/Projects/Integration/Interface Module/bin/Logs/MyFirstLogger.log"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
También he agregado esto en AssemblyInfo.cs
:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Y en una de mis clases, tengo:
private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
y
_log.Info(content);
Le he dado a todos los usuarios permisos completos para mi carpeta de registros.
Mi carpeta bin (de la cual se está ejecutando el servicio) tiene mi app.config
y log4net.config
.
Pero no se generó ningún archivo de registro. ¿Qué ajustes perdí?
Actualizado el 4 de marzo de 2014
Si está utilizando un archivo de configuración separado como lo hice (log4net.config), recuerde establecer la configuración del Copy to output directory
en Copy always
en el Explorador de soluciones
Lo siento si algunos de estos parecen obvios, pero esto es lo que comprobaría:
Asegúrese de tener las propiedades de su archivo log4net.config Copiar a la salida establecida en Copiar siempre, verifique buscando el archivo en su directorio bin
También tenga en cuenta desde los documentos de log4net relacionados con las propiedades de AssemblyInfo.cs:
El uso de atributos puede ser un método más claro para definir de dónde se cargará la configuración de la aplicación. Sin embargo, vale la pena señalar que los atributos son puramente pasivos. Son solo información. Por lo tanto, si usa los atributos de configuración, debe invocar a log4net para que pueda leer los atributos. Una simple llamada a LogManager.GetLogger hará que se lean y procesen los atributos en el conjunto de llamadas. Por lo tanto, es imprescindible realizar una llamada de registro tan pronto como sea posible durante el inicio de la aplicación, y ciertamente antes de que se hayan cargado e invocado los ensamblados externos .
Para solucionar problemas, puede intentar cambiar de la propiedad de nivel de ensamblaje a una llamada de configuración explícita
XmlConfigurator.Configure ();
debería ser suficiente
Siempre hago de log4net.config un archivo de configuración completo, empezando por
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net> ... </log4net> </configuration>
No debería necesitar nada en app.config relacionado con log4net, siempre y cuando su archivo de configuración sea log4net.config
Si va a crear un archivo de configuración diferente y coloca cosas relacionadas con log4net en él, necesitará usar [assembly: log4net.Config.XmlConfigurator(ConfigFile = @".../log4net.config", Watch = true)]
dentro de AssemblyInfo.cs en lugar de simplemente
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
De lo contrario, debe poner <log4net> ... </log4net>
parte de la configuración dentro de su App.config
log4net se ejecuta bajo los privilegios del usuario activo. Asegúrese de que el usuario activo tenga derechos para crear / modificar / eliminar el archivo de texto especificado.
Por diseño Log4Net es
fail-stop, nos referimos a que log4net no arrojará excepciones inesperadas en el tiempo de ejecución, lo que podría causar el bloqueo de la aplicación
Por lo tanto, es muy difícil averiguar qué está causando el problema.
¿Cómo habilito la depuración interna de log4net?
DESDE PREGUNTAS FRECUENTES - http://logging.apache.org/log4net/release/faq.html
- La depuración interna también se puede habilitar estableciendo un valor en el archivo de configuración de la aplicación (no en el archivo de configuración de log4net, a menos que los datos de configuración de log4net estén incrustados en el archivo de configuración de la aplicación). La configuración de la aplicación log4net.Internal.Debug debe establecerse en el valor verdadero. Por ejemplo:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings> </configuration>
Esta configuración se lee inmediatamente al inicio y hará que se emitan todos los mensajes de depuración internos.
- . Para habilitar la depuración interna de log4net mediante programación, debe establecer la propiedad log4net.Util.LogLog.InternalDebugging en verdadero. Obviamente, cuanto antes se establezca esto, se producirán más depuraciones.
Así que aquí hay una clase personalizada que creé para log4Net, porque el archivo de configuración era muy confuso. Creé esta clase de ayuda
- Puedes iniciar tantos appenders que necesites en las aplicaciones, así que si uno llama a otros dll, ambos pueden iniciar anexos y los dos anexos funcionarán.
- también puede cerrar el appender y (como en el caso de un apéndice de archivo) luego enviarlo como un correo electrónico
Log4NetFileHelper log = new Log4NetFileHelper(); log.Init(); //Initialize log.AddConsoleLogging(); //Add Console Logging log.AddFileLogging(Path.Combine(AssemblyDirectory, "BatchConsole.log")); log.AddFileLogging(Path.Combine(AssemblyDirectory,"BatchConsole_error.log"),log4net.Core.Level.Error);
Establezca esta propiedad en True log4net.Util.LogLog.InternalDebugging = true;
public class Log4NetFileHelper
{
private string DEFAULT_LOG_FILENAME=string.Format("application_log_{0}.log",DateTime.Now.ToString("yyyyMMMdd_hhmm"));
Logger root;
public Log4NetFileHelper()
{
}
public virtual void Init()
{
root = ((Hierarchy)LogManager.GetRepository()).Root;
//root.AddAppender(GetConsoleAppender());
//root.AddAppender(GetFileAppender(sFileName));
root.Repository.Configured = true;
}
#region Public Helper Methods
#region Console Logging
public virtual void AddConsoleLogging()
{
ConsoleAppender C = GetConsoleAppender();
AddConsoleLogging(C);
}
public virtual void AddConsoleLogging(ConsoleAppender C)
{
root.AddAppender(C);
}
#endregion
#region File Logging
public virtual FileAppender AddFileLogging()
{
return AddFileLogging(DEFAULT_LOG_FILENAME);
}
public virtual FileAppender AddFileLogging(string sFileFullPath)
{
return AddFileLogging(sFileFullPath, log4net.Core.Level.All);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold)
{
return AddFileLogging(sFileFullPath, threshold,true);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold, bool bAppendfile)
{
FileAppender appender = GetFileAppender(sFileFullPath, threshold , bAppendfile);
root.AddAppender(appender);
return appender;
}
public virtual SmtpAppender AddSMTPLogging(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender appender = GetSMTPAppender(smtpHost, From, To, CC, subject, threshhold);
root.AddAppender(appender);
return appender;
}
#endregion
public log4net.Appender.IAppender GetLogAppender(string AppenderName)
{
AppenderCollection ac = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Appenders;
foreach(log4net.Appender.IAppender appender in ac){
if (appender.Name == AppenderName)
{
return appender;
}
}
return null;
}
public void CloseAppender(string AppenderName)
{
log4net.Appender.IAppender appender = GetLogAppender(AppenderName);
CloseAppender(appender);
}
private void CloseAppender(log4net.Appender.IAppender appender)
{
appender.Close();
}
#endregion
#region Private Methods
private SmtpAppender GetSMTPAppender(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender lAppender = new SmtpAppender();
lAppender.Cc = CC;
lAppender.To = To;
lAppender.From = From;
lAppender.SmtpHost = smtpHost;
lAppender.Subject = subject;
lAppender.BufferSize = 512;
lAppender.Lossy = false;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
private ConsoleAppender GetConsoleAppender()
{
ConsoleAppender lAppender = new ConsoleAppender();
lAppender.Name = "Console";
lAppender.Layout = new
log4net.Layout.PatternLayout(" %message %n");
lAppender.Threshold = log4net.Core.Level.All;
lAppender.ActivateOptions();
return lAppender;
}
/// <summary>
/// DETAILED Logging
/// log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
///
/// </summary>
/// <param name="sFileName"></param>
/// <param name="threshhold"></param>
/// <returns></returns>
private FileAppender GetFileAppender(string sFileName , log4net.Core.Level threshhold ,bool bFileAppend)
{
FileAppender lAppender = new FileAppender();
lAppender.Name = sFileName;
lAppender.AppendToFile = bFileAppend;
lAppender.File = sFileName;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
//private FileAppender GetFileAppender(string sFileName)
//{
// return GetFileAppender(sFileName, log4net.Core.Level.All,true);
//}
#endregion
private void ConfigureLog(string sFileName)
{
}
}
Cuando dice ''Todos los usuarios'' tienen permisos completos para el directorio de registro, ¿esto incluye las cuentas de servicio?
Verifique que LocalService, NetworkService, LocalSystem, etc. tengan permisos (dependiendo del contexto en que se esté ejecutando el servicio).
Además, suponiendo que tiene un arnés para ejecutar el servicio como una aplicación, ¿el registro funciona cuando se ejecuta como su usuario?
Si no funciona bien como una aplicación, tiene un problema con la configuración de log4net (que otras respuestas han tratado de resolver).
¿Podrían cargar su aplicación para poder depurarla yo mismo?
algunos recomiendo verificar:
reemplace toda la "/" en su ruta de archivo a "/"
poner toda la configuración de log4net incrustada en el archivo de configuración de la aplicación.
habilitar la depuración de log4net ( ver aquí )
prueba una configuración diferente. acaba de obtener una configuración de muestra para algún lugar en Internet.
solo para estar seguro, otorgaría permisos máximos para todos los usuarios a su directorio de registro
intente desinstalar el servicio y reinstalarlo.
Aquí está la configuración que funciona para mí.
AssemblyInfo.cs
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net.config", Watch = true)]
Log4net.Config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="C:/TEMP/Logs.txt"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock,log4net" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
C # Code
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(class_name));
Tengo esta configuración en el proyecto de biblioteca de clase C # y todo el otro proyecto utiliza esta referencia de proyecto para registrar las excepciones.
si tiene un archivo separado para log4net.config. ¿Has establecido la siguiente propiedad?
Copiar al directorio de salida = Copiar siempre
Tenga en cuenta que cuando el proceso se ejecuta como servicio de Windows, Environment.CurrentDirectory será "C: / Windows / system32"
Entonces, si coloca el archivo de configuración de log4net (log4net.config) al lado de su * .exe, puede usar el siguiente código para configurar log4net.
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
XmlConfigurator.Configure(new FileInfo(Path.Combine(assemblyFolder, "log4net.config")));