Docker ELK实践之Logstash

Posted Java后端笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker ELK实践之Logstash相关的知识,希望对你有一定的参考价值。

前言

日志这个东西在日常开发中起了很重要的作用。当你的服务部署到服务器上去,报了出了你意想不到的的错误,然后通过ssh去连接服务器查看日志,还要使用grep语句等查找语句,如果是直接部署到服务器还好,但是部署到Docker上面的话,那查看日志就更加麻烦了。 所以为了方便,能快速找到报出异常的日志,搭建ELK平台是十分重要的。

本文先讲解Logstash的搭建,Logstash的主要作用是解析日志。

日志统一

能快速定位错误日志的前提是,正确的打日志。为了方便我们解析日志,我们所有的项目需要统一日志格式。

在我们项目中,我们统一用logback打印日志,配置统一的logback文件即可。

贴下我们logback的配置

 
   
   
 
  1. <configuration scan="true" scanPeriod="3 seconds" debug="false">

  2.    <contextName>scj</contextName>

  3.    <!--配置常量,在后面的配置中使用 -->

  4.    <property name="PROJECT_NAME" value="scj-web" />

  5.    <property name="LOG_HOME" value="/app/logs/${PROJECT_NAME}" />

  6.    <!--定义日志输出格式 -->

  7.    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{ip}] [%thread] %-5level %logger{60} - %msg%n" />

  8.    <!-- 定义日志输出字符集 -->

  9.    <property name="LOG_CHARSET" value="UTF-8" />

  10.    <!-- 控制台 -->

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

  12.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  13.            <pattern>${LOG_PATTERN}</pattern>

  14.            <charset>${LOG_CHARSET}</charset>

  15.        </encoder>

  16.    </appender>

  17.    <!-- 全量日志 -->

  18.    <appender name="PROJECT-COMMON" class="ch.qos.logback.core.rolling.RollingFileAppender">

  19.        <file>${LOG_HOME}/${PROJECT_NAME}-common.log</file>

  20.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  21.            <pattern>${LOG_PATTERN}</pattern>

  22.            <charset>${LOG_CHARSET}</charset>

  23.        </encoder>

  24.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  25.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-common_%d{yyyy-MM-dd}.log

  26.            </fileNamePattern>

  27.            <maxHistory>30</maxHistory>

  28.        </rollingPolicy>

  29.    </appender>

  30.    <!-- 错误日志 -->

  31.    <appender name="PROJECT-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">

  32.        <file>${LOG_HOME}/${PROJECT_NAME}-error.log</file>

  33.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  34.            <pattern>${LOG_PATTERN}</pattern>

  35.            <charset>${LOG_CHARSET}</charset>

  36.        </encoder>

  37.        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">

  38.            <level>ERROR</level>

  39.        </filter>

  40.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  41.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-error_%d{yyyy-MM-dd}.log

  42.            </fileNamePattern>

  43.            <maxHistory>30</maxHistory>

  44.        </rollingPolicy>

  45.    </appender>

  46.    <!-- 业务日志 -->

  47.    <appender name="PROJECT-BIZ" class="ch.qos.logback.core.rolling.RollingFileAppender">

  48.        <file>${LOG_HOME}/${PROJECT_NAME}-biz.log</file>

  49.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  50.            <pattern>${LOG_PATTERN}</pattern>

  51.            <charset>${LOG_CHARSET}</charset>

  52.        </encoder>

  53.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  54.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-biz_%d{yyyy-MM-dd}.log

  55.            </fileNamePattern>

  56.            <maxHistory>30</maxHistory>

  57.        </rollingPolicy>

  58.    </appender>

  59.    <!-- 持久层日志 -->

  60.    <appender name="PROJECT-DAL" class="ch.qos.logback.core.rolling.RollingFileAppender">

  61.        <file>${LOG_HOME}/${PROJECT_NAME}-dal.log</file>

  62.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  63.            <pattern>${LOG_PATTERN}</pattern>

  64.            <charset>${LOG_CHARSET}</charset>

  65.        </encoder>

  66.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  67.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-dal_%d{yyyy-MM-dd}.log

  68.            </fileNamePattern>

  69.            <maxHistory>30</maxHistory>

  70.        </rollingPolicy>

  71.    </appender>

  72.    <!-- 调用dubbo日志 -->

  73.    <appender name="PROJECT-INTEG" class="ch.qos.logback.core.rolling.RollingFileAppender">

  74.        <file>${LOG_HOME}/${PROJECT_NAME}-integ.log</file>

  75.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  76.            <pattern>${LOG_PATTERN}</pattern>

  77.            <charset>${LOG_CHARSET}</charset>

  78.        </encoder>

  79.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  80.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-integ_%d{yyyy-MM-dd}.log

  81.            </fileNamePattern>

  82.            <maxHistory>30</maxHistory>

  83.        </rollingPolicy>

  84.    </appender>

  85.    <appender name="PROJECT-SHIRO" class="ch.qos.logback.core.rolling.RollingFileAppender">

  86.        <file>${LOG_HOME}/${PROJECT_NAME}-shiro.log</file>

  87.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  88.            <pattern>${LOG_PATTERN}</pattern>

  89.            <charset>${LOG_CHARSET}</charset>

  90.        </encoder>

  91.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  92.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-shiro_%d{yyyy-MM-dd}.log

  93.            </fileNamePattern>

  94.            <maxHistory>30</maxHistory>

  95.        </rollingPolicy>

  96.    </appender>

  97.    <appender name="PROJECT-CAS" class="ch.qos.logback.core.rolling.RollingFileAppender">

  98.        <file>${LOG_HOME}/${PROJECT_NAME}-cas.log</file>

  99.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  100.            <pattern>${LOG_PATTERN}</pattern>

  101.            <charset>${LOG_CHARSET}</charset>

  102.        </encoder>

  103.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  104.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-cas_%d{yyyy-MM-dd}.log

  105.            </fileNamePattern>

  106.            <maxHistory>30</maxHistory>

  107.        </rollingPolicy>

  108.    </appender>

  109.    <appender name="PROJECT-MYBATIS" class="ch.qos.logback.core.rolling.RollingFileAppender">

  110.        <file>${LOG_HOME}/${PROJECT_NAME}-mybatis.log</file>

  111.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  112.            <pattern>${LOG_PATTERN}</pattern>

  113.            <charset>${LOG_CHARSET}</charset>

  114.        </encoder>

  115.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  116.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-mybatis_%d{yyyy-MM-dd}.log

  117.            </fileNamePattern>

  118.            <maxHistory>30</maxHistory>

  119.        </rollingPolicy>

  120.    </appender>

  121.    <appender name="PROJECT-DUBBO" class="ch.qos.logback.core.rolling.RollingFileAppender">

  122.        <file>${LOG_HOME}/${PROJECT_NAME}-dubbo.log</file>

  123.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  124.            <pattern>${LOG_PATTERN}</pattern>

  125.            <charset>${LOG_CHARSET}</charset>

  126.        </encoder>

  127.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  128.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-dubbo_%d{yyyy-MM-dd}.log

  129.            </fileNamePattern>

  130.            <maxHistory>30</maxHistory>

  131.        </rollingPolicy>

  132.    </appender>

  133.    <appender name="PROJECT-APACHECOMMON" class="ch.qos.logback.core.rolling.RollingFileAppender">

  134.        <file>${LOG_HOME}/${PROJECT_NAME}-apachecommon.log</file>

  135.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  136.            <pattern>${LOG_PATTERN}</pattern>

  137.            <charset>${LOG_CHARSET}</charset>

  138.        </encoder>

  139.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  140.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-apachecommon_%d{yyyy-MM-dd}.log

  141.            </fileNamePattern>

  142.            <maxHistory>30</maxHistory>

  143.        </rollingPolicy>

  144.    </appender>

  145.    <appender name="PROJECT-ZOOKEEPER" class="ch.qos.logback.core.rolling.RollingFileAppender">

  146.        <file>${LOG_HOME}/${PROJECT_NAME}-zookeeper.log</file>

  147.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  148.            <pattern>${LOG_PATTERN}</pattern>

  149.            <charset>${LOG_CHARSET}</charset>

  150.        </encoder>

  151.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  152.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-zookeeper_%d{yyyy-MM-dd}.log

  153.            </fileNamePattern>

  154.            <maxHistory>30</maxHistory>

  155.        </rollingPolicy>

  156.    </appender>

  157.    <appender name="PROJECT-SPRING" class="ch.qos.logback.core.rolling.RollingFileAppender">

  158.        <file>${LOG_HOME}/${PROJECT_NAME}-spring.log</file>

  159.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  160.            <pattern>${LOG_PATTERN}</pattern>

  161.            <charset>${LOG_CHARSET}</charset>

  162.        </encoder>

  163.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  164.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-spring_%d{yyyy-MM-dd}.log

  165.            </fileNamePattern>

  166.            <maxHistory>30</maxHistory>

  167.        </rollingPolicy>

  168.    </appender>

  169.    <appender name="PROJECT-QUARTZ" class="ch.qos.logback.core.rolling.RollingFileAppender">

  170.        <file>${LOG_HOME}/${PROJECT_NAME}-quartz.log</file>

  171.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  172.            <pattern>${LOG_PATTERN}</pattern>

  173.            <charset>${LOG_CHARSET}</charset>

  174.        </encoder>

  175.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  176.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-quartz_%d{yyyy-MM-dd}.log

  177.            </fileNamePattern>

  178.            <maxHistory>30</maxHistory>

  179.        </rollingPolicy>

  180.    </appender>

  181.    <appender name="PROJECT-APACHEHTTP" class="ch.qos.logback.core.rolling.RollingFileAppender">

  182.        <file>${LOG_HOME}/${PROJECT_NAME}-apachehttp.log</file>

  183.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  184.            <pattern>${LOG_PATTERN}</pattern>

  185.            <charset>${LOG_CHARSET}</charset>

  186.        </encoder>

  187.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  188.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-apachehttp_%d{yyyy-MM-dd}.log

  189.            </fileNamePattern>

  190.            <maxHistory>30</maxHistory>

  191.        </rollingPolicy>

  192.    </appender>

  193.    <appender name="PROJECT-OTHER" class="ch.qos.logback.core.rolling.RollingFileAppender">

  194.        <file>${LOG_HOME}/${PROJECT_NAME}-other.log</file>

  195.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  196.            <pattern>${LOG_PATTERN}</pattern>

  197.            <charset>${LOG_CHARSET}</charset>

  198.        </encoder>

  199.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  200.            <fileNamePattern>${LOG_HOME}/${PROJECT_NAME}-other_%d{yyyy-MM-dd}.log

  201.            </fileNamePattern>

  202.            <maxHistory>30</maxHistory>

  203.        </rollingPolicy>

  204.    </appender>

  205.    <!-- (1)root中只配置控制台日志,其他所有的日志把additivity设置为true都打到控制台,方便开发阶段定位问题。 -->

  206.    <!-- (2)第三方框架的日志抽取到单独的文件中,并且级别为ERROR。 -->

  207.    <!-- root -->

  208.    <root level="INFO">

  209.        <appender-ref ref="CONSOLE" />

  210.        <appender-ref ref="PROJECT-COMMON" />

  211.        <appender-ref ref="PROJECT-ERROR" />

  212.    </root>

  213.    <!-- 项目自己的日志 -->

  214.    <!-- 业务日志 -->

  215.    <logger name="com.scj.controllers" level="debug" additivity="false">

  216.        <appender-ref ref="PROJECT-BIZ" />

  217.        <appender-ref ref="PROJECT-ERROR" />

  218.    </logger>

  219.    <!-- 其他开源框架的日志不打印到PROJECT-COMMON,但错误级别的会打印到PROJECT-ERROR -->

  220.    <!-- shiro日志 -->

  221.    <logger name="org.apache.shiro" level="debug" additivity="false">

  222.        <appender-ref ref="PROJECT-SHIRO" />

  223.        <appender-ref ref="PROJECT-ERROR" />

  224.    </logger>

  225.    <!-- jasig.cas的日志,error级别 -->

  226.    <logger name="org.jasig.cas" level="debug" additivity="false">

  227.        <appender-ref ref="PROJECT-CAS" />

  228.        <appender-ref ref="PROJECT-ERROR" />

  229.    </logger>

  230.    <!-- mybatis的日志 -->

  231.    <logger name="org.mybatis" level="debug" additivity="false">

  232.        <appender-ref ref="PROJECT-MYBATIS" />

  233.        <appender-ref ref="PROJECT-ERROR" />

  234.    </logger>

  235.    <!-- zookeeper的日志,因为会比较多所以是error级别 -->

  236.    <logger name="org.apache.zookeeper" level="debug" additivity="false">

  237.        <appender-ref ref="PROJECT-ZOOKEEPER" />

  238.        <appender-ref ref="PROJECT-ERROR" />

  239.    </logger>

  240.    <logger name="org.I0Itec.zkclient" level="debug" additivity="false">

  241.        <appender-ref ref="PROJECT-ZOOKEEPER" />

  242.        <appender-ref ref="PROJECT-ERROR" />

  243.    </logger>

  244.    <!-- dubbo的日志,error级别 -->

  245.    <logger name="com.alibaba.dubbo" level="debug" additivity="false">

  246.        <appender-ref ref="PROJECT-DUBBO" />

  247.        <appender-ref ref="PROJECT-ERROR" />

  248.    </logger>

  249.    <!-- apache-common的日志,error级别 -->

  250.    <logger name="org.apache.commons" level="debug" additivity="false">

  251.        <appender-ref ref="PROJECT-APACHECOMMON" />

  252.        <appender-ref ref="PROJECT-ERROR" />

  253.    </logger>

  254.    <!-- spring的日志,error级别 -->

  255.    <logger name="org.springframework" level="debug" additivity="false">

  256.        <appender-ref ref="PROJECT-SPRING" />

  257.        <appender-ref ref="PROJECT-ERROR" />

  258.    </logger>

  259.    <!-- quartz的日志,error级别 -->

  260.    <logger name="org.quartz" level="debug" additivity="false">

  261.        <appender-ref ref="PROJECT-QUARTZ" />

  262.        <appender-ref ref="PROJECT-ERROR" />

  263.    </logger>

  264.    <logger name="org.apache.http" level="debug" additivity="false">

  265.        <appender-ref ref="PROJECT-APACHEHTTP" />

  266.        <appender-ref ref="PROJECT-ERROR" />

  267.    </logger>

  268.    <logger name="com.baidu.disconf" level="info" additivity="false">

  269.        <appender-ref ref="PROJECT-COMMON" />

  270.        <appender-ref ref="PROJECT-ERROR" />

  271.    </logger>

  272. </configuration>

