概述
Log4net将自身定义信息保存到文本文件和数据库的操作很简单,但是,这些信息有时不符合我们的要求,例如:我想多一些属性值,此时就不不行了。
实现
1、下载log4net,添加log4net引用。
2、创建数据库
<span style="font-size:18px;">create talbe MyLogTable
(
id int primary key identity(1,1),
userid varchar(32),
username varchar(32)
)</span>
3、添加实体类,属性为自定义的字段
namespace Log4NetToDatabase
{
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; }
}
}
}
4、添加参数转换器类,每个字段一个模式转化类
namespace Log4NetToDatabase
{
internal sealed class UserIdPatternConverter : PatternLayoutConverter
{
override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
LogMessage logMessage = loggingEvent.MessageObject as LogMessage;
if (logMessage != null)
{
// 将UserName作为日志信息输出
writer.Write(logMessage.Userid);
}
}
}
internal sealed class UserNamePatternConverter : PatternLayoutConverter
{
override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
LogMessage logMessage = loggingEvent.MessageObject as LogMessage;
if (logMessage != null)
// 将UserName作为日志信息输出
writer.Write(logMessage.Username);
}
}
}
5、自定义layout类
namespace Log4NetToDatabase
{
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; }
}
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; }
}
}
}
}
6
、添加配置信息
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<logger name="<span style="font-family: Arial, Helvetica, sans-serif;">log4netToSqlServer</span><span style="font-family: Arial, Helvetica, sans-serif;">"></span>
<level value="INFO"/>
<appender-ref ref="AdoNetAppender_SqlServer"/>
</logger>
<!--SqlServer数据库-->
<appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<connectionString value="server=****;database=***;user id=***;password=***"/>
<commandText value="INSERT INTO MyLogTable(userid,username) VALUES (@userid,@username)"/>
<bufferSize value="1"/>
<!--自定义成员 -->
<parameter>
<parameterName value="@userid"/>
<dbType value="String"/>
<size value="50"/>
<!--自定义layout类的信息-->
<layout type="Log4NetToDatabase.CustomLayout">
<conversionPattern value="%userid"/>
</layout>
</parameter>
<parameter>
<parameterName value="@username"/>
<dbType value="String"/>
<size value="20"/>
<layout type="Log4NetToDatabase.CustomLayout">
<conversionPattern value="%username"/>
</layout>
</parameter>
</appender>
</log4net>
7、程序编码
log4net.Config.XmlConfigurator.Configure();
ILog log = log4net.LogManager.GetLogger("log4netToSqlServer");
LogMessage message = new Log4NetToDatabase.LogMessage(userID, UserName);
log.Info(message);
总结
自定义字段信息到数据库和自定义字段信息到文本的操作是一样的,不一样的是配置文件的修改.