Fluentd —— :Python + MongoDB

<source>
  type tcp
  port 24224
</source>

  

Fluentd在Python Application中的应用,将Python程序在运行时输出的log输入到Fluentd,并最终持久化到MongoDB中。

把Python程序的log输出到Fluentd中很简单,Fluentd已经为你写好了lib——fluent-logger-python。从Fluentd中把数据存到MongoDB也不是很困难,因为我们安装的是稳定版本的Fluentd——td-agent,其已经自带了把数据从Fluentd输出到MongoDB的输出插件——out_mongo,我们要做的就是简单做一些简单的配置。

在动手操作之前,我们还需要明白一些事情,就是通过Fluentd,把log保存到MongoDB中相比直接在程序中输出到MongoDB,有哪些好处?

一般一个程序会频繁地大量地输出log,如果直接将log写到MongoDB中,可能会引起性能问题的是数据库的锁。虽然MongoDB的锁(更多参见官方文档)比较轻量级,甚至有人提出了叫它“栓”更合适,但是频繁的insert也会引起资源竞争,并排斥其他读操作。而使用Fluentd等日志收集框架,它们会将logs缓存,并异步地以bulk inserts的方式写入MongoDB,比直接写入高效很多,而且对程序的性能影响很低。而且就Fluentd来说,它的数据记录是JSON形式,与MongoDB的数据格式BSON融合搭配非常完美,因此用Fluentd来收集并写入MongoDB是较为理想的解决方案。

架构图如下:

准备工作

安装fluent-logger-python

$ sudo pip install fluent-logger

  

为Fluentd配置输入插件

要求Fluentd的输入插件必须做出如下配置:


为Fluentd配置输出插件

一个样例的输出插件配置如下:

<match mongo.*>
    # plugin type, must be mongo
    type mongo
    # mongodb host + port
    host 127.0.0.1
    port 27017
    # mongodb db + collection
    database grlog
    collection log
    # for capped collection
    capped
    capped_size 1024m
    # authentication
    user liushuaikobe
    password secret
    # flush interval
    flush_interval 10s
</match>

几个点说一下,其他的不言而喻。

capped

即MongoDB固定大小的集合(Capped Collections)。非常适合用来存储log信息。如果你不知道,建议先去学学基础的MongoDB的知识。

flush_interval

这个参数指定了多长时间数据被写入MongoDB一次。默认是60s。支持“s”(seconds),“m”(minutes),“h”(hours) 后缀。

collection

这个参数指定了数据存入MongoDB的哪个集合。这个参数是必须的,除非设置了tag_mapped

tag_mapped告诉Fluentd根据数据记录的tag信息把数据记录放入不同的MongoDB集合。

例如:

<match mongo.*>
    ...
    # Set 'tag_mapped' if you want to use tag mapped mode.
    tag_mapped
    # If the tag is "mongo.foo", then the prefix "mongo." is removed.
    # The inserted collection name is "foo".
    remove_tag_prefix mongo.
    ...
</match>
更多高级的配置

还有很多更具体的配置,比如buffer相关等,数据写入MongoDB时使用的线程数等,详情查看这里。

重启td-agent

$ sudo service td-agent restart

代码编写

接下来就是实际编写代码了,也非常简单。

from fluent import sender
from fluent import event
sender.setup('app', host='127.0.0.1', port=24224)
event.Event('follow', {
    'msg_1': 'msg 1',
    'msg_2': 'msg 2'
})

上面的代码就将一条数据记录(被称为event)发给了Fluentd,剩下的就是Fluentd根据你的配置把这些信息写入MongoDB了。

当然,在实际的项目中,可以采取一些灵活的手段。比如,可以根据上面所述的tag_mapped将不同LEVEL的log输出到不同的集合中。

附上我的代码,仅供参考,如有错误,恳请指正。

import loggingfrom fluent import senderfrom fluent import eventimport config__author__ = 'liushuai'DEBUG = logging.DEBUGINFO = logging.INFOWARNING = logging.WARNINGERROR = logging.ERRORCRITICAL = logging.CRITICAL_level_tag_name = {    DEBUG: "debug",    INFO: "info",    WARNING: "warning",    ERROR: "error",    CRITICAL: "critical"}sender.setup(config.FLUENTD_TAG, host=config.FLUENTD_HOST, port=config.FLUENTD_PORT)def log(level, msg):    event.Event(_level_tag_name.get(level, "unknown"), {        "msg": msg,        "level": _level_tag_name.get(level, "unknown")    })

单元测试:

from unittest import TestCaseimport log__author__ = 'liushuai'class TestLog(TestCase):    def test_log(self):        msg = "This log is just for testing."        for _ in range(100):            log.log(log.CRITICAL, msg)            log.log(log.ERROR, msg)            log.log(log.WARNING, msg)            log.log(log.INFO, msg)            log.log(log.DEBUG, msg)

可以见到log已经被成功写入了MongoDB(可能会有一些延迟):

后记

以上就是我使用Fluentd + Python + MongoDB进行项目log信息的集中处理的探索全过程,希望对你有帮助。如有错误,恳请留言指正。

写在前面

本文主要介绍Fluentd在Python Application中的应用,将Python程序在运行时输出的log输入到Fluentd,并最终持久化到MongoDB中。

posted @ 2016-11-21 11:39  众里寻,阑珊处  阅读(1204)  评论(0编辑  收藏  举报
返回顶部