Spiga

自定义log4net Appender,实现日志写入MongoDB中

2011-01-01 19:13 by Dev.Hong, 344 visits, 收藏, 编辑

 

/// <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>