Dubbo Main方式启动设置logback

我们的纯Dubbo项目不是通过web容器启动,所以需要做一些配置让logback生效

 
   
   
 
  1. public static void main(String[] args) throws Exception {

  2.        System.setProperty("dubbo.application.logger","slf4j");

  3.        MDC.put("ip", InetAddress.getLocalHost().getHostAddress());

  4.        com.alibaba.dubbo.container.Main.main(args);

  5.    }

dubbo默认的日志系统是log4j,这边通过设置环境变量把日志系统改为slf4j,slf4j会根据classpath中的桥接包选择具体的日志系统实现。需要注意在pom依赖中去除其他的桥接包,比如org.slf4j.slf4j-log4j12。

MDC

logback内置的日志字段还是比较少,如果我们需要打印有关业务的更多的内容,包括自定义的一些数据,需要借助logback MDC机制,MDC为“Mapped Diagnostic Context”(映射诊断上下文),即将一些运行时的上下文数据通过logback打印出来;此时我们需要借助org.sl4j.MDC类。

MDC类基本原理其实非常简单,其内部持有一个InheritableThreadLocal实例,用于保存context数据,MDC提供了put/get/clear等几个核心接口,用于操作ThreadLocal中的数据;ThreadLocal中的K-V,可以在logback.xml中声明,最终将会打印在日志中。

