xiafu 2019-06-25
本文章首发于我的博客 基于 Eleasticsearch 和 Kibana 的运营数据可视化后台,转载请注明来源。
前一段时间在研究 ELK 这个东西,之前也用过一点,但都没有深入研究,其实这回也没有深入研究,但我找到了在现在情况下我该怎么用这个东西的方法。
ELK 是一个日志系统的全家桶工具,Elasticsearch 用的人比较多,很多人把这个当作搜索后台,如果你选择了 Django 这样的框架的话也很容易继承搜索功能进去,比如用这个库 django-haystack,当然很多人是用来做日志存储。
L 是 Logstash,经过我的调研就发现这个玩意其实不太好用,性能差是主要原因。这个东西的用途就是一个中间件,把多个平台的不同格式的日志全部进行预处理,然后再存入 ES 中,但是作为一个还很小,没那么复杂的后台服务来说,用不着,只有一个日志来源,日志格式也是固定的,一条日志里面有四个 JSON object,每个 object 的 key 不是固定的,只要处理一下时间戳就行了,其他都不用动,直接 mapping 到 ES 中,刚开始我甚至还用到了 filebeat,先用 filebeat 监控文件,然后 filebeat output 给 logstash,然后 logstash 再 output 给 ES,简直了,测试的时候没什么问题,但一上线过了两三天日志数量多了起来我就发现问题了,数量不对,每天都在累加前一天的日志条数,等于说是 tail 文件没成功,每次都从头开始读文件了,外加用了 rsync 这个东西从生产服务器上同步日志到 ES 机器上,我也没整明白到底是哪里出了问题,索性直接弃用 logstash 和 filebeat,只用 ES 和 kibana,我自己写脚本监控文件、把日志写入 ES 中,也把日志按天切分成文件,简单又靠谱。
运营数据日志的日志内容其实和消息系统很像,我就直接引用这里的概念 AVOT,Actor/Verb/Object/Target
。举例说明: xxx 关注了 yyy
,xxx
是 Actor,关注
是 Verb,yyy
是 Target,这里没有 Object,再举一个例子,xxx 将 uuu 添加到了 yyy 中,这里的 Verb 是 添加
,Object 是 uuu
,Actor/Object/Target
就是模型,当然我们不用把模型的全部字段都放进去,放个 type/id/name 就够了。按照这样的规则规定好日志内容之后就简单了,在每个需要记录日志的地方进行埋点,这个就是比较麻烦的地方,如果业务比较复杂的化,埋点很多,写的时候一定要一次性写对 Object 和 Target,不要写了一次之后复制粘贴,很容易搞错,一个个写。还有一点就是 Actor/Object/Target
的 id 都转成字符串存储,因为用户的 id 是 uuid
,日志 object 直接 to_json()
,django logger 直接用,用户 id 会变成字符串,其他 model 的 id 还是 int
,类型如果不一致再存到 ES 里面数据会有冲突。
最终的日志格式示例:
{"target": {"type": "Paper", "title": "Deep Depth Super-Resolution : Learning Depth Super-Resolution using Deep Convolutional Neural Network", "id": "791", "owner": "MKFMIKU"}, "object": {}, "actor": {"agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36", "accept_language": "en-US,en;q=0.8", "username": "qhl722", "host": "zijin.paperweekly.site", "referer": "http://www.paperweekly.site/getting-started"}, "verb": "点赞", "time": 1507000406.305043} {"target": {"type": "User", "id": "fcc3837f-1a61-4d2c-bdbf-0961085547a3", "owner": "gg5d"}, "object": {}, "actor": {"agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", "accept_language": "zh-CN,zh;q=0.8", "username": "", "host": "zijin.paperweekly.site", "referer": "http://www.paperweekly.site/"}, "verb": "注册", "time": 1507000688.429523}
我用了 Elasticsearch 的官方 Python API elasticsearch-py,脚本放在了 Gist 里面。
日志存到 ES 中是这个样子:
Kibana 是一个可是化工具,能看到 ES 中的数据,做一些报表,只要把数据导入到 ES 中,做报表就很简单了,简单的也是有前提的,前提是你要定义好日志的内容。
比如点赞数量,在 Visualize 里面新建一个柱状图,搜索 item.verb="点赞"
,然后第一个 Y 轴聚合搜索出来的日志条数,就是点赞的数量,再添加一个 Y 轴 Unique Count
item.actor.username.keyword
就能得出多少个用户产生了这么多赞,X 轴就是按照时间,我都是按天来,选择 Date Histogram
,Interval
选 Daily
,如果你的日志系统要求的实时性比较高,还能选择 Hourly
,然后把实时刷新打开,就能看到比较实时的数据了。
Kibana 最终是这个样子:
过几天我把这个东西拆分出来变成一个仓库再详细写一下教程。