• 前言
  • Log4j2配置
  • Logstash配置
  • ElasticSearch配置
  • Kibana配置
  • 实战
  • 总结

前言

通过阅读本文,我们了解如何在web项目中配置log4j2使得其可以与ELK协作。

说明:ELK是Logstash+ElasticSearch+Kibana,其中,Logstash负责收集日志,ElasticSearch负责存储日志,而Kibana提供界面查看日志信息。

Log4j2配置

Log4j2为我们提供SocketAppender,使得我们可以通过TCP或UDP发送日志,详见:http://logging.apache.org/log4j/2.x/manual/appenders.html#SocketAppender。

为了将日志发送到Logstash,我们的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< Configuration  status = "WARN"  monitorInterval = "60" >
     < Properties >
         < Property  name = "PATTERN" >%d %-5p [%t] %C{1} (%F:%L) - %m%n</ Property >
     </ Properties >
     < Appenders >
         < Socket  name = "Logstash"  host = "172.30.20.8"  port = "4560"  protocol = "TCP" >
             < PatternLayout  pattern = "${PATTERN}"  />
         </ Socket >
     </ Appenders >
     < Loggers >
         < Root  level = "error" >
             < AppenderRef  ref = "Logstash" />
         </ Root >
         < Logger  name = "Error"  level = "error"  additivity = "false" >
             < AppenderRef  ref = "Logstash" />
         </ Logger >
         < Logger  name = "Request"  level = "info"  additivity = "false" >
             < AppenderRef  ref = "Logstash" />
         </ Logger >
     </ Loggers >
</ Configuration >

我们在程序里打印我们的日志信息:

1
LogService.getLogger(LogService.REQUEST_LOG).info( "{} tries to login" , login);

Logstash配置

为了获取Log4j2的日志信息,我们编写logstash的配置文件micro-wiki.conf,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
input {
   tcp {
     host =>  "0.0.0.0"
     port =>  "4560"
     mode =>  "server"
     type =>  "microwiki"
     add_field => {
       "name"  =>  "Routh"
     }
   }
}
filter {
}
output {
   stdout {
     codec => rubydebug
   }
}

Logstash提供了log4j输入插件,但是只能用于log4j1.x,不能用于log4j2,因此,我们在配置文件中使用tcp输入插件,关于该插件的参数解释,详见:https://www.elastic.co/guide/en/logstash/current/plugins-inputs-tcp.html。

在该配置文件中,我们使用stdout输出插件以及rubydebug的codec插件,这使得我们的logstash输出打印在控制台,并且使用ruby的输出格式。

因此,当我们在控制台启动logstash,如下:

1
. /bin/logstash  -f config /micro-wiki .conf

当我们在应用程序打印日志,logstash的输出如下:

1
2
3
4
5
6
7
8
{
        "message"  =>  "2015-12-08 12:57:45,178 INFO  [qtp981012032-24] UserController (UserController.java:37) - hello tries to login" ,
       "@version"  =>  "1" ,
     "@timestamp"  =>  "2015-12-08T04:57:45.180Z" ,
           "host"  =>  "172.30.20.8" ,
           "type"  =>  "microwiki" ,
           "name"  =>  "Routh"
}

ElasticSearch配置

