Log4net自定义信息存入数据库

本文档介绍了如何在Asp.Net应用中利用Log4net将日志信息,包括自定义的UserId和UserName字段,存储到Oracle数据库。首先创建LOG表,然后在项目中添加必要的引用和配置文件,接着编写自定义字段类、字段辅助类、字段转换类和日志工具类。最后,在页面中调用日志输出并展示了结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Asp.Net 应用 ;Oracle数据库

1. 新建数据库表Log

create table LOG

(

 --默认信息

  DATETIME  DATE,

  THREAD    VARCHAR2(255),

  LOG_LEVEL VARCHAR2(255),

  LOGGER    VARCHAR2(255),

  MESSAGE   VARCHAR2(4000),

 --自定义信息

  USERID    VARCHAR2(50),

  USERNAME  VARCHAR2(20),

)

2. 新建Asp.Net网站 解决方案名:Log4net

  (1) 添加引用

       System.Data.OracleClient

       log4net.dll

  (2) 添加全局配置文件Global.asax

  (3) 根目录添加文件夹Log用来存放日志输出的文本文件

到此项目结构如:

3. 配置文件web.config请看清楚位置,配置文件中的其它内容默认即可-数据库连接字符串一定要改正确

<?xml version="1.0"?>
<configuration>
	<configSections>
		<!-- log4net-->
		<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
		
	</configSections>
	<log4net>
		<!-- 
		根节点<root>可以对日志级别进行控制<level value="INFO"/>
		在这个根节点处可以设置appender列表如:
		AdoNetAppender_Oracle 存入数据库
		ColoredConsoleAppender 输出到控制台
		RollingFileAppender 输出到文本文件
		这里灵活定义,在这里选择INFO级别并且输入到Oracle数据库
		 -->
		<root>
			<level value="INFO"/>
			<appender-ref ref="AdoNetAppender_Oracle"/>
		</root>
		<!--
		这个logger可要可不要,如果不要会默认根节点执行
		如果配置,会根据配置里面的<level value="INFO"/>
		到根节点中找到相应级别然后调用appender输出
		有这个节点的好处,可以程序中通过name="WebLogger"
		得到用哪一个logger模式控制日志信息
		-->
		<logger name="WebLogger">
			<level value="INFO"/>
		</logger>
        <logger name="开发用">
            <level value="DEBUG"/>
            <appender-ref ref="RollingFileAppender"/>
        </logger>
		<!--
		输出到文本文件
		网站根目录Log/log.txt
		-->
		<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
			<file value="Log/log.txt"/>
			<appendToFile value="true"/>
			<maxSizeRollBackups value="20"/>
			<maximumFileSize value="500"/>
			<rollingStyle value="Date"/>
			<datePattern value="yyyy-MM-dd"/>
			<staticLogFileName value="true"/>
			<layout type="log4net.Layout.PatternLayout">
				<param name="Header" type="log4net.Util.PatternString" value="[%date]%newline"/>
				<param name="Footer" value="

"/>
				<conversionPattern value="%-5level %date %logger - %message%newline"/>
			</layout>
		</appender>
		<!--Oracle数据库-->
		<appender name="AdoNetAppender_Oracle" type="log4net.Appender.AdoNetAppender">
			<!-- Oracle数据源 ,本地安装Oracle客户端-->
			<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
			<!-- Oracle连接字符串-->
			<connectionString value="data source=jdlcerp;User ID=jduser;Password=jduser"/>
			<!--
			Log4net默认数据表中有Datetime,Thread,Log_Level,Logger,Message这五个字段
			数据库表名Log
			我们创建数据表时,可以根据自已需求
			在这里创建的Log表多加userid,username两个字段
			数据表自已提前在数据库定义好			
			-->
			<commandText value="INSERT INTO Log (Datetime,Thread,Log_Level,Logger,Message,userid,username) VALUES (:log_date, :thread, :log_level, :logger, :message,:userid,:username)"/>
			<!--
			 设置缓存区大小
			 1表明有一条日志就要写入
			 如果10就表示日志到达10条时一起写入
			 -->
			<bufferSize value="1"/>
			<!--默认已有的成员 -->
			<parameter>
				<parameterName value=":log_date"/>
				<dbType value="DateTime"/>
				<layout type="log4net.Layout.RawTimeStampLayout"/>
			</parameter>
			<parameter>
				<parameterName value=":thread"/>
				<dbType value="String"/>
				<size value="255"/>
				<layout type="log4net.Layout.PatternLayout">
					<conversionPattern value="%thread"/>
				</layout>
			</parameter>
			<parameter>
				<parameterName value=":log_level"/>
				<dbType value="String"/>
				<size value="50"/>
				<layout type="log4net.Layout.PatternLayout">
					<conversionPattern value="%level"/>
				</layout>
			</parameter>
			<parameter>
				<parameterName value=":logger"/>
				<dbType value="String"/>
				<size value="255"/>
				<layout type="log4net.Layout.PatternLayout">
					<conversionPattern value="%logger"/>
				</layout>
			</parameter>
			<parameter>
				<parameterName value=":message"/>
				<dbType value="String"/>
				<size value="4000"/>
				<layout type="log4net.Layout.PatternLayout">
					<conversionPattern value="%message"/>
				</layout>
			</parameter>
			<!--自定义成员 -->
			<parameter>
				<parameterName value=":userid"/>
				<dbType value="String"/>
				<size value="50"/>
				<!--
				CustomLayout类的命名空间由自己定义
				请注意否则这里找不到定义的字段
				此例定义命名空间是:Log4Net
				在这个命名空间下写了一个类CustomLayout
				用来配置自定义的字段
				-->
				<layout type="Log4Net.CustomLayout">
					<conversionPattern value="%userid"/>
				</layout>
			</parameter>
			<parameter>
				<parameterName value=":username"/>
				<dbType value="String"/>
				<size value="20"/>
				<layout type="Log4Net.CustomLayout">
					<conversionPattern value="%username"/>
				</layout>
			</parameter>
		</appender>
	</log4net>

