.net core+ado.net如何架构项目_从零学ELK系列(八):SpringBoot项目接入ELK(超详细图文教程)

【从零学ELK系列目录】

从零学ELK系列(一):为什么要跟我学从零学ELK系列

从零学ELK系列(二):VMware安装Centos(超详细图文教程)

从零学ELK系列(三):Centos安装Docker(超详细图文教程)

从零学ELK系列(四)Docker安装Elasticsearch(超详细图文教程)

从零学ELK系列(五):Docker安装kibana(超详细图文教程)

从零学ELK系列(六):Docker安装Logstash(超详细图文教程)

从零学ELK系列(七):Centos安装Filebeat(超详细图文教程)

从零学ELK系列(八):SpringBoot项目接入ELK(超详细图文教程)

从零学ELK系列(九):Nginx接入ELK(超详细图文教程)

【前言】

在前几篇博文中将ELK+Filebeat日志收集系统搭建完毕,本次我们将展示如何将SpringBoot接入我们搭建的日志系统,把步骤记录下来,一是方便自己以后安装,二是可以为大家做参考共享。

【一句总结一张架构图】

一、一句话总结学完本篇博文,你将学到什么?

SpringBoot项目接入ELK+Filebeat收集系统,Kibana设置展示日志

二、架构图

bf377e835cc146be9d772959c1b8b0b5

【SpringBoot接入ELK】

一、环境:

1、Windows系统(本人是win10环境)

2、VMware10.0.1

3、Centos 7.4

4、Xshell5

5、Docker 19.03

6、Elasticsearch 7.2.0

7、Kibana 7.2.0

8、Logstash 7.2.0

9、Filebeat 7.2.0