为了让logstash将日志信息输出到elasticsearch,我们更改logstash的配置文件,增加了名为elasticsearch的输出插件,如下:(详见:https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
input {
   tcp {
     host =>  "0.0.0.0"
     port =>  "4560"
     mode =>  "server"
     type =>  "microwiki"
     add_field => {
       "name"  =>  "Routh"
     }
   }
   stdin {}
}
filter {
}
output {
   stdout {
     codec => rubydebug
   }
   elasticsearch {
     hosts => [ "172.30.20.8:9200" ]
     action =>  "index"
     codec => rubydebug
     index =>  "microwiki-%{+YYYY.MM.dd}"
     template_name =>  "microwiki"
   }
}

我们修改elasticsearch的配置文件config/elasticsearch.yml,主要的修改为:

1
2
3
4
cluster.name: MicroWiki-Cluster
node.name: microwiki-node1
network.host:  172.30 . 20.8
http.port:  9200

elasticsearch的其他配置采用默认的配置项。配置完成后,我们启动elasticsearch,如下:

bin/elasticsearch -d

此时,我们通过应用程序打印日志,即可将日志信息通过logstash输出至elasticsearch,我们通过elasticsearch提供的API查看我们的日志信息,如下:

输入:

http://172.30.20.8:9200/microwiki-2015.12.08/_search

输出:

elasticsearch的输出结果 Collapse source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
   "took" 2 ,
   "timed_out" false ,
   "_shards" : {
     "total" 5 ,
     "successful" 5 ,
     "failed" 0
   },
   "hits" : {
     "total" 4 ,
     "max_score" 1 ,
     "hits" : [
       {
         "_index" "microwiki-2015.12.08" ,
         "_type" "microwiki" ,
         "_id" "AVGALOrsilzU44B28xlP" ,
         "_score" 1 ,
         "_source" : {
           "message" "2015-12-08 14:00:04,884 INFO  [qtp981012032-24] UserController (UserController.java:37) - hello tries to login" ,
           "@version" "1" ,
           "@timestamp" "2015-12-08T06:00:04.886Z" ,
           "host" "172.30.20.8" ,
           "type" "microwiki" ,
           "name" "Routh"
         }
       },
       {
         "_index" "microwiki-2015.12.08" ,
         "_type" "microwiki" ,
         "_id" "AVGAMByJilzU44B28xlR" ,
         "_score" 1 ,
         "_source" : {
           "message" "2015-12-08 14:03:35,357 INFO  [qtp981012032-22] UserController (UserController.java:37) -hello tries to login" ,
           "@version" "1" ,
           "@timestamp" "2015-12-08T06:03:35.358Z" ,
           "host" "172.30.20.8" ,
           "type" "microwiki" ,
           "name" "Routh"
         }
       },
       {
         "_index" "microwiki-2015.12.08" ,
         "_type" "microwiki" ,
         "_id" "AVGAMCCIilzU44B28xlS" ,
         "_score" 1 ,
         "_source" : {
           "message" "2015-12-08 14:03:35,831 INFO  [qtp981012032-22] UserController (UserController.java:37) - hello tries to login" ,
           "@version" "1" ,
           "@timestamp" "2015-12-08T06:03:35.831Z" ,
           "host" "172.30.20.8" ,
           "type" "microwiki" ,
           "name" "Routh"
         }
       },
       {
         "_index" "microwiki-2015.12.08" ,
         "_type" "microwiki" ,
         "_id" "AVGAMByJilzU44B28xlQ" ,
         "_score" 1 ,
         "_source" : {
           "message" "2015-12-08 14:03:34,608 INFO  [qtp981012032-25] UserController (UserController.java:37) - hello tries to login" ,
           "@version" "1" ,
           "@timestamp" "2015-12-08T06:03:34.609Z" ,
           "host" "172.30.20.8" ,
           "type" "microwiki" ,
           "name" "Routh"
         }
       }
     ]
   }
}

Kibana配置

Kibana提供良好的用户界面,使得我们可以很方便地访问elasticsearch并通过图形化工具展示。我们修改Kibana的配置文件,使之能与我们的elasticsearch配合使用,主要修改项如下:

1
2
3
server.host:  "172.30.20.8"
server.port:  5601
elasticsearch.url:  "<a href="http://172.30.20.8:9200/" "="" style="color: rgb(53, 114, 176); text-decoration: none; border-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important; background: none !important;">http://172.30.20.8:9200"

因为ELK所有组件都在同一台机器上跑,所以将其相关的URL都设置为172.30.20.8。此时,我们可以启动Kibana,它会自动连接elasticsearch,如下:

