【 前面的话 】在前面我们已经介绍了Elasticsearch、 Logstash 、 Kibana 和Beats,并且都对各个组件进行了初步体验。今天我们就来模拟一把日常使用,来收集一个我们自己的应用的日志,并使用Kibana展示。
Centos:CentOS-7-x86_64-Minimal-1908 VM: 15.5.0 build-14665864 Java: 1.8.0_211 Elasticsearch: elasticsearch-7.6.0 Logstash: logstash-7.6.0 Kibana: kibana-7.6.0 Filebeat:filebeat-7.6.0
我们这里来模拟一个现在购物网站的使用,主要代码如下
package com.eelve.elk.dashboardgenerate; import org.apache.commons.lang3.RandomUtils; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DashboardGenerateApplication { private static final Logger LOGGER = LoggerFactory.getLogger(DashboardGenerateApplication.class); public static final String[] VISIT = new String[]{"浏览页面", "评论商品", "加入收藏", "加入购物车", "提交订单", "使用优惠券", "领取优惠券", "搜索", "查看订单"}; public static void main(String[] args) throws Exception { while(true){ Long sleep = RandomUtils.nextLong(200, 1000 * 5); Thread.sleep(sleep); Long maxUserId = 9999L; Long userId = RandomUtils.nextLong(1, maxUserId); String visit = VISIT[RandomUtils.nextInt(0, VISIT.length)]; DateTime now = new DateTime(); int maxHour = now.getHourOfDay(); int maxMillis = now.getMinuteOfHour(); int maxSeconds = now.getSecondOfMinute(); String date = now.plusHours(-(RandomUtils.nextInt(0, maxHour))) .plusMinutes(-(RandomUtils.nextInt(0, maxMillis))) .plusSeconds(-(RandomUtils.nextInt(0, maxSeconds))) .toString("yyyy-MM-dd HH:mm:ss"); String result = "IIO|" + userId + "|" + visit + "|" + date; LOGGER.info(result); } } }
log4j.rootLogger=DEBUG,A1,A2 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%c] - %m%n log4j.appender.A2 = org.apache.log4j.DailyRollingFileAppender log4j.appender.A2.File = /iio/logs/app.log log4j.appender.A2.Append = true log4j.appender.A2.Threshold = INFO log4j.appender.A2.layout = org.apache.log4j.PatternLayout log4j.appender.A2.layout.ConversionPattern =[%p] %-d{yyyy-MM-dd HH:mm:ss} [%c] - %m%n
"C:/Program Files/Java/jdk1.8.0_221/bin/java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:C:/Program Files/JetBrains/IntelliJ IDEA 2019.1/lib/idea_rt.jar=6396:C:/Program Files/JetBrains/IntelliJ IDEA 2019.1/bin" -Dfile.encoding=UTF-8 -classpath "C:/Program Files/Java/jdk1.8.0_221/jre/lib/charsets.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/deploy.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/access-bridge-64.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/cldrdata.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/dnsns.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/jaccess.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/jfxrt.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/localedata.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/nashorn.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/sunec.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/sunjce_provider.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/sunmscapi.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/sunpkcs11.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/ext/zipfs.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/javaws.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/jce.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/jfr.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/jfxswt.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/jsse.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/management-agent.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/plugin.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/resources.jar;C:/Program Files/Java/jdk1.8.0_221/jre/lib/rt.jar;D:/iio/dashboard-generate/target/classes;C:/Users/Chirius/.m2/repository/org/springframework/boot/spring-boot-starter/2.2.5.RELEASE/spring-boot-starter-2.2.5.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/boot/spring-boot/2.2.5.RELEASE/spring-boot-2.2.5.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-context/5.2.4.RELEASE/spring-context-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-aop/5.2.4.RELEASE/spring-aop-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-beans/5.2.4.RELEASE/spring-beans-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-expression/5.2.4.RELEASE/spring-expression-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.2.5.RELEASE/spring-boot-autoconfigure-2.2.5.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.2.5.RELEASE/spring-boot-starter-logging-2.2.5.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.12.1/log4j-to-slf4j-2.12.1.jar;C:/Users/Chirius/.m2/repository/org/apache/logging/log4j/log4j-api/2.12.1/log4j-api-2.12.1.jar;C:/Users/Chirius/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar;C:/Users/Chirius/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-core/5.2.4.RELEASE/spring-core-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/springframework/spring-jcl/5.2.4.RELEASE/spring-jcl-5.2.4.RELEASE.jar;C:/Users/Chirius/.m2/repository/org/yaml/snakeyaml/1.25/snakeyaml-1.25.jar;C:/Users/Chirius/.m2/repository/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar;C:/Users/Chirius/.m2/repository/joda-time/joda-time/2.9.9/joda-time-2.9.9.jar;C:/Users/Chirius/.m2/repository/org/slf4j/slf4j-log4j12/1.7.26/slf4j-log4j12-1.7.26.jar;C:/Users/Chirius/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar;C:/Users/Chirius/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar" com.eelve.elk.dashboardgenerate.DashboardGenerateApplication [INFO] 2020-03-14 21:06:09 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|4234|加入收藏|2020-03-14 04:04:03 [INFO] 2020-03-14 21:06:11 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|6502|领取优惠券|2020-03-14 14:05:07 [INFO] 2020-03-14 21:06:12 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|3694|加入购物车|2020-03-14 20:03:09 [INFO] 2020-03-14 21:06:14 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|8112|使用优惠券|2020-03-14 12:06:02 [INFO] 2020-03-14 21:06:14 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|3391|加入收藏|2020-03-14 02:01:05 [INFO] 2020-03-14 21:06:17 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|3696|搜索|2020-03-14 04:06:05 [INFO] 2020-03-14 21:06:18 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|6670|使用优惠券|2020-03-14 17:04:17 [INFO] 2020-03-14 21:06:21 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|6646|搜索|2020-03-14 11:06:05 [INFO] 2020-03-14 21:06:24 [com.eelve.elk.dashboardgenerate.DashboardGenerateApplication] - IIO|8227|使用优惠券|2020-03-14 12:06:24 Process finished with exit code -1
我们这里模拟了用户的操作,并记录到/iio/logs/app.log文件中。主要的业务流程为:APP->filebeat->logstash->elasticsearch->kibanan->User
[iio@192 filebeat]$ vi dashboard.yml filebeat.inputs: - type: log enabled: true paths: - /iio/logs/*.log output.logstash: hosts: ["192.168.237.11:5044"]
[iio@192 config]$ vi logstash-dashboard.yml input { beats { port => "5044" } } filter { mutate { split => {"message"=>"|"} } mutate { add_field => { "userId" => "%{[message][1]}" "visit" => "%{[message][2]}" "date" => "%{[message][3]}" } } mutate { convert => { "userId" => "integer" "visit" => "string" "date" => "string" } } } output { elasticsearch { hosts => ["192.168.237.11:9200"] } }
[root@192 home]# java -jar dashboard-generate-0.0.1-SNAPSHOT.jar &
[iio@192 bin]$ ./elasticsearch
[iio@192 bin]$ ./kibana
[iio@192 bin]$ ./logstash -f /usr/elastic/logstash/config/logstash-dashboard.yml
[iio@192 filebeat]$ ./filebeat -e -c dashboard.yml
到这里我们可以看到就已经完成了对我们自定义数据的监控,然后还利用了Kibana做了图表化展示。
【 后面的话 】在我们日常应用中,我们的日志需要按照某种跪着产生,方便我们使用logstash进行过滤,然后做一些处理。也就是说我们在开发之前就应该想好日志生成的格式,然后设计好日志的处理方式。