那么在logback.xml中,即可在layout中通过声明“%X{userId}”来打印此信息。

Dubbo Main启动方式设置MDC

这种启动方式设置MDC十分简单 在main函数中增加一下代码即可

 
   
   
 
  1. MDC.put("ip", InetAddress.getLocalHost().getHostAddress());

web容器启动方式设置MDC

这里我们通过监听spring上下文的ContextRefreshedEvent事件实现,代码如下

 
   
   
 
  1. @Service

  2. @Slf4j

  3. public class MDCListener implements ApplicationListener<ContextRefreshedEvent>{

  4.    @Override

  5.    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {

  6.        try {

  7.            MDC.put("ip", InetAddress.getLocalHost().getHostAddress());

  8.        } catch (UnknownHostException e) {

  9.            log.error("MDC 设置ip失败",e);

  10.        }

  11.    }

  12. }

正确的打日志

日志最大的作用就是排查问题,如果你打的日志没有把问题产生点输出,那这个日志就是白打。在我们项目中,我看到这么一些打印日志的代码把异常也通过占位符输出了,那么会调用e.toString()方法,只会打出当前方法的错误日志,看不到整个异常栈。

正确的做法是

 
   
   
 
  1. log.error("发生错误xxx....",e);

日志框架会把整个异常栈打印出来