1
2
3
4
5
6
7
8
9
10
11
localhost:kibana- 4.3 . 0 -darwin-x64 routh$ bin/kibana
   log   [ 14 : 29 : 33.048 ] [info][status][plugin:kibana] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.066 ] [info][status][plugin:elasticsearch] Status changed from uninitialized to yellow - Waiting  for  Elasticsearch
   log   [ 14 : 29 : 33.074 ] [info][status][plugin:kbn_vislib_vis_types] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.080 ] [info][status][plugin:markdown_vis] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.084 ] [info][status][plugin:metric_vis] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.090 ] [info][status][plugin:spyModes] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.093 ] [info][status][plugin:statusPage] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.096 ] [info][status][plugin:elasticsearch] Status changed from yellow to green - Kibana index ready
   log   [ 14 : 29 : 33.097 ] [info][status][plugin:table_vis] Status changed from uninitialized to green - Ready
   log   [ 14 : 29 : 33.105 ] [info][listening] Server running at http: //172.30.20.8:5601

此时,我们通过浏览器访问:http://172.30.20.8:5601,进入Kibana页面,如下:

logstash默认的index为“logstash-%{+YYYY.MM.dd}”,而上述配置文件更改为“microwiki-%{+YYYY.MM.dd}”,因此我们配置该索引项,如下:

点击“Create”按钮,即可创建我们的索引项,该索引项所包含的字段如下:

导航条有四个选项:Discover、Visualize、Dashboard和Settings,点击“Discover”选项,如下:

注意图片右上角的红色框,我们可以在这筛选出我们所关心时间段的数据,图片所示为“Today”,即今天的数据。我们可以搜索我们关心的数据,也可以进入“Visualize”使用图形化工具查看我们所关心的数据。

此时,我们即可看到我们的日志数据,当然大部分字段是logstash和elasticsearch附加上去的,只有message字段是我们程序打印的日志信息。在logstash中,我们可以剔除我们不关心的字段,如host,我们也可以使用logstash提供的filter插件方便地解析我们的日志,即解析message内容,当然,这些内容不在本文所介绍的范围内。

实战

这里的实战主要为了说明如何根据项目中的日志样式进行解析。例如,我在项目中Log4j2使用的PatternLayout为:

<PatternLayout pattern="%d %p [%t] %C{1} (%F:%L) [%marker] - %m%n" />

在我的项目中,一共有三条打印日志的方式:

1
2
3
4
5
6
7
8
LogService.getLogger(LogService.REQUEST_LOG).info( "{} tries to login" , login);
 
LogService.getLogger(LogService.SERVICE_LOG).info(
         MarkerConstants.USER_MARKER,  "{} tries to create wiki with title {}" , UserUtils.getLoginUser(), title);
 
LogService.getLogger(LogService.SERVICE_LOG).info(MarkerConstants.WIKI_MARKER,
         "title={} header={} content={} footer={}" ,
         wiki.getTitle(), wiki.getHeader(), wiki.getContent(), wiki.getFooter());

它们打印的日志信息如下:

2015-12-11 10:37:57,291 INFO [qtp1975171943-26] UserController (UserController.java:27) [] - hello tries to login2015-12-11 10:38:42,277 INFO [qtp1975171943-24] WikiController (WikiController.java:31) [User] - UserModel{name='Routh', sex=1, age=25} tries to create wiki with title c952015-12-11 10:38:42,278 INFO [qtp1975171943-24] WikiController (WikiController.java:36) [Wiki] - title=c95 header=c95_header content=c95_content footer=c95_footer

此处,我们用两个Marker(User和Wiki)标记日志,这可以方便处理日志信息。User Marker用于记录用户日志,Wiki Marker用于记录Wiki每部分的内容,它是kv形式。(这不是实际项目,只是示例项目)

因此,我在Logstash中,为了解析我的日志格式,我使用grok和kv两个filter,配置文件如下:(input和output部分与上文示例一样)

1
2
3
4
5
6
7
8
9
10
11
12
filter {
   grok {
     match => {
       "message"  =>  "(?<datetime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3})\s(?<level>\w*)\s\[(?<thread>\S*)\]\s(?<class>\S*)\s\((?<file>[^:]*)[:]{1}(?<line>\d*)\)\s\[(?<marker>\w*)\]\s[-]\s(?<msg>.*)"
     }
   }
   if  ([marker] ==  "Wiki" ) {
     kv {
       include_keys => [  "title" "header" "content" "footer"  ]
     }
   }
}