10、SpringBoot项目 (项目地址:https://github.com/dangnianchuntian/springboot 版本号1.7.0-Release)

二、项目接入主要代码展示:

1、通过拦截请求,记录请求日志

/* * Copyright (c) 2019. zhanghan_java@163.com All Rights Reserved. * 项目名称:实战SpringBoot * 类名称:ControllerLogAspectConf.java * 创建人:张晗 * 联系方式:zhanghan_java@163.com * 开源地址: https://github.com/dangnianchuntian/springboot * 博客地址: https://zhanghan.blog.csdn.net */package com.zhanghan.zhboot.aop;import com.zhanghan.zhboot.util.FileBeatLogUtil;import com.zhanghan.zhboot.util.HttpTypeUtil;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.annotation.Order;import org.springframework.core.env.Environment;import org.springframework.stereotype.Component;@Aspect@Order(0)@Componentpublic class RequestLogAspectConf {    @Autowired    private Environment env;    /**     * 范围切点方法     */    @Pointcut("execution(* com.zhanghan.zhboot.controller..*.*(..))")    public void methodPointCut() {    }    @Before("methodPointCut()")    void doBefore(JoinPoint joinPoint) {        authLogic(joinPoint);    }    private void authLogic(JoinPoint joinPoint) {        try {            Logger log = LoggerFactory.getLogger("logstashInfo");            String applicationName = env.getProperty("spring.application.name");            //获取当前http请求            String reqName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();            String requestParams = FileBeatLogUtil.getParams(joinPoint);            FileBeatLogUtil.writeLog(log, applicationName, HttpTypeUtil.REQUEST, reqName, requestParams);        } catch (Exception e) {            System.out.println(e.getMessage());        }    }}

2、通过拦截响应,记录响应日志

/* * Copyright (c) 2019. zhanghan_java@163.com All Rights Reserved. * 项目名称:实战SpringBoot * 类名称:ResponseLogAdvice.java * 创建人:张晗 * 联系方式:zhanghan_java@163.com * 开源地址: https://github.com/dangnianchuntian/springboot * 博客地址: https://zhanghan.blog.csdn.net */package com.zhanghan.zhboot.aop;import com.zhanghan.zhboot.util.FileBeatLogUtil;import com.zhanghan.zhboot.util.HttpTypeUtil;import com.zhanghan.zhboot.util.JsonUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.MethodParameter;import org.springframework.core.env.Environment;import org.springframework.http.MediaType;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;@ControllerAdvicepublic class ResponseLogAdvice implements ResponseBodyAdvice {    @Autowired    private Environment env;    @Override    public boolean supports(MethodParameter methodParameter, Class aClass) {        return true;    }    @Override    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {        try {            if (o != null) {                Logger log = LoggerFactory.getLogger("logstashInfo");                String applicationName = env.getProperty("spring.application.name");                String responseParams = JsonUtil.objtoJson(o);                String reqName = methodParameter.getDeclaringClass().getName() + "." + methodParameter.getMember().getName();                FileBeatLogUtil.writeLog(log, applicationName, HttpTypeUtil.RESPONSE, reqName, responseParams.toString());            }        } catch (Exception e) {            System.out.println(e.getMessage());        }        return o;    }}

3、日志记录工具类

/* * Copyright (c) 2019. zhanghan_java@163.com All Rights Reserved. * 项目名称:实战SpringBoot * 类名称:FileBeatLogUtil.java * 创建人:张晗 * 联系方式:zhanghan_java@163.com * 开源地址: https://github.com/dangnianchuntian/springboot * 博客地址: https://zhanghan.blog.csdn.net */package com.zhanghan.zhboot.util;import com.alibaba.fastjson.JSON;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.MDC;import org.springframework.util.ObjectUtils;import org.springframework.util.StringUtils;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.text.SimpleDateFormat;import java.util.Date;import java.util.LinkedHashMap;import java.util.UUID;public class FileBeatLogUtil {    public static void writeLog(Logger log, String applicationName, String type, String reqName, String params) {        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request = attributes.getRequest();        String requestURI = request.getRequestURI();        String httpUUID = "";        if (type.equals(HttpTypeUtil.REQUEST)) {            httpUUID = UUID.randomUUID().toString();            request.setAttribute("uuid", httpUUID);        } else {            if (!ObjectUtils.isEmpty( request.getAttribute("uuid"))) {                httpUUID = request.getAttribute("uuid").toString();            }        }        //请求时间        String actionTime = getStringTodayTime();        /**         * 防止MDC值空指针,所有入参不为null         */        applicationName = StringUtils.isEmpty(applicationName) ? "" : applicationName;        requestURI = StringUtils.isEmpty(requestURI) ? "" : requestURI;        reqName = StringUtils.isEmpty(reqName) ? "" : reqName;        params = "null".equals(params) ? "" : params;        actionTime = StringUtils.isEmpty(actionTime) ? "" : actionTime;        /**         * map值为ES备份字符串信息(此字符串不会被ES解析为JSON字符串)         */        LinkedHashMap reqInfo = new LinkedHashMap<>();        reqInfo.put("applicationName", applicationName);        reqInfo.put("requestURI", requestURI);        reqInfo.put("sourceName", reqName);        reqInfo.put("httpUUID", httpUUID);        reqInfo.put("httpType", type);        reqInfo.put("httpParams", params);        reqInfo.put("httpTime", actionTime);        /**         * MDC值为ES键值对JSON信息         */        MDC.put("applicationName", applicationName);        MDC.put("requestURI", requestURI);        MDC.put("sourceName", reqName);        MDC.put("httpUUID", httpUUID);        MDC.put("httpType", type);        MDC.put("httpParams", params);        MDC.put("httpTime", actionTime);        String reqInfoJsonStr = JSON.toJSONString(reqInfo);        log.info(reqInfoJsonStr);    }    /**     * 获取请求参数,处理为json字符串     *     * @param joinPoint     * @return     */    public static String getParams(JoinPoint joinPoint) {        Object[] argValues = joinPoint.getArgs();        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();        LinkedHashMap linkedHashMap = new LinkedHashMap<>();        if (argNames != null && argNames.length > 0) {            for (int i = 0; i < argNames.length; i++) {                String thisArgName = argNames[i];                String thisArgValue = argValues[i].toString();                linkedHashMap.put(thisArgName, thisArgValue);            }        }        return JSON.toJSONString(linkedHashMap);    }    public static String getStringTodayTime() {        Date todat_date = new Date();        //将日期格式化        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");        //转换成字符串格式        return simpleDateFormat.format(todat_date);    }}

4、logback配置xml文件

<?xml version="1.0" encoding="UTF-8"?>%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %green([${LOG_HOME},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]) %magenta(${PID:-}) %white(---) %-20(%yellow([%20.20thread])) %-55(%cyan(%.32logger{30}:%L)) %highlight(- %msg%n)UTF-8${LOG_PATH}/${appName}-log-console-%d{yyyy-MM-dd}.%i.log.zip${maxSaveDays}${maxFileSize}%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %green([${LOG_HOME},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]) %magenta(${PID:-}) %white(---) %-20(%yellow([%20.20thread])) %-55(%cyan(%.32logger{30}:%L)) %highlight(- %msg%n)UTF-8${LOG_PATH}/${appName}-log-info-%d{yyyy-MM-dd}.%i.log.zip${maxSaveDays}${maxFileSize}%d{"yyyy-MM-dd HH:mm:ss,SSS"}[%X{userId}|%X{sessionId}][%p][%c{0}-%M]-%m%nUTF-8ERRORDENYACCEPT${LOG_PATH}/${appName}-log-error-%d{yyyy-MM-dd}.%i.log.zip${maxSaveDays}${maxFileSize}%d{"yyyy-MM-dd HH:mm:ss,SSS"}[%X{userId}|%X{sessionId}][%p][%c{0}-%M]-%m%nUTF-8ERRORACCEPTDENYINFOACCEPTDENY${LOGSTASH_LOG_FILE}${LOGSTASH_LOG_FILE}.%d{yyyy-MM-dd}.gzUTC                        {                        "esindex":"zh-boot-allrequest-log",                        "severity": "%level",                        "service": "${springAppName:-}",                        "trace": "%X{X-B3-TraceId:-}",                        "span": "%X{X-B3-SpanId:-}",                        "parent": "%X{X-B3-ParentSpanId:-}",                        "exportable": "%X{X-Span-Export:-}",                        "pid": "${PID:-}",                        "thread": "%thread",                        "class": "%logger{40}",                        "message": "%message",                        "applicationName" : "%X{applicationName}",                        "requestURI" : "%X{requestURI}",                        "sourceName" : "%X{sourceName}",                        "httpUUID" : "%X{httpUUID}",                        "httpType" : "%X{httpType}",                        "httpParams" : "%X{httpParams}",                        "httpTime" : "%X{httpTime}"                        }                    

5、配置文件中增加日志目录配置

logstash.path=/elklogs/zh-boot-allrequest-log

三、项目部署到虚拟机中:

1、创建项目的目录

mkdir /data/elk/project –p

2、将项目打成zh-boot.jar并通过Xshell拖到刚才创建的目录中

3、启动zh-boot.jar

java -jar  zh-boot.jar
bd12e5983f454a7dac6d592f264c0068

四、访问项目并在Kibina中进行查看:

1、在本地浏览器中访问刚刚部署项目 http://192.168.37.129:8080/swagger-ui.html

3ada9747fb734c39a14787464afadad2

​ 2、在Kibana中创建索引

(1)Create index pattern

484a5a3539004afeaefb062d86f68911

​ (2)Define index pattern

ce1f2cb31dff4e728fbcba6a9ec7edb0

​ (3)Configure settings

699918340bc044b1a9b73794d899830e

​ 3、在Discover中查看项目日志

c724e11aaf1148d2ab79b4210bb947ef

4、Kibana提供了丰富的搜索,下面以httpUUID等于某个值进行查找

(1)设置查找条件

8ea550a332ee428c940a1ce73e81f5c9

(2)查看检索结果

ea2be6f3072b4ae5a1511e6475d0a45d

【总结】

惊不惊喜,意不意外,有没有感觉到日志收集系统的强大,以后线上排查问题再也不用在Linux下用繁杂的命令看,只需在界面上点几下就可以;大大提高了排错效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值