Logstash安装

Logstash在Docker中启动,由于公司服务器不能连接elastic官网镜像,所以通过下面命令从docker官方镜像库拉取,版本不能保证是官方最新。

 
   
   
 
  1. docker pull logstash

拉好镜像之后就是启动容器了

 
   
   
 
  1. docker run -d

  2. -v  /app/logs:/app/logs

  3. -v /etc/logstash/pipeline/first-pipeline.conf:/etc/logstash/pipeline/first-pipeline.conf

  4. -v /etc/logstash/logstash.yml:/etc/logstash/logstash.yml

  5. -v /app/data/logstash:/app/data/logstash

  6. logstash

  7. logstash -f /etc/logstash/pipeline/first-pipeline.conf

上面这个命令我不保证完全正确,因为我都是在rancher配置参数启动的,接下来有空我会写个demo测试

-v /app/logs:/app/logs 映射日志存储的目录,日志产生的docker容器也需要配置这个 -v /etc/logstash/pipeline/first-pipeline.conf:/etc/logstash/pipeline/first-pipeline.conf 映射pipeline配置文件 -v /etc/logstash/logstash.yml:/etc/logstash/logstash.yml 映射logstash配置文件 -v /app/data/logstash:/app/data/logstash 映射logstash的一些存储文件,我主要想保存file的读取位置,保证镜像升级后不会重新读取

