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

   日期:2020-09-11     浏览:163    评论:0    
核心提示:从零学ELK系列(十):SpringBoot项目接入ELK升级版(超详细图文教程)前言之前在《从零学ELK系列(八):SpringBoot项目接入ELK(超详细图文教程)》中演示了SpringBoot项目接入ELK,后来项目中对这部分进行了优化,之前博文中也有读者问到,将优化整理成博文和大家共享;优化前:一次请求记录两条日志(request一条,response一条),通过UUID传连起来优化后:一次请求记录一条日志(request信息与response信息都在一起)目录从零

前言

之前在《从零学ELK系列(八):SpringBoot项目接入ELK(超详细图文教程)》中演示了SpringBoot项目接入ELK,后来项目中对这部分进行了优化,之前博文中也有读者问到,将优化整理成博文和大家共享;

优化前:

  • 一次请求记录两条日志(request一条,response一条),通过UUID传连起来

优化后:

  • 一次请求记录一条日志(request信息与response信息都在一起)

目录

  • 从零学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系列(十):SpringBoot项目接入ELK升级版(超详细图文教程)

架构图&时序图

  • 架构图

  • 程序写入日志时序图

  • ELK收集日志及Kibina查询日志时序图

代码实现

  • 完整代码(GitHub,欢迎大家Star,Fork,Watch)

    https://github.com/dangnianchuntian/springboot

  • 主要代码展示

    • FileBeatLogUtil
    
    
    package com.zhanghan.zhelkboot.util;
    
    import com.alibaba.fastjson.JSON;
    import com.zhanghan.zhelkboot.util.wrapper.Wrapper;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.slf4j.Logger;
    import org.slf4j.MDC;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    public class FileBeatLogUtil {
    
        public static void writeRequestInfo(HttpServletRequest request, String applicationName, String reqName, String requestParams) {
    
            String requestURI = request.getRequestURI();
    
            //获取requestHeader
            Enumeration<String> requestHeaderNames = request.getHeaderNames();
            Map<String, Object> reuestHeaderMap = new HashMap<>();
            while (requestHeaderNames.hasMoreElements()) {
                String name = requestHeaderNames.nextElement();
                String value = request.getHeaders(name).nextElement();
                reuestHeaderMap.put(name, value);
            }
            String requestHeader = "";
            if (null != reuestHeaderMap && reuestHeaderMap.size() > 0) {
                requestHeader = JSON.toJSONString(reuestHeaderMap);
            }
    
            //防止MDC值空指针,所有入参不为null
            applicationName = org.springframework.util.StringUtils.isEmpty(applicationName) ? "" : applicationName;
            requestURI = org.springframework.util.StringUtils.isEmpty(requestURI) ? "" : requestURI;
            reqName = org.springframework.util.StringUtils.isEmpty(reqName) ? "" : reqName;
            requestParams = "null".equals(requestParams) ? "" : requestParams;
    
            //MDC值为ES键值对JSON信息
            MDC.put("applicationName", applicationName);
            MDC.put("requestTime", getStringTodayTime());
            MDC.put("requestURI", requestURI);
            MDC.put("requestHeader", requestHeader);
            MDC.put("sourceName", reqName);
            MDC.put("requestParams", requestParams);
        }
    
        public static void writeResponseLog(Object o, Logger log, HttpServletResponse response) {
    
            //取responseHeader内容
            Map<String, Object> responseHeaderMap = new HashMap<>();
            Collection<String> headerNames = response.getHeaderNames();
            headerNames.forEach(name -> {
                responseHeaderMap.put(name, response.getHeader(name));
            });
            String strResponseHeader = "";
            if (null != responseHeaderMap && responseHeaderMap.size() > 0) {
                strResponseHeader = JSON.toJSONString(responseHeaderMap);
            }
    
            //获取response内容
            String responseCode = "";
            String responseMsg = "";
            String responseBody = "";
            Wrapper wrapper;
            if (null != o) {
                wrapper = (Wrapper) o;
                if (null != wrapper) {
                    responseCode = String.valueOf(wrapper.getCode());
                    responseMsg = wrapper.getMessage();
                    responseBody = wrapper.getResult().toString();
                }
            }
    
    
            //MDC值为ES键值对JSON信息
            MDC.put("responseHeader", strResponseHeader);
            MDC.put("responseCode", responseCode);
            MDC.put("responseMsg", responseMsg);
            MDC.put("responseBody", responseBody);
            MDC.put("responseTime", getStringTodayTime());
    
            Map<String, String> copyOfContextMap = MDC.getCopyOfContextMap();
            String reqInfoJsonStr = JSON.toJSONString(copyOfContextMap);
            log.info(reqInfoJsonStr);
        }
    
        
        public static String getParams(JoinPoint joinPoint) {
            Object[] argValues = joinPoint.getArgs();
            String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
            LinkedHashMap<String, Object> 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);
        }
    }
    
    
    • RequestLogAspectConf
    
    
    package com.zhanghan.zhelkboot.aop;
    
    import com.zhanghan.zhelkboot.util.FileBeatLogUtil;
    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;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Aspect
    @Order(0)
    @Component
    public class RequestLogAspectConf {
    
        @Autowired
        private HttpServletRequest request;
    
        @Autowired
        private Environment env;
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        
        @Pointcut("execution(* com.zhanghan.zhelkboot.controller..*.*(..))")
        public void methodPointCut() {
        }
    
        @Before("methodPointCut()")
        void doBefore(JoinPoint joinPoint) {
            authLogic(joinPoint);
        }
    
        private void authLogic(JoinPoint joinPoint) {
    
            try {
    
                String applicationName = env.getProperty("spring.application.name");
    
                //获取当前http请求
                String reqName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
    
                String requestParams = FileBeatLogUtil.getParams(joinPoint);
    
                FileBeatLogUtil.writeRequestInfo(request, applicationName, reqName, requestParams);
            } catch (Exception e) {
                logger.error("authLogic;Exception:{}", e.getMessage());
            }
    
        }
    
    }
    
    • ResponseLogAdvice
    
    
    package com.zhanghan.zhelkboot.aop;
    
    import com.zhanghan.zhelkboot.util.FileBeatLogUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.MethodParameter;
    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;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    @ControllerAdvice
    public class ResponseLogAdvice implements ResponseBodyAdvice {
    
        @Autowired
        private HttpServletResponse response;
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @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");
    
                    FileBeatLogUtil.writeResponseLog(o, log, response);
    
                }
            } catch (Exception e) {
                logger.error("beforeBodyWrite;Exception:{}", e.getMessage());
            }
            return o;
        }
    
    }
    
    • LombokController
    
    
    package com.zhanghan.zhelkboot.controller;
    
    import com.zhanghan.zhelkboot.controller.request.LombokRequest;
    import com.zhanghan.zhelkboot.util.wrapper.WrapMapper;
    import com.zhanghan.zhelkboot.util.wrapper.Wrapper;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @RestController
    public class LombokController {
    
        private static Logger logger = LoggerFactory.getLogger(LombokController.class);
    
        @RequestMapping(value = "/lombok", method = RequestMethod.POST)
        public Wrapper lombok(@RequestBody LombokRequest lombokRequest) {
    
            logger.info("lombok param {}", lombokRequest.toString());
    
            Map<String, Object> map = new HashMap();
            map.put("intLombok", lombokRequest.getIntLombok());
            map.put("strLombok", lombokRequest.getStrLombok());
            map.put("boleanLombok", lombokRequest.getBoleanLombok());
            map.put("personLombok", lombokRequest.getPersonLombok());
            return WrapMapper.ok(map);
        }
    
    }
    

测试

  • 在服务器上部署并进行请求

  • 在Kibina上进行查看(请求时间,请求内容,响应内容,响应时间)

总结

  • 通过日志收集系统可以对系统进行监控
    • 有助于排错
    • 可以看到每个接口的处理时间,是我们对系统进行优化一个重要参考指标
  • 会持续将生产项目中进行优化同步到本项目中并进行输出
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服