此处,我使用自定义的grok模式(grok内置约120种模式)解析日志信息,并对marker为"Wiki"的日志信息,使用kv解析"title"、"header"、"content"和"footer"四个字段,我们看一看解析后的日志信息,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
        "message"  =>  "2015-12-10 19:51:43,367 INFO [qtp1975171943-23] WikiController (WikiController.java:31) [User] - UserModel{name='Routh', sex=1, age=25} tries to create wiki with title c75" ,
       "@version"  =>  "1" ,
     "@timestamp"  =>  "2015-12-10T11:51:43.367Z" ,
           "host"  =>  "172.30.20.8" ,
           "type"  =>  "microwiki" ,
           "name"  =>  "Routh" ,
       "datetime"  =>  "2015-12-10 19:51:43,367" ,
          "level"  =>  "INFO" ,
         "thread"  =>  "qtp1975171943-23" ,
          "class"  =>  "WikiController" ,
           "file"  =>  "WikiController.java" ,
           "line"  =>  "31" ,
         "marker"  =>  "User" ,
            "msg"  =>  "UserModel{name='Routh', sex=1, age=25} tries to create wiki with title c75"
}
{
        "message"  =>  "2015-12-10 19:51:43,367 INFO [qtp1975171943-23] WikiController (WikiController.java:36) [Wiki] - title=c75 header=c75_header content=c75_content footer=c75_footer" ,
       "@version"  =>  "1" ,
     "@timestamp"  =>  "2015-12-10T11:51:43.367Z" ,
           "host"  =>  "172.30.20.8" ,
           "type"  =>  "microwiki" ,
           "name"  =>  "Routh" ,
       "datetime"  =>  "2015-12-10 19:51:43,367" ,
          "level"  =>  "INFO" ,
         "thread"  =>  "qtp1975171943-23" ,
          "class"  =>  "WikiController" ,
           "file"  =>  "WikiController.java" ,
           "line"  =>  "36" ,
         "marker"  =>  "Wiki" ,
            "msg"  =>  "title=c75 header=c75_header content=c75_content footer=c75_footer" ,
          "title"  =>  "c75" ,
         "header"  =>  "c75_header" ,
        "content"  =>  "c75_content" ,
         "footer"  =>  "c75_footer"
}

此是其中的两条日志信息解析后的样子,有一些字段是logstash自带的,message为解析前的日志信息。若我们不希望记录某些日志,我们可以通过grok提供的remove_field移除我们不需要的字段信息,如:

grok {remove_field => [ "message", "name", "type" ]
}

至此,我们已经知道如何使用logstash解析我们的日志信息了。在我们的日志信息通过解析后传入elasticsearch处理。最后,我们可以通过Kibana查看我们的日志数据,如下图:

在此示例中,我logstash解析后的所有字段都输出到elasticsearch。若我们想统计某段时间内,创建wiki的情况,见下图:

在搜索框输入“_exists_:title”,目的在于筛选具有title字段的日志;x轴将时间按每分钟进行展示,y轴为对应的数量;右上角为所选的时间段。关于Kibana的搜索,采用Lucene的语法,详见:https://lucene.apache.org/core/2_9_4/queryparsersyntax.html。

至此,我们了解如何通过logstash的grok解析我们应用程序的日志,并通过Kibana搜索相关字段以图形化的方式展示。

总结

我们了解如何将log4j2的日志输出到ELK以及如何使用ELK收集、处理和展示我们的日志数据。为了更好地使用Log4j2+ELK,我们还需要深入学习。

