最近公司有个需求,要对业务日志进行记录并根据日志排查问题,以前都是使用log4net之类的日志组件来记录到文件,这种方式已经不能满足业务的需要,因为日志文件会很大,即使进行分割后,查找也是很不方便,何况现在项目基本都是分布式,会有多台应用服务器,那么就需要把多台服务器上的日志弄到一起,十分的麻烦,经过选择后ELK进入视线,测试环境也搭建了一套,现在唯一的问题就是怎么把多台服务器上的日子泵出到elstaticsearch中,我们的应用服务器都是windows,所以需要在每一台应用服务器上安装一个服务,如:NXlog之类的,经过考虑觉得这种方式太麻烦,所以决定把日志先记录到MongoDb,先实现简单的日志查询,再统一从MongoDb将数据泵出到elstaticsearch中,思路有了,开始动手测试。

第一步,插入测试数据,MongoDb数据库我是安装在本地一个linux虚拟机里,插入1000000条数据耗时8分钟,有兴趣的童鞋自己测试一下,用来存储日志完全没有问题,废话不多说了,上代码:

  1. static void Main(string[] args)
  2. {
  3. try
  4. {
  5. #region 插入测试数据
  6. //var sw = new Stopwatch();
  7. //sw.Start();
  8. //string tableName = "InsuranceLog";
  9. //for (var i = 0; i < 1000000; i++)
  10. //{
  11. // var lb = new LogBase<InsuranceLog>()
  12. // {
  13. // Message = new InsuranceLog
  14. // {
  15. // BusinessKey = i.ToString(),
  16. // BusinessName = "政策查询" + i,
  17. // BusinessParameters = "根据实际需要组织<xml><OrderId>AutoHome" + i + "</OrderId></xml>"
  18. // }
  19. // };
  20.  
  21. // InsertOneLogToMongoDbAsync(lb, tableName);
  22. //}
  23. //sw.Stop();
  24. //Console.WriteLine("插入100000条数据耗时:" + sw.ElapsedMilliseconds + "ms");
  25. #endregion
  26.  
  27. #region 根据条件从1000000条数据中获取指定数据
  28. var sw = new Stopwatch();
  29. sw.Start();
  30. var obj = GetList();
  31. sw.Stop();
  32. Console.WriteLine("从100000条数据获取指定数据耗时:" + sw.ElapsedMilliseconds + "ms");
  33. foreach (var o in obj)
  34. {
  35. if (o.Message != null)
  36. {
  37. Console.WriteLine("调用时间:"+o.CallTime);
  38. Console.WriteLine("业务key:" + o.Message.BusinessKey);
  39. Console.WriteLine("业务名称:" + o.Message.BusinessName);
  40. Console.WriteLine("业务参数:" + o.Message.BusinessParameters);
  41. }
  42. }
  43. #endregion
  44. Console.ReadKey();
  45. }
  46. catch (Exception ex)
  47. {
  48. throw;
  49. }
  50. }
  51.  
  52. /// <summary>
  53. /// 从MongoDb 获取数据
  54. /// </summary>
  55. /// <returns></returns>
  56. static List<LogBase<InsuranceLog>> GetList()
  57. {
  58. try
  59. {
  60. var client = new MongoClient("mongodb://192.168.21.129:27017");
  61. var database = client.GetDatabase("logs");
  62. var collection = database.GetCollection<LogBase<InsuranceLog>>("InsuranceLog");
  63. var b = (from x in collection.AsQueryable()
  64. where x.CallTime.StartsWith("")
  65. && x.CallTime.EndsWith("")
  66. select x).ToList();
  67. return b;
  68. }
  69. catch (Exception ex)
  70. {
  71. throw;
  72. }
  73. }
  74.  
  75. /// <summary>
  76. /// 插入单条数据
  77. /// </summary>
  78. /// <typeparam name="T"></typeparam>
  79. /// <param name="t"></param>
  80. /// <param name="name"></param>
  81. static async Task InsertOneLogToMongoDbAsync<T>(T t, string name)
  82. {
  83. try
  84. {
  85. var client = new MongoClient("mongodb://192.168.21.129:27017");
  86. var database = client.GetDatabase("logs");
  87. var collection = database.GetCollection<T>(name);
  88. await collection.InsertOneAsync(t);
  89. }
  90. catch (Exception ex)
  91. {
  92. throw;
  93. }
  94. }

主要测试点在查询上,要根据条件快速检索出需要的数据,我测试了一下,单条数据大概是800ms左右,我的查询条件取出来38条数据,耗时842ms,

重点:日志基类,扩展性很好,支持自定义实体类

  1. /// <summary>
  2. /// 日志基类
  3. /// </summary>
  4. [BsonIgnoreExtraElements]
  5. public class LogBase<T>
  6. {
  7. public LogBase()
  8. {
  9. CallTime = DateTime.Now.ToString("yyyyMMddHHmmssfff");
  10. SerialNo = Guid.NewGuid().ToString("N");
  11. ClientType = "";
  12. Message = default(T);
  13. var myEntry = Dns.GetHostEntry(Dns.GetHostName());
  14. var address = myEntry.AddressList.FirstOrDefault(e => e.AddressFamily.ToString().Equals("InterNetwork"));
  15. if (address == null) return;
  16. var ip = address.ToString();
  17. HostIp = ip;
  18. }
  19.  
  20. /// <summary>
  21. /// 调用时间,格式:yyyyMMddHH24mmss
  22. /// </summary>
  23. public string CallTime { get; private set; }
  24.  
  25. /// <summary>
  26. /// 消息序列号 UUID
  27. /// </summary>
  28. public string SerialNo { get; private set; }
  29.  
  30. /// <summary>
  31. /// 客户端IP地址
  32. /// </summary>
  33. public string HostIp { get; private set; }
  34.  
  35. /// <summary>
  36. /// 客户端类型:1:pc 2:手机
  37. /// </summary>
  38. public string ClientType { get; private set; }
  39.  
  40. /// <summary>
  41. /// 业务信息
  42. /// </summary>
  43. public T Message { get; set; }
  44.  
  45. }