一个重要的点

这边需要mark一下, /app/data/logstash这个目录,docker镜像内需要向这个目录写入文件,但是在宿主机权限一般是root用户,docker内部的用户不是root,就算是root id也匹配不上,所以docker容器内向宿主机目录写入的时候会报错。 两种解决方式,第一种,暴力解决,chmod +777 ,第二种,通过 cat /etc/passwd拿到docker容器内logstash用户id,然后再宿主机,通过chown id /app/data/logstash设置目录权限。

配置文件编写

在使用logstash前,需要对它有一定的了解。logstash的组件其实很简单,主要包括input、filter、output、codec四个部分。

  • input 用于读取内容,常用的有stdin(直接从控制台输入)、file(读取文件)等,另外还提供了对接redis、kafka等的插件

  • filter 用于对输入的文本进行处理,常用的有grok(基于正则表达式提取字段)、kv(解析键值对形式的数据)、csv、xml等,另外还提供了了一个ruby插件,这个插件如果会用的话,几乎是万能的。

  • output 用于把fitler得到的内容输出到指定的接收端,常用的自然是elasticsearch(对接ES)、file(输出到文件)、stdout(直接输出到控制台)

  • codec 它用于格式化对应的内容,可以再Input和output插件中使用,比如在output的stdout中使用rubydebug以json的形式输出到控制台

以下是我的配置文件

 
   
   
 
  1. input{

  2.        file{

  3.                path => "/app/logs/*/*.log"

  4.                        exclude => "*-error.log"

  5.                        codec => multiline {

  6.                                pattern => "^%{TIMESTAMP_ISO8601}"

  7.                                        what => "previous"

  8.                                        negate => true

  9.                        }

  10.        }

  11. }

  12. filter{

  13.        grok{

  14.                match =>{

  15.                        "message" => "%{TIMESTAMP_ISO8601:date}s*[%{DATA:ip}]s*[%{DATA:thread}]s*%{LOGLEVEL:level}s*%{NOTSPACE:clazz}s*-s*%{DATA:method}s*(?<body>[Ss]*)"

  16.                }

  17.                remove_field => ["@timestamp","host","@version"]

  18.        }

  19.        grok{

  20.                match => {

  21.                        "path" => "/app/logs/%{NOTSPACE:project}/"

  22.                }

  23.        }

  24.        mutate{

  25.                replace => ["date","%{date}+0800"]

  26. }

  27.        date {

  28.                match => ["date", "yyyy-MM-dd HH:mm:ss.SSSZ"]

  29.                        target => "@timestamp"

  30.        }

  31. }

  32. output{

  33.        stdout{

  34.                codec => rubydebug

  35.        }

  36.        elasticsearch{

  37.                hosts => "es:9200"

  38.                        index => "testindex"

  39.        }

  40. }

