/// <summary>
/// 一个用于将log4net日志内容写入mongodb数据库的自定义Appender
/// </summary>
public class MongoAppender : log4net.Appender.BufferingAppenderSkeleton
{
/// <summary>
/// new
/// </summary>
public MongoAppender()
: base(true)
{
}
/// <summary>
/// Mongodb连接字符串
/// </summary>
public string ConnectionString
{
get;
set;
}
/// <summary>
/// SendBuffer
/// 写入数据库中
/// </summary>
/// <param name="events"></param>
protected override void SendBuffer(Core.LoggingEvent[] events)
{
if (events != null && events.Length > 0)
{
List<Log> logs = new List<Log>();
foreach (var child in events)
{
logs.Add(new Log
{
_id = MongoDB.Oid.NewOid(),
Date = child.TimeStamp,
Exception = child.GetExceptionString(),
Level = child.Level.DisplayName,
Logger = child.LoggerName,
Message = child.RenderedMessage,
Thread = child.ThreadName
});
}
using (var db = new DataContext(this.ConnectionString))
{
db.Logs.Insert(logs);
}
}
}
}
/// <summary>
/// MongoDB中表Log的映射实体类。
/// </summary>
public class Log
{
/// <summary>
/// id
/// </summary>
public MongoDB.Oid _id
{
get;
set;
}
/// <summary>
/// 时间
/// </summary>
public DateTime Date
{
get;
set;
}
/// <summary>
/// 线程ID
/// </summary>
public string Thread
{
get;
set;
}
/// <summary>
/// 级别
/// </summary>
public string Level
{
get;
set;
}
/// <summary>
/// Logger
/// </summary>
public string Logger
{
get;
set;
}
/// <summary>
/// 内容
/// </summary>
public string Message
{
get;
set;
}
/// <summary>
/// 异常
/// </summary>
public string Exception
{
get;
set;
}
}
/// <summary>
/// 数据访问上下文类。
/// </summary>
public class DataContext : Novus.Data.Mongo.DataContext
{
private MongoDB.IMongoCollection<Log> _logs = null;
/// <summary>
/// new
/// </summary>
public DataContext(string connectionString)
: base(connectionString)
{
}
/// <summary>
/// 返回表Logs的映射
/// </summary>
public MongoDB.IMongoCollection<Log> Logs
{
get
{
if (this._logs == null)
this._logs = base.GetTalbe<Log>("Logs");
return this._logs;
}
}
}
代码很简单,MongoAppender继承自log4net.Appender.BufferingAppenderSkeleton,实现SendBuffer方法即可。
这里给出用于访问mongodb的datacontext
(mongodb的客户端为mongodb-csharp)
/// <summary>
/// 此类为用于访问MongoDB数据库的基础虚类。
/// MongoDB的客户端为MongoDB CSharp。
/// </summary>
public class DataContext : IDisposable
{
#region Static Members
/// <summary>
/// 获取设置当前Context ConfigurationManager连接字符串Key
/// </summary>
static public string connectionStringKey = "mongo";
#endregion
#region Private Members
private MongoDB.Mongo _Mongo = null;
private MongoDB.IMongoDatabase _database = null;
#endregion
#region Constructors
/// <summary>
/// new
/// </summary>
public DataContext()
: this(ConfigurationManager.ConnectionStrings[connectionStringKey].ConnectionString)
{
}
/// <summary>
/// new
/// </summary>
/// <param name="connectionString">如:Server=localhost;Database=test</param>
public DataContext(string connectionString)
{
this.IsOpen = false;
this.ConnectionString = connectionString;
this.DataBaseName = connectionString.Split(';').Where(c => c.ToLower().StartsWith("database=")).First().Substring(9);
}
#endregion
#region Protected Properties
/// <summary>
/// True表示MongoDB数据库连接已经打开。
/// </summary>
protected virtual bool IsOpen
{
get;
set;
}
/// <summary>
/// 获取MongoDB数据库连接字符串
/// </summary>
protected virtual string ConnectionString
{
get;
set;
}
/// <summary>
/// 获取数据库名称
/// </summary>
protected virtual string DataBaseName
{
get;
set;
}
/// <summary>
/// 获取或设置Mongo对象
/// </summary>
protected virtual MongoDB.Mongo Mongo
{
get
{
if (this._Mongo == null)
this._Mongo = new MongoDB.Mongo(this.ConnectionString);
return this._Mongo;
}
}
/// <summary>
/// 获取数据库
/// </summary>
protected virtual MongoDB.IMongoDatabase DataBase
{
get
{
if (this._database == null)
{
this.Connect();
this._database = this.Mongo[this.DataBaseName];
}
return this._database;
}
}
#endregion
#region Protected Methods
/// <summary>
/// 开始连接MongoDB数据库
/// </summary>
protected virtual void Connect()
{
if (!this.IsOpen)
{
this.IsOpen = true;
this.Mongo.Connect();
}
}
/// <summary>
/// 获取Mongo的表映射。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tableName"></param>
/// <returns></returns>
protected virtual MongoDB.IMongoCollection<T> GetTalbe<T>(string tableName) where T : class
{
return this.DataBase.GetCollection<T>(tableName);
}
#endregion
#region Public Methods
/// <summary>
/// 写入文件
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="fileContents">文件内容</param>
/// <returns>返回存储在MongoDB中的文件名。</returns>
public virtual string InsertFile(string fileName, byte[] fileContents)
{
if (!string.IsNullOrEmpty(fileName) && fileContents != null)
{
string newFileName = string.Format("{0}{1}", MongoDB.Oid.NewOid().ToString(), System.IO.Path.GetExtension(fileName));
var gf = new MongoDB.GridFS.GridFile(this.DataBase);
using (var gfs = gf.Create(newFileName, System.IO.FileMode.CreateNew))
{
gfs.Write(fileContents, 0, fileContents.Length);
}
return newFileName;
}
return null;
}
/// <summary>
/// 根据文件名获取文件内容
/// </summary>
/// <param name="fileName">文件名</param>
/// <returns></returns>
public virtual byte[] GetFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
var gf = new MongoDB.GridFS.GridFile(this.DataBase);
if (gf.Exists(fileName))
{
using (var gfs = gf.OpenRead(fileName))
{
byte[] array = new byte[gfs.Length];
gfs.Read(array, 0, array.Length);
return array;
}
}
}
return null;
}
/// <summary>
/// 删除文件
/// </summary>
/// <param name="fileName"></param>
public virtual void RemoveFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
var gf = new MongoDB.GridFS.GridFile(this.DataBase);
gf.Delete(fileName);
}
}
#endregion
#region IDisposable Members
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (this.Mongo != null)
{
this.Mongo.Dispose();
this._Mongo = null;
}
this._database = null;
}
#endregion
}
最后附上配置文件

代码<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
<appender name="MongoAppender" type="log4net.Appender.MongoAppender, log4net.Appender">
<!--设置每20条日志写入数据库一次-->
<bufferSize value="20" />
<!--设置MongoDB数据库连接字符串-->
<connectionString value="Server=localhost;Database=GOA2" />
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="MongoAppender" />
</root>
</log4net>
</configuration>