Para integrar log4net con MySQL en una aplicación WinForms, sigue estos pasos detallados con código de ejemplo.
- Instalación de paquetes NuGet
Agrega el paquete log4net mediante la consola de paquetes:
Install-Package log4net
Luego instala MySql.Data (versión 6.8.3, versiones superiores pueden causar problemas):
Install-Package MySql.Data -Version 6.8.3
- Configuración de App.config
Dentro del nodo <configuration> agrega la fábrica de proveedores de base de datos:
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL"
type="MySql.Data.MySqlClient.MySqlConnection, MySql.Data, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
- Clase auxiliar de logging (LogHelper)
Crea una clase estática que encapsule el uso de log4net:
using MySql.Data.MySqlClient;
using System;
namespace Utilidades
{
public static class GestorLogs
{
private static readonly log4net.ILog InfoLog = log4net.LogManager.GetLogger("info");
private static readonly log4net.ILog ErrorLog = log4net.LogManager.GetLogger("error");
public static void RegistrarInfo(string mensaje)
{
if (InfoLog.IsInfoEnabled)
InfoLog.Info(mensaje);
}
public static void RegistrarError(string mensaje, Exception excepcion = null)
{
if (!string.IsNullOrEmpty(mensaje) && excepcion == null)
{
ErrorLog.ErrorFormat("【Información adicional】 : {0}<br>", mensaje);
}
else if (!string.IsNullOrEmpty(mensaje) && excepcion != null)
{
string errorFormateado = FormatearError(excepcion);
ErrorLog.ErrorFormat("【Información adicional】 : {0}<br>{1}", mensaje, errorFormateado);
}
else if (string.IsNullOrEmpty(mensaje) && excepcion != null)
{
string errorFormateado = FormatearError(excepcion);
ErrorLog.Error(errorFormateado);
}
}
private static string FormatearError(Exception ex)
{
string msg = $"【Tipo de excepción】: {ex.GetType().Name} <br>【Mensaje】: {ex.Message} <br>【Pila de llamadas】: {ex.StackTrace}";
msg = msg.Replace("\r\n", "<br>");
msg = msg.Replace("en ", "<strong style=\"color:red\">en </strong>");
return msg;
}
}
}
- Manejador global de excepciones y configuración de appenders
Implementa una clase que capture excepciones no controladas y configure el appender de log4net para MySQL:
using log4net.Appender;
using log4net.Config;
using log4net.Layout;
using System;
using System.Data;
using System.Windows.Forms;
namespace PruebaLog4N
{
public class ControladorExcepciones
{
private static string CadenaConexion = "server=servidor;port=3306;database=basedatos;uid=usuario;pwd=contraseña;";
public static void VincularManejadores()
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += (sender, e) =>
GestorLogs.RegistrarError(null, e.Exception as Exception);
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
GestorLogs.RegistrarError(null, e.ExceptionObject as Exception);
CargarAppenderMySQL();
}
private static void CargarAppenderMySQL()
{
var jerarquia = log4net.LogManager.GetRepository() as log4net.Repository.Hierarchy.Hierarchy;
if (jerarquia == null) return;
var appender = new AdoNetAppender
{
Name = "MySQLAppender",
CommandType = CommandType.Text,
BufferSize = 1,
ConnectionType = "MySql.Data.MySqlClient.MySqlConnection, MySql.Data, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
ConnectionString = CadenaConexion,
CommandText = @"INSERT INTO `registro_logs` (`Fecha`, `Hilo`, `Nivel`, `Logger`, `Metodo`, `Ubicacion`, `Mensaje`, `Excepcion`)
VALUES (@Fecha, @Hilo, @Nivel, @Logger, @Metodo, @Ubicacion, @Mensaje, @Excepcion)"
};
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Fecha",
DbType = DbType.DateTime,
Layout = new RawTimeStampLayout()
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Hilo",
DbType = DbType.String,
Size = 255,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%thread"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Nivel",
DbType = DbType.String,
Size = 50,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Logger",
DbType = DbType.String,
Size = 255,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Metodo",
DbType = DbType.String,
Size = 255,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%method"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Ubicacion",
DbType = DbType.String,
Size = 255,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%location"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Mensaje",
DbType = DbType.String,
Size = 4000,
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%message"))
});
appender.AddParameter(new AdoNetAppenderParameter
{
ParameterName = "@Excepcion",
DbType = DbType.String,
Size = 4000,
Layout = new ExceptionLayout()
});
appender.ActivateOptions();
BasicConfigurator.Configure(appender);
}
// Método alternativo para registro en archivo (comentado)
// private static void CargarAppenderArchivo() { ... }
}
}
- Uso en la aplicación
En el punto de entrada de tu aplicación (por ejemplo, Main o el constructor del formulario principle) llama a:
ControladorExcepciones.VincularManejadores();
Esto habilitará la captura de excepciones no controladas y las registrará en la base de datos MySQL.
Nota: Asegúrate de que la tabla registro_logs exista en tu base de datos con las columnas correspondientes (Fecha DATETIME, Hilo VARCHAR(255), Nivel VARCHAR(50), etc.).