MongoDB中的日志系统

本文是一篇源码导读类文章,主要是写给MongoDB的开发者看的,首先会简单介绍一下MongoDB的日志系统的组成,然后会再介绍一下如何使用。

日志系统组成

首先介绍一下日志系统的几个基本组件和概念。

Encoder

Encoder类负责对日志格式化,在不同的场景可能需要不同格式的日志,比如输出到console和文件可以使用一种格式,输出到syslog用另一种格式,还有些时候是不需要特定格式,直接输出raw信息即可。那么只要定义一个特定格式的派生类,实现对应的encode()接口即可。MongoDB目前定义了以下3种Encoder分别用于console/文件、syslog和raw:

  • MessageEventDetailsEncoder
  • MessageEventWithContextEncoder
  • MessageEventUnadornedEncoder

Appender

和其他日志系统一样,Appender就是日志输出到什么地方,常见的有Console、File、syslog等。作为一个服务,日志切割是普遍需求,为此MongoDB实现了一个RotatableFileAppender结合RotatableFileWriter和RotatableFileManager来实现这个功能。
每个Appender类有一个append()接口,所有派生类都需要实现这个接口。Appender类在构造时需要指定一个Encoder,append()的时候调用Encoder的encode()接口对日志进行格式化,然后再输出。MongoDB目前定义了以下几种Appender分别用于console、File和syslog输出:

  • ConsoleAppender
  • RotatableFileAppender
  • SyslogAppender

LogDomain

LogDomain可以理解为用来对日志按照业务类型进行分类(Domain)。这里业务类型是一个抽象的说法,具体可以是普通的程序日志、或是一些特殊模块的日志。MongoDB中有一个全局的LogDomain用于普通的日志输出,另外还有一个专门用于JavaScript输出。每个LogDomain管理了一组Appender,因此可以实现比较灵活的配置,比如系统日志可以输出到一个文件,JavsScript相关的日志可以输出到console或是另一个文件。除Appender的管理方法(attachAppender()、detachAppender()、clearAppenders())外,LogDomain也提供一个append()方法,调用后就是遍历其包含的Appender依次调用append()方法。

LogManager

LogDomain的管理者,包含一个全局的LogDomain以及一个LogDomain map,可以根据LogDomain的名字获取到对应的LogDomain。

LogComponent

标识日志是哪个组件产生的,是一个枚举值,有

  • kDefault
  • kControl
  • kCommand
  • ...

如果没有明确的所属组件,那么使用kDefault这个默认组件。

LogSeverity

日志级别,按照严重程度包含以下级别:

  • Severe
  • Error
  • Warning
  • Info
  • Log
  • Debug(1)
  • Debug(2)

各级别有一个对应的整型值,从小到大依次对应-4到2。当一个log调用时使用的日志级别对应的整型值大于当前配置的日志级别的整型值时,这个log才会被记录。可以在YAML配置文件中使用systemLog.verbosity来配置日志级别,注意这个配置只能配置非负值,即0、1、2分别对应Log、Debug(1)和Debug(2)。因此,值为负数的日志,即Info级别以上的的日志是一定会被记录的。另外,MongoDB可以支持不同的LogComponent使用不同的LogSeverity,比如可以配置systemLog.component.control.verbosity等。

LogstreamBuilder

根据提供的LogDomain、的LogSeverity和LogComponent等封装一个日志流,包含一个std::ostringstream。它重载了『<<』操作符,将日志内容输入到std::ostringstream中去,因此可以直接按照std::ostringstream的使用方式去使用。在LogstreamBuilder析构时会调用LogDomain的append()方法将日志输出到Appender中。

如何使用

MongoDB启动时在GlobalLogManager这个全局初始化函数中实例化了全局的LogManager单例,其中包含了ComponentMessageLogDomain这个全局的LogDomain。因此我们只只需要在需要记log的地方构造LogstreamBuilder,再传入日志内容就可以了。

在util/log.h中定义了以下函数直接构造一个对应的LogstreamBuilder(使用全局的LogDomain和MONGO_LOG_DEFAULT_COMPONENT):

  • severe()
  • error()
  • warning()
  • log()

此外,还定义了以下一系列LOG宏来根据传入的DLEVEL值是否大于组件配置的日志级别的值来判断是否需要记录log:

  • LOG
  • MONGO_LOG(DLEVEL)
  • MONGO_LOG_COMPONENT(DLEVEL, COMPONENT1)
  • MONGO_LOG_COMPONENT2(DLEVEL, COMPONENT1, COMPONENT2)
  • MONGO_LOG_COMPONENT3(DLEVEL, COMPONENT1, COMPONENT2, COMPONENT3)

这种方式可以指定DLEVEL,因此更加灵活。

综上,MongoDB日志系统的使用非常简单,只需:

  1. 在cpp文件中include util/log.h头文件,注意不可include多次
  2. 在当前cpp文件中定义一个MONGO_LOG_DEFAULT_COMPONENT宏
  3. 使用预定义的几个函数或LOG系列宏来进行log调用
时间: 2024-09-20 15:14:00

MongoDB中的日志系统的相关文章

日志系统中多线程写文件的问题

