logstash+logback收集spring boot日志

    项目上线都已经有一段了时间,新的功能在不断上,bug也随着时间慢慢浮现。令人差异的是,每次出现bug都是用户发现的,虽然开发迭代的版主里,一直都没有测试跟着我们走,但是让用户去发现bug实在有点说不过了。在项目初期我用backlog做了info,error文件切分,但是每次看日志都是要用head | more这些命令去看,而且效率也很慢。没这么多时间天天去看error.log。业界做日志处理都是用elk,自己从零开始琢磨到构建完成,一点点心得分享出来,也当作一次学习笔记。

   Logstash介绍


Logstash 是开源的服务器端数据处理管道,能够同时 从多个来源采集数据、转换数据,然后将数据发送到您最喜欢的 “存储库” 中。

图片的上部分可以理解为:logstash各种输入源input ,可以从日志文件追加的形式,就像linux tail -f 命令将日志添加进来,或者开启tcp端口,监听文件传输(我就是用这种方法收集),udp方法等等,这些都是基于插件完成的。中间圆形的就是logstash的核心,也是功能最强大的地方filter,可以将日志进行切分,过滤,类型转换。下面想想都知道是输出output,把处理好日志放到elasticsearch,或者redis,mongodb等等都是可以的。

   安装启动Logstash

在下载之前请确认电脑是否安装了java,logstash5.0之后的版本好像都需要1.8以上的支持,没有的话,最好装一个jdk1.8。下载地址 点击logstash选择相应的版本即可,下载完成后解压文件后,使用cmd进入解压的目录/bin


测试是否安装成功  logstash -e 'input { stdin { } } output { stdout {} }'

如果看见下面信息 9600端口启动了,说明logstash启动成功,网上有些教程是:logstash -e  'input { stdin { } } output { stdout { codec => rubydebug } }'在我的电脑上没有用,这个命令在高版本没用

springboot logback配合

要使用logback一个插件来将数据转成json,引入maven配置

<dependency>

      <groupId>net.logstash.logback</groupId>

      <artifactId>logstash-logback-encoder</artifactId>

     <version>4.10</version>

</dependency>


在springboot的resource创建logback.xml文件

<xml version="1.0" encoding="UTF-8"?>

    <configuration scan="true" scanPeriod="60 seconds" debug="true">

         <contextName>logstash-test</contextName>

   <!-- 这个是控制台日志输出格式 方便调试对比--->

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">

      <encoder>

          <pattern>%d{yyyy-MM-dd HH:mm:ss} %contextName %-5level %logger{50} -%msg%n</pattern>

   </encoder>

</appender>

<appender name="stash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">

  <destination>localhost:8888</destination> 这是是logstash服务器地址 端口

  <encoder class="net.logstash.logback.encoder.LogstashEncoder" /> 输出的格式,推荐使用这个

</appender>

<root level="info">

   <appender-ref ref="console"/>

   <appender-ref ref="stash"/>

</root>

启动项目,就会请求localhost:8888,如果有监听,就会自动发送日志。

logstash配置

input {

             tcp {

                        host => "localhost" #这个一定要是logstash本机ip,不然logstash 无法启动,也可以去除

                        port => 8888

                       codec => json_lines

                       mode => "server"

                  }

}

filter {

                 grok {

               match => {

"message" => "%{URIPATH:request} %{IP:clientip} %{NUMBER:response:int} \"%{WORD:sources}\" (?:%{URI:referrer}|-) \[%{GREEDYDATA:agent}\] \{%{GREEDYDATA:params}\}"

     }

}

geoip { #利用geoLite数据库,将ip转成经纬度

            source => ["clientip"]

           database => "E:/java_software/logstash-5.4.0/config/GeoLite2-City.mmdb" }

           mutate { remove_field => ["port","@version","level_value"]

      }

}

output {

       stdout { codec => rubydebug } #标准输出,在命令行中输出方便调试

elasticsearch { hosts => [ "localhost:9200" ]

index => "pybbs"

document_type => "weblog"

    }

}

大家看见这个配置文件都是一头雾水吧!主要重点在于filter grok。Grok是将非结构化日志数据解析为结构化和可查询的好方法。

这个工具非常适合syslog日志,apache和其他web服务器日志,mysql日志,以及通常为人类而不是计算机消耗的任何日志格式。

默认情况下,Logstash附带约120个模式。你可以在这里找到它们:https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns

Grok通过将文本模式组合成与日志匹配的东西来工作。

grok模式的语法是%{SYNTAX:SEMANTIC}

这SYNTAX是与您的文字相匹配的图案的名称。例如,3.44将被匹配的NUMBER模式,55.3.244.1并将被匹配的IP模式。语法是你如何匹配。

这SEMANTIC是你给正在匹配的文本的标识符。例如,3.44可能是一个事件的持续时间,所以你可以简单地调用它duration。此外,一个字符串55.3.244.1可能会识别client发出请求。

对于上面的例子,你的Grok过滤器看起来像这样:

%{NUMBER:response}%{IP:clientIp}

或者,您可以将数据类型转换添加到您的grok模式。默认情况下,所有的语义都保存为字符串。如果您希望转换语义的数据类型,例如将字符串更改为整数,则将其后缀与目标数据类型。例如%{NUMBER:num:int},将num语义从一个字符串转换为一个整数。目前唯一支持的转换是int和float。

例子:用这个语法和语义的思想,我们可以从一个样本日志中抽出有用的字段,就像这个虚构的http请求日志:

55.3.244.1 GET /index.html 15824 0.043

这种模式可能是:

