首页 > 技术文章 > 使用MongoDB 记录业务日志

autohome7390 原文

      最近公司有个需求,要对业务日志进行记录并根据日志排查问题,以前都是使用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 
53         /// <summary>
54         /// 从MongoDb 获取数据
55         /// </summary>
56         /// <returns></returns>
57         static List<LogBase<InsuranceLog>> GetList()
58         {
59             try
60             {
61                 var client = new MongoClient("mongodb://192.168.21.129:27017");
62                 var database = client.GetDatabase("logs");
63                 var collection = database.GetCollection<LogBase<InsuranceLog>>("InsuranceLog");
64                 var b = (from x in collection.AsQueryable()
65                          where x.CallTime.StartsWith("201604281414")
66                          && x.CallTime.EndsWith("000")
67                          select x).ToList();
68                 return b;
69             }
70             catch (Exception ex)
71             {
72                 throw;
73             }
74         }
75 
76 
77         /// <summary>
78         /// 插入单条数据
79         /// </summary>
80         /// <typeparam name="T"></typeparam>
81         /// <param name="t"></param>
82         /// <param name="name"></param>
83         static async Task InsertOneLogToMongoDbAsync<T>(T t, string name)
84         {
85             try
86             {
87                 var client = new MongoClient("mongodb://192.168.21.129:27017");
88                 var database = client.GetDatabase("logs");
89                 var collection = database.GetCollection<T>(name);
90                 await collection.InsertOneAsync(t);
91             }
92             catch (Exception ex)
93             {
94                 throw;
95             }
96         }

主要测试点在查询上,要根据条件快速检索出需要的数据,我测试了一下,单条数据大概是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 = "1";
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     }
View Code

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

 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     }
View Code

未完待续

推荐阅读