测试程序用到的自定义日志类:

  1. public class InsuranceLog
  2. {
  3. /// <summary>
  4. /// 当前登录用户
  5. /// </summary>
  6. public string UserName { get; set; }
  7.  
  8. /// <summary>
  9. /// 业务key
  10. /// </summary>
  11. public string BusinessKey { get; set; }
  12.  
  13. /// <summary>
  14. /// 业务名称 如:查询政策 下订单 查看订单
  15. /// </summary>
  16. public string BusinessName { get; set; }
  17.  
  18. /// <summary>
  19. /// 业务参数
  20. /// </summary>
  21. public string BusinessParameters { get; set; }
  22. }

未完待续

使用MongoDB 记录业务日志的更多相关文章

  1. 使用NLog记录业务日志到数据库

    项目中很多时候要记录业务日志,其实是可以直接用日志框架计入数据库的. 使用NLog并不是只能将日志主体插入数据库,而是可以根据实际情况自定义任意列记入.非常方便.而且很容易实现 下面是用NLog记录业 ...

  2. spring集成mongodb通过aop记录业务日志

    1. 编辑 pom.xml 添加 maven 依赖 <!-- mongodb --> <dependency> <groupId>org.mongodb</g ...

  3. aop 例外通知就是记录业务方法出现错误 并保存到日志里面的功能

    aop 例外通知就是记录业务方法出现错误 并保存到日志里面的功能

  4. 十:SpringBoot-配置AOP切面编程,解决日志记录业务

    SpringBoot-配置AOP切面编程,解决日志记录业务 1.AOP切面编程 1.1 AOP编程特点 1.2 AOP中术语和图解 2.SpringBoot整合AOP 2.1 核心依赖 2.2 编写日 ...

  5. ASP.NET记录错误日志的方式

    程序记录错误日志是一种看起来对一般用户没什么作用,但对程序开发者用处很大的东西,它能查出错误或异常的程序马迹.那么,常用的记录错误日志的方式有哪些呢? 大多数情况下使用的是 1.直接记录为txt/xm ...

  6. Appfuse:记录操作日志

    appfuse的数据维护操作都发生在***form页面,与之对应的是***FormController,在Controller中处理数据的操作是onSubmit方法,既然所有的操作都通过onSubmi ...

  7. MongoDB实战指南(四):MongoDB的Journaling日志功能

    mongoDB的Journaling日志功能与常见的log日志是不一样的,mongoDB也有log日志,它只是简单记录了数据库在服务器上的启动信息.慢查询记录.数据库异常信息.客户端与数据库服务器连接 ...

  8. 采用Spring AOP+Log4j记录项目日志

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6567672.html 项目日志记录是项目开发.运营必不可少的内容,有了它可以对系统有整体的把控,出现任何问题 ...

  9. Spring AOP+Log4j记录项目日志

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6567672.html 项目日志记录是项目开发.运营必不可少的内容,有了它可以对系统有整体的把控,出现任何问题 ...

随机推荐

  1. -------------》》》【Vim】vim的一些简单配置~

    在linux下使用   :vsp ~/.vimrc   来打开配置文件 一些命令[任何命令前加上   !    强制执行]: :w     保存 :wq    保存退出 :q     退出 ctrl ...

  2. [LOJ6278]数列分块入门 2

    题目大意: 给你一个长度为$n(n\leq 50000)$的序列$A$,支持进行以下两种操作: 1.将区间$[l,r]$中所有数加上$c$: 2.询问区间$[l,r]$中小于$c^2$的数的个数.思路 ...

  3. iOS 自定义字体设置

    有时候客户都要求使用方正兰亭刊黑字体,可是iOS没有自带这个字体,肿么办 ,只能自己自定义字体了,下面是自定义字体的几个重要步骤: 1.下载字体资源文件(.ttf或.otf格式的文件) 比如说你要使用 ...

  4. 检索COM 类工厂中CLSID 为{00024500-0000-0000-C000-000000000046}组件时失败

    检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005 当在ASP.NET应用程序中引 ...

  5. 小程序 wx:for 循环嵌套

    json数据: [//library-6F    [//library-6F-601      [//id:1-1 ,8(Y/N),9(Y/N)……21(Y/N)        'Y','Y','Y' ...

  6. mysql行转列,单列转多行

    行转列 使用CASE语句: SELECT SUM(CASE USER_NAME='A' THEN KILLS END) AS 'A', SUM(CASE USERNAME='B' THEN KILL ...

  7. Unable to list target platforms. Please make sure the android sdk path is correct. See the Console for more details.

    在android上发布遇到 androidSDK无法找到的问题 http://www.jianshu.com/p/fe4c334ee9fe

  8. Python 面向对象三(转载)

    来源:Mr.Seven www.cnblogs.com/wupeiqi/p/4766801.html 四.类的特殊成员 上文介绍了Python的类成员以及成员修饰符,从而了解到类中有字段.方法和属性三 ...

  9. ElasticSearch的内存设置

    编辑ElasticSearch中bin目录下 vi elasticsearch中 加上   export ES_HEAP_SIZE=24g 修改配置文件 config/elasticsearch.ya ...

  10. How to dynamically load directive into page

    https://stackoverflow.com/questions/23556398/how-to-dynamically-load-directive-into-page I have an h ...