1.日志系统概述
1.1应用程序日志的作用:
应用程序日志的作用:日志分析并不仅仅包括系统产生的错误日志,异常,同时也包括业务逻辑,或者任何文本类型的分析。而基于日志的分析,具有重要的现实意义,典型地,
- 问题排查
- 开发和运维需要快速的定位问题,甚至防微杜渐,把问题杀死在摇篮。日志分析技术显然问题排查的基石。基于日志进行问题排查,还有一个很帅的技术,叫全链路追踪。
- 监控和预警
日志,监控,预警是相辅相成的。基于日志的监控,预警使得运维有自己的机械战队,大大节省人力以及延长运维的寿命 - 关联事件
多个数据源产生的日志进行联动分析,通过某种分析算法,就能够解决生活中各个问题,病毒分析,金融欺诈等 - 数据分析
数据就是一个企业的重要财富,尤其对于数据分析师,算法工程师都是有所裨益的
1.2 集中式日志系统
在互联网时代,分布式应用程序是主流的架构,它能快简单地,快速地,便捷地提供服务的并发性,容灾性,可用性。但是这就带来若干问题,
- 应用程序的日志分散在不同的机器上,这些机器可能是物理机,可能是内网vm,也可能是公有云,分散性较大。
- 随着服务的持续运行,日志文件将变得越来越大。
- 如果服务器磁盘损坏,日志文件将丢失
由此可见,传统的日志记录方式不利于问题的定位,日志的搜索,日志的保存。我们需要寻找一种新的记录日志的手段,集中式日志系统应运而生
所谓集中式:即将所有相关日志收集,汇总到一起,并使之结构化,可搜索,可持久化存储。
业界著名的解决方案有:
- Splunk: 企业级的日志收集引擎
- ELK: elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写ElasticSearch、Logstash 和 Kibana
- Graylog: 开源的完整日志管理工具,功能和ELK类似,但比ELK简单。本文重点介绍
2.鸟瞰Graylog
2.1相关组件
- Elasticsearch: 日志内容的实际存储地,提供搜索等功能。部署es服务器的内存越大已经磁盘速度越高,es提供搜索的性能也就越高。
- MongoDB:用于存储基本的元信息以及配置信息,没有太高的硬件需求。
- Graylog:日志API的提供者,面向浏览器以及应用程序,cpu密集型任务。
2.2Graylog架构
2.2.1 极简的部署方案
上图展示的是Graylog极简的部署方案,没有任何冗余的组件,全都都是单点,不建议在生产环境使用,但是对于了解,测试graylog,这种方案以及足够了。
应用程序通过Graylog组件提供api,从而进行日志的传输,同时,Graylog还提供的界面友好的web系统,使得开发者可以查询,搜索日志,并提供诸如过滤,告警,图表等高级功能。
Graylog将日志进行一定的处理后,存入es中,而在MongoDB中存放在用户等配置信息。
2.2.2 生产环境的部署方案
我们使用es集群代替单几点的es,这将极大的提高数据的安全性,以及服务的性能,高可用性,另外我们将启用多个Graylog服务,并将其挂载在负载均衡(LB)的后面,LB不仅能分流,减轻单个节点的压力,同时具有健康检查的能力,定期的检查后端Graylog服务的健康情况,将异常节点剔除出集群。
2.3Graylog部署
Graylog官方提供了ubuntu,centos等主流os的安装包,大家可以根据实际情况予以安装,为了简单,高效,笔者这里提供Docker的部署方案,可供参考,在linux ,mac下通用。这里以ubuntu18系统为例说明
相关依赖:
(一)安装docker: apt-get install –y docker
(二)启动docker服务: sudo systemctl start docker
(三)设置docker命令免sudo: sudo groupaddß docker && sudo gpasswd -a ${USER} docker && newgrp – docker
(四)安装 docker-compose: docker编排工具,将相关的容器集中管理,如果系统安装的 python的装包工具pip可以直接执行
pip install docker-compose,或者 sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose
docker-compose 通过一个yaml文件来描述需要启动的容器信息。笔者已经准备好,执行如下命令:
mkdir TestGraylog && cd TestGraylog && git clone https://code.*****.com/users/graylog.git 修复配置文件中GRAYLOG_HTTP_EXTERNAL_URI配置项 ,将ip改为自己服务器的ip
接着键入: docker-compose up –d ,一键启动 graylog,es,mongodb服务,
通过docker-compose ps命令查看服务启动情况
第三列State 为UP 表明三个服务均正常启动
查看服务器9000端口是否处于listen状态
Graylog 将在此端口运行web界面服务,以及接受rest api请求。
在浏览器中输入:http://ip:9000 ,输入账号 admin/admin 将看到类似下图所示画面,说明Graylog服务启动正常
注意: docker-compose.yaml文件中默认开启9000/tcp, 12201/tcp 12201/udp等端口,注意防火墙的设置
3.如何搜集日志
如果Graylog中不能收集/存储日志数据,它将失去存在的意义,本节将说明如何将应用程序的日志发送到Graylog系统中。
3.1Graylog input
Graylog input ,它负责接收日志文件,我需要在web界面设置input ,在配置完成后及时生效,并不需要重启Graylog服务。
Input的种类很多,这里以GELF UDP类型予以说明
GELF是一种日志组织格式,后文具体说明;UDP表明应用程序通过UDP协议将日志发送给Graylog,虽然UDP意味着,不可靠的,不保序的,无连接的。但是在我们的日志系统中,UDP仍然具有优势。
- UDP没有要建立,维持,撤销连接的开销
- Graylog服务出现异常时,不影响自身应用
- 除了GELF格式,还可以选择文本格式,syslog等,除了UDP协议,还可以选择TCP,HTTP,AMQP,Kafka等当然这些应对应用程序透明。
- 接下来,配置一下input的具体内容
Bind address:键入部署Graylog服务所在的ip
Port: 键入需要监听的端口
注意Port一定要在docker-compose.yaml文件中配置,
点击save按钮,这样就完成了一个input的设置,这意味着:Graylog在12201端口接受通过UDP协议传输的GELF格式的日志消息
3.2GELF格式
传输给Graylog 系统的日志格式可以各种各样,限于篇幅的原因,我们选取其中广泛使用的GELF格式, The Graylog Extended Log Format(GELF) 这种格式克服了传统syslog文件的诸多缺点,
syslog限制单条日志文件的长度为1024bytes
syslog日志没有数据类型,你通常区分不了这是数字还是字符串
虽然 RFCs对syslog有严格的定义,但syslog的诸多实现并不完全遵守,这就导致我们的应用程序不可能解析所有的情况
Syslog没有压缩功能:当使用UDP作为传输协议时,GEFL消息能够使用GZIP OR ZLIB压缩,这有利于消息体积和快速传输,当然这会消耗一些cpu资源,不过这是值得的。
Syslog能够胜任记录系统或者网络设备的任务,显然GELF更适合记录应用程序产生的日志,Graylog 提供了多种语言的Lib,方便接入,你甚至通过Graylog发送异常日志,同时由于UDP协议,从而不用考虑超时,连接等问题导致自身应用的故障。
GELF格式其实是一个json字符串,包含下表所示的字段
字符名称 含义 类型 是否可选
version Graylog使用的版本 字符串 否
host 产生日志所在主机的名称 字符串 否
short_message 对一条消息的简短描述 字符串 否
full_message 消息的详尽描述 字符串 是
timestamp Unix时间戳 整数数字 否
level 日志消息的级别 整数 否
file 产生消息日志文件的路径 字符串 是
line 产生日志在源码文件中的行数 整数 是
_[additional field] 前缀为_的字段名称也会添加到Graylog中 任意 是
{
"version": "1.1",
"host": "example.org",
"short_message": "A short message that helps you identify what is going on",
"full_message": "A full message here\n\nmore stuff",
"timestamp": 1385053862,
"level": 1,
"_user_id": 9001,
"_some_info": "foo",
"_some_env_var": "bar"
}
下面使用netcat工具,向graylog发送一条日志文件
echo -n '{ "version": "1.1", "host": "******.com", "short_message": "******* is a Promising company", "level": 5, "_user_name”: "******",”_user_id”:7798 }' | nc -w0 -u 127.0.0.1 12201
然后打开web界面就可以看到格式化的日志了
3.3应用程序接入日志系统
上一节中我们通过netcat命令行工具,向graylog发送一条GELF格式的消息。这是我们需要手动构造,消息格式,指定udp协议(参数-u),指定ip和端口,多次发送日志文件时,显得繁琐。由于公司绝大部分业务都是使用python和golang开发,本节对此分别给出示例
3.3.1python
笔者在第三方的基础上自行封装一个python使用的lib,能够和python标准的logging库无缝对接,对应用程序的入侵极小
首先我们一定义一个log hander
我们指明graylog handler的类(这个笔者已经放到公司python的公用仓库中),同时指定graylog的ip以及监听端口,协议类型。
具体打日志时,
debug表明日志的等级,第一个参数是message字段的内容,extra参数中的字段是额外的信息,便于搜索,后文有例子说明。
Demo使用方式:
下载代码 git clone git@code.******.com:users/demo_for_graylog.git
cd python && pip install -r requirements.txt
python main.py
3.3.2 golang
直接使用官方提供的 graylog-golang lib
Demo 使用方式:
下载代码 git clone git@code.******.com:users/demo_for_graylog.git
cd golang && go build
./graylog
查看效果
有此图可知,UDP的确不保序,但对于日志系统通常没有什么影响。
4 强大而简单的搜索语法
如前文,现在日志已经成功录入Graylog系统中,这并没有什么了不起的,mysql, mongo都能做。Graylog最令人心动是,简单而强大的搜索功能。
在web系统的主页,我们可以选择搜索的时间范围,比如最近5分钟,2小时前,当前你也可以精确的指定事件范围,注意默认是 UTC的时间,选择时间范围将减少搜到范围,提高搜索的速度,所以请尽可能的不要全局搜索。
第二个框,我们可以指定搜索的条件,总结起来有如下几条规则,
a)默认搜索所有的消息字段,如果不显式指定搜索字段名称: 当我们键入this 关键字时,将返回所选时间范围内,所有消息字段中包含 this的日志
b)当多个关键字用空格分开时,表示or的语义:键入 this message 返回所有消息字段包含 this 或者message的日志
c)当需要精确匹配时,加上引号: 键入”this message” 返回消息字段中包含this message的日志
d)指定消息的字段,减少搜索范围:键入 user_id:7789 返回消息中包含user_id字段且值为7789的日志,键入user_id:(7789 OR 7798):返回user_id为7789 或者7798 的日志,注意 OR需要大写
e)多个搜索条件之间支持逻辑操作 AND NOT OR, 例如:level:<=3 AND user_id:12
f)支持wildcard语法的模糊查找,键入req_path:api 返回包含req_path字段 且值包含api字符串
更多的搜索语法参见官方文档