log4net 自定义Appender

时间:2021-09-16 06:00:16

最近有个需求,使用log4net来记录日志,然后将数据保存到服务器端。一开始打算写一个windows service,定期上传日志。

后来又因为一些场景下不适应,因此直接改为保存内存中,到一定阀值之后将数据post到服务器。

考虑用log4net的MemoryAppender,但是没办法控制这个阀值,同时还需要另外配置服务器接受数据地址。

因此也不适用,还好log4net支持自定义Appender,于是,参考MemoryAppender,自定义一个,问题解决。

下面是Appender代码。

  /// <summary>
/// Customize Appender, save the Log in the memory
/// when it the event queue reach maximum queue size
/// the queue will post to sever.
/// </summary>
public class MyMemAppender : AppenderSkeleton
{
#region public properties
public string RemoteAddress { get; set; }
public int QueueSize { get; set; }
#endregion #region Public Instance Constructors
public MyMemAppender()
: base()
{
eventQueue = new ArrayList();
}
#endregion #region private fields
private ArrayList eventQueue;
#endregion #region Override implementation of AppenderSkeleton
protected override void Append(log4net.Core.LoggingEvent loggingEvent)
{
lock (eventQueue.SyncRoot)
{
eventQueue.Add(loggingEvent);
if (eventQueue.Count >= QueueSize)
{
this.Clear();
}
}
}
#endregion #region Public Instance Methods /// <summary>
/// Clear the list of events
/// </summary>
/// <remarks>
/// Clear the list of events
/// </remarks>
virtual public void Clear()
{
lock (eventQueue.SyncRoot)
{
SaveToServer();
eventQueue.Clear();
}
} /// <summary>
/// Gets the events that have been logged.
/// </summary>
/// <returns>The events that have been logged</returns>
/// <remarks>
/// <para>
/// Gets the events that have been logged.
/// </para>
/// </remarks>
virtual public LoggingEvent[] GetEvents()
{
lock (eventQueue.SyncRoot)
{
return (LoggingEvent[])eventQueue.ToArray(typeof(LoggingEvent));
}
} #endregion Public Instance Methods #region private methods
private void SaveToServer()
{
lock (eventQueue.SyncRoot)
{
List<LogModel> logList = new List<LogModel>();
foreach (log4net.Core.LoggingEvent evt in eventQueue)
{
try
{
LogModel m = Newtonsoft.Json.JsonConvert.DeserializeObject<LogModel>(evt.RenderedMessage);
logList.Add(m);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
continue;
}
}
SaveToServer(logList);
}
} private void SaveToServer(List<LogModel> logList)
{
try
{
IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
string str = Newtonsoft.Json.JsonConvert.SerializeObject(logList, Newtonsoft.Json.Formatting.Indented, timeConverter);
PostStrToServer(str, RemoteAddress);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
return;
}
} private void PostStrToServer(string content, string url)
{
using (WebClient client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
client.Encoding = System.Text.Encoding.UTF8;
client.UploadStringAsync(new Uri(url), ("logList=" + content));
}
} #endregion
}

配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
<appender name="myMemAppender" type="LogSystem.Common.MyMemAppender">
<param name="QueueSize" value="10"/>
<param name="RemoteAddress" value="http://localhost/PostLogData.aspx"/>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="myMemAppender" />
</root>
</log4net>

调用方式:

MyMemAppender logger = new MyMemAppender();
logger.QueueSize = ;
logger.RemoteAddress = "http://localhost:57427/PostLogData.aspx";
log4net.Config.BasicConfigurator.Configure(logger);
ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 或者

log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(configPath));
log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);