</configuration>

4. App_Code中添加类文件,以实现自定义信息

  (1)添加自字义字段类 ,创建一个新字段,添加这样一个类

     1) UserIdPatternConverter.cs

using System;
using System.Collections.Generic;
using System.Text;
using log4net.Layout.Pattern;
using System.IO;
using log4net.Core;
namespace Log4net
{
    internal sealed class UserIdPatternConverter : PatternLayoutConverter
    {
        override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            LogMessage logMessage = loggingEvent.MessageObject as LogMessage;
            if (logMessage != null)
                writer.Write(logMessage.Userid);
        }
    }
}

     2) UserNamePatternConverter.cs

using System;
using System.Collections.Generic;
using System.Text;
using log4net.Layout.Pattern;
using System.IO;
using log4net.Core;
namespace Log4net
{
    internal sealed class UserNamePatternConverter : PatternLayoutConverter 
    {
        override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            LogMessage logMessage = loggingEvent.MessageObject as LogMessage;
            if (logMessage != null)
                writer.Write(logMessage.Username);
        }
    }
}

  (2) 添加字段辅助类LogMessage.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.SessionState;
namespace Log4net
{
    public class LogMessage:IRequiresSessionState
    {
        public LogMessage(){  }
        public LogMessage(string userID,string UserName)
        {
            this.userid = userID;
            this.username = UserName;
        }
        private string userid;
        public string Userid
        {
            get { return userid; }
            set { userid = value; }
        }
        private string username;
        public string Username
        {
            get { return username; }
            set { username = value; }
        }
    }
}

  (3) 添加字段转换类CustomLayout.cs