input模块用来配置日志的来源,我这边是文件,codec => multiline用来处理日志分行的情况,异常报错日志有很多行,但是每个日志都是时间开头的

filter用来解析日志,提取有用信息。 grok模块用来提取字段,我们可以在http://grokdebug.herokuapp.com/这个网站来验证自己写的表达式是否正确,在http://grokdebug.herokuapp.com/patterns可以查看各种自带的配置表达式,我的第一个grok用来解析日志中有用字段,第二个grok通过日志的目录来解析出应用名称。 mutate模块对时间进行处理,加上时区,不然在kibana查询会有8个小时时间差。 date模块用来转换时间,经过研究可有可无,直接用date字段即可。

output模块用来选择解析后的日志输出位置,我这边配置了控制台(用于调试)和ES。测试通过后,需要把stdout这块删除。

下面贴上logstash.yml

 
   
   
 
  1. pipeline:

  2.  batch:

  3.    size: 125

  4.    delay: 50

  5. path:

  6.  data: /app/data/logstash

没什么东西,主要设置了path.data,再这个目录下面会保存文件读取位置Docker ELK实践之Logstash

注意这个文件是隐藏的,并且它再plugin/input/file目录下,因为这个读取位置的文件是和file有关的

看下这个文件的内容吧Docker ELK实践之Logstash

sincedb的格式为inode majorNumber minor Number pos。每行记录每个文件处理进度,比如下面的例子,表示inode为177037的文件处理到25951716位置、inode为176956的文件处理到32955178位置。

 
   
   
 
  1. 177037 0 64768 25951716

  2. 176956 0 64768 32955178

什么是inode请看这篇文章(https://www.cnblogs.com/bkylee/p/5484288.html)

如果我们测试的时候需要重新读取,那么把这个文件删掉就可以了

总结

我这个ELK是给开发测试预发环境使用,因为现在的设计是每个环境搭一套,所以没有必要使用filebeat这种轻量级的收集器,我现在也只是把开发环境搭好了,准备向运维单独申请服务器放置ELK,然后再各个环境启动filebeat,如果ELK消费不过来,中间再弄一个消息队列缓冲。这都是以后的事情了。

下一篇就讲解下Docker搭建ES和Kibana以及一些操作把。相对于本章较简单。

接下来上一点我学习的链接 logstash官方文档(https://www.elastic.co/guide/en/logstash/current/index.html) 一篇很好的ELK入门文章(https://www.cnblogs.com/xing901022/p/6596182.html) 这家伙的logstash介绍也还凑合(http://www.51niux.com/?id=203) grok表达式工具网站(http://grokdebug.herokuapp.com/) logbakc MDC(http://shift-alt-ctrl.iteye.com/blog/2345272) 解决Docker不能向宿主机目录写入问题(https://blog.csdn.net/csdn_duomaomao/article/details/78567748) logstash处理文件进度记录机制(https://blog.csdn.net/wangyangzhizhou/article/details/53328040)

最后

看到这里的观众,关注吧,关于技术的一切我都有可能分享


以上是关于Docker ELK实践之Logstash的主要内容,如果未能解决你的问题,请参考以下文章

Docker安装部署ELK教程 (Elasticsearch+Kibana+Logstash+Filebeat)

ELK docker 安装logstash

五分钟带你玩转docker(十三)实战elk环境——logstash搭建

五分钟带你玩转docker(十三)实战elk环境——logstash搭建

ELK——Logstash 2.2 date 插件翻译+实践

Docker安装部署ELK教程 (Elasticsearch+Kibana+Logstash+Filebeat)