Springboot项目通过logstash将日志分类写入Elasticsearch

需求:我们需要把线上日志收集起来进行分析。在开发阶段,更多的时候程序是运行在本地,所以使用FileBeats就有点繁琐。我们采用直接将日志通过tcp输出到logstash的方案。

同时,我们的日志并没有统一的格式,按照日志分析的需求格式都不一样。比如我们需要监控http请求的日志,监控websocket对话的日志,监控搜索关键词的日志等等。这就需要我们需要根据不同的需求制定各自的格式,然后分开输出到ES数据库。

一、安装ELK

这里对此不作过多讲解。es我使用的是docker版本,logstash的docker版本有点问题,所以最终使用的是rpm版本。

二、配置文件

我们就按照http和ws两种日志来处理。

创建logstash.conf文件,内容如下:

input {
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
    codec => json_lines
  }
}

filter {
  grok {
    match => [
      "message","%{NOTSPACE:tag}[T ]%{NOTSPACE:method}[T ]%{NOTSPACE:api}[T ]%{NOTSPACE:params}",
      "message","%{NOTSPACE:tag}[T ]%{NOTSPACE:author}[T ]%{NOTSPACE:msg}"
      ]
  }
}

output {
  if[tag]=="HTTP"{
    elasticsearch {
      hosts => ["192.168.0.101:9200"]
      index => "logstash-test-http-%{+YYYY.MM.dd}"
    }
  }
  if[tag]=="WS"{
    elasticsearch {
      hosts => ["192.168.0.101:9200"]
      index => "logstash-test-ws-%{+YYYY.MM.dd}"
    }
  }
}

大致讲解一下:

输入使用tcp插件。

过滤插件grok针对两种日志进行处理,我们设置两个标记HTTP和WS,把这两个值放在message的前边,HTTP日志用空格分成了四段,而WS日志只有三段。

这里要说明的是,日志格式都是简单地使用空格分隔,所以每一段输出的内容就不能带空格,否则解析会出错。如果确实需要空格,则每段信息就需要用符号进行分隔或者包裹,比如方括号。

输出插件根据处理之后的tag字段,按照不同的结构把数据写入到ES不同的index中。

logstash的运行命令

logstash -f /etc/logstash/conf.d/logstash.conf

如果测试完成,可以使用后台运行命令:

nohup logstash -f /etc/logstash/conf.d/logstash.conf >/var/log/logstash.log 2>&1 &

日志文件的位置需要提前创建。

三、Springboot项目

创建一个普通的Springboot项目。

1. 在pom中加入logstash依赖:

        
        
            net.logstash.logback
            logstash-logback-encoder
            5.3
        

2. 在静态资源文件夹下创建logback-spring.xml文件



    

    
    
        
        192.168.0.101:4560
        
        
            
                
                    UTC
                
                
                    
                        {
                        "logLevel": "%level",
                        "serviceName": "${springAppName:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "message": "%message"
                        }
                    
                
            
        
    

    
        
        
    

主要关注LOGSTASH的appender,以及相关的级别设置。

3. yml文件

server:
  port: 8011
spring:
  application:
    name: logstash-test
logging:
  level:
    com.chris.log: debug

注意日志级别设置,否则日志不能输出。

4.写一个用于测试的接口

@RestController
@RequestMapping("api")
public class TestController {
    Logger logger = LoggerFactory.getLogger(TestController.class);

    /**
     * 测试不同格式的message过滤处理之后写入不同的elasticsearch-index
     *
     * @param type
     * @return
     */
    @GetMapping("test")
    public Boolean test(int type) {
        switch (type) {
            case 1:
                logger.info("{} {} {} {}", "HTTP", "GET", "/api/test", "none");
                break;
            case 2:
                logger.info("{} {} {} {}", "HTTP", "POST", "/api/test", "天王盖地虎");
                break;
            case 3:
                logger.info("{} {} {}", "WS", "ChenFabao", "我已到达");
                break;
            default:
                logger.info("{} {} {} {}", "HTTP", "GET", "/api/test", "other");
                break;
        }
        return true;
    }
}

这里可以看出,第三条ws日志与http日志格式不同。

四、测试

运行起来,调用接口

http://localhost:8011/api/test?type=3

改变参数,刷新ES,可以看到出现了两个不同的index,查看内容,数据得到了正确的解析,结构也有分别。这样就便于我们正确查询和处理线上日志,解决bug。

Springboot项目通过logstash将日志分类写入Elasticsearch_第1张图片

Springboot项目通过logstash将日志分类写入Elasticsearch_第2张图片

Springboot项目通过logstash将日志分类写入Elasticsearch_第3张图片

五、问题

由于是临时方案,也遇到一个问题。用例是,应用程序修改了一点代码,然后重新运行,这时logstash就会报Connection reset by peer的错误,意思是tcp链接出现了问题。目前研究得比较浅,不知道怎么处理。看来如果需要在线上收集日志而不出现这个问题,还是借用FileBeats中转一下比较好,或者使用file输入插件读取日志文件来输入。

 

你可能感兴趣的:(Spring,Boot,Java)