将Log4Net 日志保存到mongodb数据库实践

log4net的大名早有耳闻,一直没真正用过,这次开发APP项目准备在服务端使用log4net。 日志的数据量较大,频繁的写数据库容易影响系统整体性能,所以独立将日志写到mongodb数据库是不错的选择。---经过2天的摸索,总结出本文档。

github有个开源项目log4mongo-net,另一位斯克迪亚作者根据开源项目又做了修改http://skyd.sinaapp.com/archives/1282

所以直接拿斯克迪亚的代码来使用。

1、将log4net和mongodb驱动升级为最新版本。log2net: 1.2.15   mongodb: 2.2.3.3

2、新加了一个LogHelper类(单件模式),所有的日志通过LogHelper的静态方法来写。

public  class LogHelper
  {
private static readonly LogHelper instance=new LogHelper();  private static ILog log = null;
  
 private Logger()
  {
      // XmlConfigurator.Configure();    
      LogLog.InternalDebugging = true;
       
       
  }
public  static LogHelper getInstance()  {
      if (log == null)
      {
          log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
      }
          return instance;
  }
public void Debug(Object message, Exception exception)
{
  
    log.Debug(message);
}
public void Debug(Object message)
{
  
    log.Debug(message);
}
}

结果发现会有问题,log4net本来可以记录日志发生所在的类名,和具体的行号。如果使用了单独的类来写日志,那么记录下来的类和行号都是LogHelper的内容,没法定位到错误具体发生的位置。原因就在ILog是通过LogManger.GetLogger(Type)方法来获的,要想获取错误的类和行号,那么必须在每个类里单独调用LogManger.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)。(自己的理解,不一定准确)

3、自定义日志内容字段。网上能找到很多Log4net添加字段的方法,但因为我用的是修改过的log4mongo。而且简化了配置,默认就是显示所有字段。所以基本上通过改配置的都不适用。

开始准备使用 LogicalThreadContext.Properties["CustomColumn"] = "Custom value" ,可以将更多自定义的内容写到日志。

执行写日志log.Debug(object)之前,先把各种自定义内容通过LogicalThreadContext设置好。然后再执行log.Debug(object)。

这种方式虽然可以达到目的,但感觉不是很方便。另一个问题是设置LogicalThreadContext后,这些值会一直存在,在同一个线程里再次执行 log.Debug(object)时,任然会记录这些自定义的属性值,不太好控制,容易写错内容。

另一种办法是通过 log.Debug(object)里的object来实现,一般情况下都是直接 log.Debug("this is message")这种方式来写日志,也可以将一个对象传递给 log.Debug。在往数据库写数据前,可以通过loggingEvent.RenderedMessage来读取传递过来的对象,

public  class LogInfo

{

public string AppKey { set; get; }

public string UserID { set; get; }

public string HostName { set; get; }

public string IPAddress { set; get; }

public string Message { set; get; }

public override string ToString()

{

var bsonDoc = this.ToBsonDocument();

return bsonDoc.ToString();

}

}

默认loggingEvent.RenderedMessage是获取object 的ToString()的值,这里需要重写一下ToString(),将类转化为BsonDocument。

loggingEvent.RenderedMessage获取BsonDocument后再拆分为具体的属性。

private static void BuildCustomMessage(string message,ref Log log)

{

try

{

var bson = BsonDocument.Parse(message);

foreach (var item in bson.Elements)

{

string value = item.Value.ToString();

if (item.Value.IsBsonNull)

{

value = string.Empty;

}

log.Properties.Add(item.Name, value);

}

}

catch (Exception)

{

log.RenderedMessage = message;

}

}

为了方便,直接用 BsonDocument.Parse(message)来判断是复杂对象还是String。直接用try catch来处理,对性能会有一点影响。做了测试相比直接传递String不需要BuildCustomMessage ,传递复杂对象时性能相差6%左右。这6%主要是对象ToString()转化为BsonDocument,和BuildCustomMessage两部份。

4、在测试时发生一个奇怪的问题,单独一个语句log.Debug(string)可以输出到控制台,但死活写不到数据库。而用一个循环来执行log.Debug(string),却能正常写到数据库。  log4net有输出Shutdown called on Hierarchy的提示,但不明白是什么意思,也不知道是否有相关。

解决办法是将写数据库的操作由异步改为同步。具体原因没找到。log4net自身问题、  mongodb驱动 、 log4net缓存等等都没法排除。

//collection.InsertOneAsync(BuildBsonDocument(loggingEvent));

collection.InsertOne(BuildBsonDocument(loggingEvent));

5、为了方便日后的维护,将数据库名和Collection(表名)设置到配置文件。

<appender name="MongoDBAppender" type="Log4Mongo.MongoDBAppender, Log4Mongo">

<connectionString value="mongodb://root:[email protected]:27017"/>

<DatabaseName value="log4mongo"/>

<CollectionName value="yyyyMM"/>

</appender>

配置的值在public class MongoDBAppender : AppenderSkeleton这个类里会直接获取,不需要做额外处理

public string ConnectionStringName { get; set; }

public string DatabaseName { get; set; }

public string CollectionName { get; set; }