%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes}%{NUMBER:duration}

一个更现实的例子,让我们从文件中读取这些日志:

input {

      file { path => "/var/log/http.log" }

}

filter {

grok {

match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}"

   }

}

}

在grok过滤器之后,会将行日志转化成json格式

client: 55.3.244.1,

method: GET,

request: /index.html,

bytes: 15824,

duration: 0.043,

在调试的过程中,不要一次性把全部的日志打出来,一次性将grok的表达式写出来,如果有一个写错的话,日志切分失败,错误很难排查出来。建议每一个一个字段地添加测试,比较快上手。对于一些特别长的字符串尽量是一些特殊字符包裹起来,比如使用

[“User-agent”]

这样会让gork表达式比较容易匹配

这个是我自己摸索出来日志格式,对应上面gork message

log.info("{} {} {} \"{}\" {} [{}] {}",request.getRequestURI(),IpUtil.getIpAddr(request),executionTime,value,request.getHeader("Referer"),request.getHeader("User-Agent"),“(请求参数)”);

打印的信息从左往右分别是:uri,客户端ip,请求执行时间,日志来源,Referer,User-Agent,我这样摆放是多次实验成果,得出最好方法。像uri,客户端Ip这种比较容易匹配放在前面,这些信息不容易为空,保证日志切分不会失效,像请求参数这些可能为空的字段,一定要放在最后,即使为空了,也不会影响整条日志切分。注意当Referer,User-Agent为空的情况下,会导致整条日志切分失败,在打印日志之前,最好做一下非空处理。

在调试这个logstash过程,我都是参考logstash gork nginx日志格式来写的。

nginx日志:

08/Jan/2016:08:27:43 +0800 - 10.10.6.212:8088 10.10.6.110:80 GET /vvv/te/stat/indexproptype=11&level=2&srtype=2&city=dzion=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2 - 10.10.6.10 HTTP/1.1 [Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36] [JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131] www.test.cn www.test.com 200 0 0 485 209 0"-" 1.642 1.642

对应的grok表达式

NGINXACCESS %{HTTPDATE:timestamp} - (?:%{HOSTPORT:upstream}|-) %{HOSTPORT:request_server} %{WORD:request_method} %{URIPATH:uri} %{URIPARAM1:args} - %{IP:clientip} HTTP/%{NUMBER:httpversion} \[%{GREEDYDATA:agent}\] \[%{GREEDYDATA:cookie}\] (?:%{REFER:referrer}|-) %{HOSTNAME:domain} %{NUMBER:status:int} 0 0 %{NUMBER:body_sent:int} %{NUMBER:request_length:int} 0\"(?:%{WORD:cache_status}|-)\"

最后copy从别人的帖子分享grok参数含义

常用表达式

USERNAME 或 USER

用户名,由数字、大小写及特殊字符(._-)组成的字符串

比如:1234、Bob、Alex.Wong等

EMAILLOCALPART

电子邮件用户名部分,首位由大小写字母组成,其他位由数字、大小写及特殊字符(_.+-=:)组成的字符串。注意,国内的QQ纯数字邮箱账号是无法匹配的,需要修改正则

比如:stone、Gary_Lu、abc-123等

EMAILADDRESS

电子邮件

比如:stone@abc.com、Gary_Lu@gmail.com、abc-123@163.com等

HTTPDUSER

Apache服务器的用户,可以是EMAILADDRESS或USERNAME

INT

整数,包括0和正负整数

比如:0、-123、43987等

BASE10NUM 或 NUMBER

十进制数字,包括整数和小数

比如:0、18、5.23等

BASE16NUM

十六进制数字,整数

比如:0x0045fa2d、-0x3F8709等

BASE16FLOAT

十六进制数字,整数和小数

WORD

字符串,包括数字和大小写字母

比如:String、3529345、ILoveYou等

NOTSPACE

不带任何空格的字符串

SPACE

空格字符串

QUOTEDSTRING 或 QS

带引号的字符串

比如:"This is an apple"、'What is your name?'等

UUID

标准UUID

比如:550E8400-E29B-11D4-A716-446655440000

MAC

MAC地址,可以是Cisco设备里的MAC地址,也可以是通用或者Windows系统的MAC地址

IP

IP地址,IPv4或IPv6地址

比如:127.0.0.1、FE80:0000:0000:0000:AAAA:0000:00C2:0002等

HOSTNAME

主机名称

IPORHOST

IP或者主机名称

HOSTPORT

主机名(IP)+端口

比如:127.0.0.1:3306、api.stozen.net:8000等

PATH

路径,Unix系统或者Windows系统里的路径格式

比如:/usr/local/nginx/sbin/nginx、c:\windows\system32\clr.exe等

URIPROTO

URI协议

比如:http、ftp等

URIHOST

URI主机

比如:www.stozen.net、10.0.0.1:22等

URIPATH

URI路径

比如://www.stozen.net/abc/、/api.php等

URIPARAM

URI里的GET参数

比如:?a=1&b=2&c=3

URIPATHPARAM

URI路径+GET参数

比如://www.stozen.net/abc/api.php?a=1&b=2&c=3

URI

完整的URI

比如:http://www.stozen.net/abc/api.php?a=1&b=2&c=3

日期时间表达式

MONTH

月份名称

比如:Jan、January等

MONTHNUM

月份数字

比如:03、9、12等

MONTHDAY

日期数字

比如:03、9、31等

DAY

星期几名称

比如:Mon、Monday等

YEAR

年份数字

HOUR

小时数字

MINUTE

分钟数字

SECOND

秒数字

TIME

时间

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容