Registro de logs en MySQL desde una aplicación WinForms usando log4net

Para integrar log4net con MySQL en una aplicación WinForms, sigue estos pasos detallados con código de ejemplo.

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

  1. 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() { ... }
    }
}

  1. 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.).

Etiquetas: log4net MySQL WinForms C# AdoNetAppender

Publicado el 7-2 00:00