<CollectionName value="yyyyMM"/>这么写的目的是让日志根据日期来自动分表。通过修改配置就能按日、按月、按年来分表。

        private IMongoCollection<Log> GetCollection()
		{
            string tableName;
            tableName = CollectionName ?? "yyyyMM";
            tableName = "log"+ string.Format("{0:" + tableName + "}", DateTime.Now);
            return GetDatabase().GetCollection<Log>(tableName); 
		}
时间: 2024-10-13 22:27:01

将Log4Net 日志保存到mongodb数据库实践的相关文章

python实现将文件中的每一行文本记录,保存到MongoDB数据库,并防止重复插入

文本如下: #日期 流水号 被浏览页面URL 第×页 访问者IP 访问时间 是否入口 操作系统 浏览器 语言 时区 屏幕分辨率 屏幕色彩位数 省份 城市 接入商 上网场所 是否安装ALEXA 2014-7-17 11452775496 http://www.imaibo.net/space/178120 1 59.41.23.101 2014-7-17 13:38:14 0 Windows XP Chrome 21.0.82014-7-17 11452775466 http://www.imai

vue+vux 仿飞猪app火车票部分(五)---城市列表保存到MongoDB数据库并且启用node.js服务

把车站列表保存到数据库,并且从本地创建服务 node.js创建httpserver 1.搭建基于express的运行环境 全局安装express-gengerator cnpm install -g express-gengerator 2.创建express项目,创建了本地服务 express server 生成server目录,目录下的bin是可执行文件,运行bin下的www文件启动服务 node server/bin/www 启动成功打开浏览器localhost:3000 server下的

mongodb数据库实践笔记

mongodb 操作规则 从网站上下载安装文件然后在安装目录下创建文件夹data和log创建配置文件mongo.config里面填充如下: ##数据文件dbpath=D:\mongodb\data##日志文件logpath=D:\mongodb\log\mongo.log##错误日志采用追加模式,配置这个选项后mongodb的日志会追加到现有的日志文件,而不是从新创建一个新文件 启动mongodb在cmd命令下启动以下命令d:cd d:\MongoDBcd bin然后输入 mongod --co

Vue 添加评论,node作后台保存到MongoDB数据库中

成品图 1.在 textarea 中 v-model 双向绑定要添加的数据,并且 button 中绑定方法 2.将from表单绑定的数据挂载到data上 3. methods 中实现方法,将评论内容以参数形式传进 4.node中调用数据库的create方法添加进数据库 原文地址:https://www.cnblogs.com/zhaohui-116/p/12271161.html

【代码笔记】将log日志保存到文件

代码: #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initW

C# log4net 配置及使用详解--日志保存到文件和Access(转)

按语: 最近项目要求选用Access数据库,但日志管理采用log4net,但保存到数据库一直没有成功,后按照如下配置在程序退出时可以成功保存. 开始新建文件应用log4net.dll  ,重新编译就报缺少log4net的库,后参考网上资料在项目属性中把目标框架由 Framework client 改为Framwork4 就可以了 本程序演示如何利用log4net记录程序日志信息.log4net是一个功能著名的开源日志记录组件.利用log4net可以方便地将日志信息记录到文件.控制台. Windo

入门系列之在Ubuntu 14.04上备份,还原和迁移MongoDB数据库

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由信姜缘 发表于云+社区专栏 MongoDB是最受欢迎的NoSQL数据库引擎之一.它以可扩展,强大,可靠和易于使用而闻名.在本文中,我们将向您展示如何备份,还原和迁移MongoDB数据库. 导入和导出数据库意味着以人类可读的格式处理数据,与其他软件产品兼容.相反,备份和还原操作创建或使用特定于MongoDB的二进制数据,这不仅保留了数据的一致性和完整性,还保留了其特定的MongoDB属性.因此,对于迁移,只要源系统和目标系统兼容,通

用MongoDB数据库来管理办公系统中文档型的表单和信息——通用流程化应用审批单设计思路(二,续)

1.办公系统中文档的定义 办公系统中的文档就是指对数据不敏感的业务,例如流程中的审批单.信息专栏.数据上报.信息记录等.而对于这些信息的管理,特别是时效性较强的管理记录,仍采用关系型数据库进行管理. (1)流程中审批单 流程中审批单由功能按钮区.特殊功能区.业务表单区.附件区.审批意见区等区域构成,其中,业务表单区理论上包含附件和意见,但是由于附件和意见的业务特殊性,需要单独进行管理,剩下的业务表单就可以看作文档了. 在一些流程审批业务中,业务信息有的是以Excel或word文件等方式专递,这样

java操作MongoDB数据库

1.如何启动MongoDB数据库? 如图所示:安装好MongoDB之后,文件夹显示如下: MongoDB默认开启27017端口,打开浏览器,输入http://localhost:27017/,显示如下: 启动数据库步骤: (1)cd d:\beiyongkaifa\mongodb\bin (2)输入:mongod --dbpath=D:\beiyongkaifa\mongodb\db,回车.如图1所示: (3)启动另一个cmd,cd d:\beiyongkaifa\mongodb\bin (4)