问题描述 大家好,我现在在写一个日志系统,因为我需要在另外的项目中使用这个日志系统,在项目中调用日志系统的输出日志功能时,需要把日志写到一个文件里面,因为项目中可能启动几十上百个线程,这样的话,就会出现很多线程都是向同一个文件里面写日志,考虑的性能和资源的前提下,有没有一个好的方案解决多个线程写文件的问题.在下考虑到的方法有:1,每次每个线程读写文件的时候,打开输入流,写完了以后关闭输出流.这样做的话每次都要打开关闭输出流,会不会很耗资源2,程序中使用一个集合保存需要写文件的输出流,当哪个线程需

Node.js和MongoDB实现简单日志分析系统

  Node.js和MongoDB实现简单日志分析系统  这篇文章主要介绍了Node.js和MongoDB实现简单日志分析系统,本文给出了服务器端.客户端.图表生成.Shell自动执行等功能的实现代码,需要的朋友可以参考下     在最近的项目中,为了便于分析把项目的日志都存成了JSON格式.之前日志直接存在了文件中,而MongoDB适时闯入了我的视线,于是就把log存进了MongoDB中.log只存起来是没有意义的,最关键的是要从日志中发现业务的趋势.系统的性能漏洞等.之前有一个用Java写的

Node.js和MongoDB实现简单日志分析系统_node.js

在最近的项目中,为了便于分析把项目的日志都存成了JSON格式.之前日志直接存在了文件中,而MongoDB适时闯入了我的视线,于是就把log存进了MongoDB中.log只存起来是没有意义的,最关键的是要从日志中发现业务的趋势.系统的性能漏洞等.之前有一个用Java写的分析模块,运行在Tomcat下.实现相当的重量级,添加一个新指标的流程也比较繁琐,而且由于NFS的原因还导致分析失败.一直想改写,最初想用Ruby On Rails,可是一直没有时间学习和开发(在找借口啊!).在杭州QCon 201

Windows Vista系统中的日志查看器功能介绍

当我们的Windows 系统出现问题时,要分析与定位故障,最简单的办法莫过于使用事件查看器,如Windows XP中的事件查看器可以让我们分析系统日志.应用程序日志与安全性日志,以从中找出可能存在问题的线索.不过,客观地说来,之前Windows版本包括Windows XP中的事件查看器在使用中存在很多不足,很多时候所给出的信息呆板.含糊,不足以让我们准确地定位可能发生的故障,而当待找的信息淹没在大量的事件之中时,简陋的事件过滤与查询机制往往让我们很难快速找到与定位. 在Windows Vista

MongoDB在呼叫中心系统中的应用

MongoDB在呼叫中心系统中的应用 席晓筱,詹舒波 MongoDB是一个可扩展,高性能,无模式,基于文档存储的非关系型数据管理系统.它的面向文档存储的特点使得MongoDB可以支持松散结构数据的存储:弱一致性特点使得MongoDB可以保证更快速的用户访问速度:高性能特点使得MongoDB可以更好的支持大数据量的处理.呼叫中心的不断发展对数据存储系统提出了新要求:大数据量+松散数据结构+高访问速度,因此引入非关系数据库MongoDB作为呼叫中心部分应用数据的存储系统十分合适.本文首先对Mongo

ELK统一日志系统的应用

收集和分析日志是应用开发中至关重要的一环,互联网大规模.分布式的特性决定了日志的源头越来越分散, 产生的速度越来越快,传统的手段和工具显得日益力不从心.在规模化场景下,grep.awk 无法快速发挥作用,我们需要一种高效.灵活的日志分析方式,可以给故障处理,问题定位提供更好的支持.基于全文搜索引擎 Lucene 构建的 ELKstack 平台,是目前比较流行的日志收集方解决方案. ELK系统的部署按照官方文档操作即可,相关资料也很多,这篇文章更多的关注三个组件的设计和实现,帮助大家了解这个流行的

日志系统之扩展Flume-LineDeserializer

继续闲聊日志系统,在之前的博文里已提到我们在日志收集上的选择是flume-ng.应用程序将日志打到各自的日志文件或指定的文件夹(日志文件按天滚动),然后利用flume的agent去日志文件中收集. Deserializer简介 flume将一条日志抽象成一个event.这里我们从日志文件中收集日志采用的是定制版的SpoolDirectorySource(我们对当日日志文件追加写入收集提供了支持).从日志源中将每条日志转换成event需要Deserializer(反序列化器).flume的每一个s

日志系统之Flume采集加morphline解析

概述 这段时间花了部分时间在处理消息总线跟日志的对接上.这里分享一下在日志采集和日志解析中遇到的一些问题和处理方案. 日志采集-flume logstash VS flume 首先谈谈我们在日志采集器上的选型.由于我们选择采用ElasticSearch作为日志的存储与搜索引擎.而基于ELK(ElasticSearch,Logstash,Kibana)的技术栈在日志系统方向又是如此流行,所以把Logstash列入考察对象也是顺理成章,Logstash在几大主流的日志收集器里算是后起之秀,被Elas

实时查询日志系统

最近作一模块 ,实时查询日志系统.其思路是:1:加载网页时,从数据库读x条记录,显示在页面中.2:设置刷新时间,动态的从数据库中读取记录,在客户端进行局部刷新.由于是局部刷新,所以就用到了ajax技术.具体做法是:1:从网站http://ajax.schwarz-interactive.de/csharpsample/default.aspx 下载ajax.dll动态连接库.2:配置web.config  <system.web>  <httpHandlers>  <add