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中。