Log4j2+ELK使用说明相关推荐

  1. log4j2+ELK

    问题初衷 最近有个项目需求,需要统计下用户app的使用情况,比如:什么时候登录的,查询了什么内容等信息. 解决方案 1.定义用户轨迹模型,每步操作都写到数据库中,然后在前端展示. 优点:可以针对业务需 ...

  2. ELK系列(1) - Elasticsearch + Logstash + Kibana + Log4j2快速入门与搭建用例

    前言 最近公司分了个ELK相关的任务给我,在一边学习一边工作之余,总结下这些天来的学习历程和踩坑记录. 首先介绍下使用ELK的项目背景:在项目的数据库里有个表用来存储消息队列的消费日志,这些日志用于开 ...

  3. Spring Boot应用集成Docker并结合Log4j2、Kafka、ELK管理Docker日志

    Preface 原文链接: http://yangbingdong.com/2018/spring-boot-docker-elk/ 微服务架构下,微服务在带来良好的设计和架构理念的同时,也带来了运维 ...

  4. Elastic stack 技术栈学习(三)—— 在Windows10系统下部署ELK

    目录 零.前言 最后才发现的超级棒的教程: 一. Elasticsearch 1. Elasticsearch部署 2. 基本概念 3. elasticsearch文件夹介绍 4. 源码安装elast ...

  5. Centos7 安装ELK/EFK 7.x 集群搭建实战攻略

    Centos7 安装ELK/EFK 7.x 集群搭建实战攻略 1.1 写在前面的话 1.2 开始之前 1.3 安装ELK/EFK 1.3.1 海量数据存储和检索-->E-->安装Elast ...

  6. Spring Boot 搭建 ELK,这才是正确看日志的方式!

    点击关注公众号,Java干货及时送达 作者:JingQ 来源:https://www.sevenyuan.cn 在看大型网站的中间件技术,对于Elasticsearch有点兴趣,所以将配置流程记录了一 ...

  7. elk日志分析系统_部署ELK企业内部日志分析系统

    部署ELK企业内部日志分析系统 一.实验环境 二.基本环境部署 1.IP地址配置 2.主机名配置三台节点hosts文件要一致 [root@yichen-els-node1 ~]# cat /etc/h ...

  8. ELK安装配置,日志展示

    ELK 首先要准备好ELK的安装包: jdk-8u162-linux-x64.rpm elasticsearch-6.2.4.rpm kibana-6.2.4-x86_64.rpm logstash- ...

  9. CentOs 7.2下ELK日志分析系统搭建

    系统环境 为了安装时不出错,建议选择这两者选择一样的版本,本文全部选择5.3版本. System: Centos release 7.2 Java: openjdk version "1.8 ...

最新文章

  1. FileReader对象和FormData对象
  2. 战略配售基金成热点,它或成为入局CDR的最优选择
  3. 【java读书笔记】——java的异常处理
  4. U3D-FSM有限状态机的简单设计
  5. 从土地利用规划到国土空间规划的一些思考
  6. eclipse-在编译项目时js特别慢的问题
  7. 这几年养成的几个比较好的工作习惯
  8. ASP.NET域集成AD身份验证
  9. 申音:被人为割裂的中国互联网
  10. cad放大_如何玩转CAD看图?1分钟,一款完全免费的高效软件,解决所有看图
  11. 打印的时候显示域服务器不可用,Win10打印时active directory域服务不可用解决方法...
  12. 一口气从零读懂CAN总线以及应用
  13. c++ 巧妙利用二进制,猜出你的生日 猜生日游戏
  14. 微信小程序生成普通网页的二维码
  15. Google Android SDK开发范例大全
  16. VR家居解决方案,打造可“移动”的家居体验馆
  17. Java获取时间几月第几周
  18. CenOS 7 网络连接设置
  19. 【嵌入式】单片机,FPGA,CPLD,PLC,DSP之间的关系与区别
  20. RFID标签EPC物品编码区PC协议控制字编码解析

热门文章

  1. 周鸿祎:360将发力物联网,解决老百姓的家庭安全问题
  2. 为何AI创业者在此集结?火山引擎X锦秋基金511神秘计划曝光
  3. 一个成功男人30岁前应该完成的那些事情
  4. 【PLC学习四】散装上料例子学习(1)
  5. tomcat 责任链设计模式 底层源码剖析
  6. 爬取超星考试题目_如何使用网页的源代码分析找到超星线上考试的答案
  7. Android 如何使Tablayout内容和下划线长度相同?
  8. 利用plsql工具恢复误删表和恢复误删数据
  9. 基于嵌入莱维飞行的灰狼优化(LGWO)算法的函数寻优算法
  10. excel 调用barTender打印条码 VBA 调用BarTender打印标签BarTender二次开发 VBA 条码打印 VBA二维码打印 Excel条码打印 Excel二维码打印