using System;
using System.Collections;
using System.IO;
using log4net.Core;
using log4net.Layout.Pattern;
using log4net.Util;
using log4net.Layout;
using Log4net;
namespace Log4Net
{
	public class CustomLayout : log4net.Layout.LayoutSkeleton
	{
		public const string DefaultConversionPattern ="%message%newline";
        public const string DetailConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline";
		private static Hashtable s_globalRulesRegistry;
		private string m_pattern;
  		private PatternConverter m_head;
		private Hashtable m_instanceRulesRegistry = new Hashtable();
		//这里是重点-------------------------------------------------------
        /// <summary>
        /// 把自定义的字段放进Hashtable
        /// 定义多少个写多少个
        /// 注意这里有名称要和配置文件中的名称一致
        /// 注意命名空间
        /// 在配置文件中要用到命名空间
        /// </summary>
		static CustomLayout()
		{
			s_globalRulesRegistry = new Hashtable(2);
            s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter));
            s_globalRulesRegistry.Add("userid", typeof(UserIdPatternConverter));
		}
        //--------------------------------------------------------------------
		public CustomLayout() : this(DefaultConversionPattern)
		{}
        public CustomLayout(string pattern) 
		{
			IgnoresException = true;
			m_pattern = pattern;
			if (m_pattern == null)
			{
				m_pattern = DefaultConversionPattern;
			}
			ActivateOptions();
		}
		public string ConversionPattern
		{
			get { return m_pattern;	}
			set { m_pattern = value; }
		}
        /// <summary>
        /// 对Hashtable中的值进行转换
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
		virtual protected PatternParser CreatePatternParser(string pattern) 
		{
			PatternParser patternParser = new PatternParser(pattern);
			foreach(DictionaryEntry entry in s_globalRulesRegistry)
			{
				patternParser.PatternConverters[entry.Key] = entry.Value;
			}
			foreach(DictionaryEntry entry in m_instanceRulesRegistry)
			{
				patternParser.PatternConverters[entry.Key] = entry.Value;
			}
			return patternParser;
		}
		override public void ActivateOptions() 
		{
			m_head = CreatePatternParser(m_pattern).Parse();

			PatternConverter curConverter = m_head;
			while(curConverter != null)
			{
				PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter;
				if (layoutConverter != null)
				{
					if (!layoutConverter.IgnoresException)
					{
						this.IgnoresException = false;

						break;
					}
				}
				curConverter = curConverter.Next;
			}
		}
		override public void Format(TextWriter writer, LoggingEvent loggingEvent) 
		{
			if (writer == null)
			{
				throw new ArgumentNullException("writer");
			}
			if (loggingEvent == null)
			{
				throw new ArgumentNullException("loggingEvent");
			}
			PatternConverter c = m_head;
			while(c != null) 
			{
				c.Format(writer, loggingEvent);
				c = c.Next;
			}
		}
		public void AddConverter(ConverterInfo converterInfo)
		{
			AddConverter(converterInfo.Name, converterInfo.Type);
		}
		public void AddConverter(string name, Type type)
		{
			if (name == null) throw new ArgumentNullException("name");
			if (type == null) throw new ArgumentNullException("type");

			if (!typeof(PatternConverter).IsAssignableFrom(type))
			{
				throw new ArgumentException("The converter type specified ["+type+"] must be a subclass of log4net.Util.PatternConverter", "type");
			}
			m_instanceRulesRegistry[name] = type;
		}
		public sealed class ConverterInfo
		{
			private string m_name;
			private Type m_type;
			public ConverterInfo()
			{}
			public string Name
			{
				get { return m_name; }
				set { m_name = value; }
			}
			public Type Type
			{
				get { return m_type; }
				set { m_type = value; }
			}
		}
	}
}

  (4) 输出日志的工具类LogUtil.cs

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using log4net;
public class LogUtil
{
    public LogUtil()
    {    }
    private static Log4net.LogMessage message=null;
    private static ILog _log;
    public static ILog log
    {
        get
        {
            if (_log == null)
            {
                //从配置文件中读取Logger对象
                 _log = log4net.LogManager.GetLogger("WebLogger");
            }
            return _log;
        }
    }
    public static void debug()
    {
        if (log.IsDebugEnabled)
        {
            log.Debug(message);
        }
    }
    public static void error()
    {
        if (log.IsErrorEnabled)
        {
            log.Error(message);
        }
    }
    public static void fatal()
    {
        if (log.IsFatalEnabled)
        {
            log.Fatal(message);
        }
    }
    public static void info()
    {
        if (log.IsInfoEnabled)
        {
            log.Info(message);
        }
    }
    public static void warn()
    {
        if (log.IsWarnEnabled)
        {
            log.Warn(message);
        }
    }
    /// <summary>
    /// 需要写日志的地方调用此方法
    /// </summary>
    /// <param name="userID">自定义字段</param>
    /// <param name="UserName">自定义字段</param>
    /// <param name="level">自定义级别</param>
    public static void SaveMessage(string userID, string UserName, int level)
    {
        message = new Log4net.LogMessage(userID,UserName);//用到字段辅助类
        switch (level){case 1: info(); break; case 2: warn(); break; case 3: error(); break; case 4: fatal(); break; default: break; }
    }
}

5. 具体应用

  (1) 在使用日志之前,必须监视Log4net配置;一种可以直接在类中,一种可以配置到全局配置文件中如全局配置     

 void Application_Start(object sender, EventArgs e) 
    {
        //在应用程序启动时运行的代码
        log4net.Config.XmlConfigurator.Configure();
    }

  (2) 示例Default.aspx页面,页面为空只是在Page_Load中调用输出日志如:

protected void Page_Load(object sender, EventArgs e)
    {
        //自定义信息
        string userID="10000";
        string userNmae="ajaxtop";
        //级别:1[一般] 2[警告] 3[错误] 4[严重]
        int level = 2;    
        LogUtil.SaveMessage(userID,userNmae,level);
    }

6. 结果


参考:Log4net基础详解Log4net基础详解 


7. 对提出问题的朋友表示感谢,但是没能及时回复又表示歉意,为此整理了一个事例,希望可以帮助到有需求的朋友

Log4Net事例源码

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值