–“平凡的我们生活在这个不平凡的世界,即使生活很苦,但我们依旧热爱生活”
--《平凡的世界》
概述
当我们的日志达到一定数量级的时候我们怎么查看,分析日志?打开日志慢慢找?别扯了。ELK能够实现日志过滤,分析?接下来将进行介绍。
首先看图说话
然后一步一步来
因为我引用了视频spring cloud sleuth,所以会带有16位的traceId,由于我需要32位,所有我自己生成了traceId,如若不需要刻意参考后面配置直接使用MDC在全局变量中取
网关拦截http请求,生成traceId,并添加到header
@Component
public class HttpFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求
ServerHttpRequest request = exchange.getRequest();
//获取uuid
String traceId = UUIDUtil.getUUID();
MDC.put("traceId",traceId);
//添加请求头
ServerHttpRequest addHeader = request.mutate().header("traceId",traceId).build();
ServerWebExchange build = exchange.mutate().request(addHeader).build();
return chain.filter(build);
}
@Override
public int getOrder() {
return 0;
}
}
UUIDUtil是获取uuid的一个工具,自己写的时候换掉,自己生成一个uuid即可。
下游服务接受traceId:
- 不调用其他服务
首先拦截请求获取traceId
@Component
public class TraceInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String traceId = request.getHeader("traceId");
if (StringUtil.isNotNullOrEmpty(traceId)) {
MDC.put("traceId", traceId);
}
return true;
}
}
添加拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TraceInterceptor()).addPathPatterns("/**");
}
}
在日志文件中添加%X{traceId},添加traceId到日志
<PatternLayout>
<pattern>[%-5p] %d %c %l -[%X{traceId}] - %m%n</pattern>
</PatternLayout>
- 调用其他服务
通过openfeign调用其他服务,不了解openfeign的可以查看其他资料
@Configuration
public class FeignInterceptorConfig {
/**
* <p>方法描述:feign日志等级 </p >
* @author zlh
* @since 2019/9/17 14:56
* @return
*/
@Bean
Logger.Level feignLevel() {
return Logger.Level.BASIC;
}
/**
* <p>方法描述:feign传递traceId </p >
* @author zlh
* @since 2019/9/17 14:56
* @return
*/
@Bean
public RequestInterceptor requestInterceptor() {
RequestInterceptor requestInterceptor = template -> {
//传递日志traceId
String traceId = MDC.get("traceId");
template.header("traceId", traceId);
};
return requestInterceptor;
}
/**
* <p>方法描述:添加info级别feign日志 </p >
* @author zlh
* @since 2019/9/17 14:57
* @return
*/
@Bean
Logger FeignLog(){
return new FeignLogger();
}
}
里面多了两个方法,自己看需不需要,由于feign默认是不开启日志的,需要到配置开启。feign的日志级别
- NONE,无记录(DEFAULT)。
- BASIC,只记录请求方法和URL以及响应状态代码和执行时间。
- HEADERS,记录基本信息以及请求和响应标头。
- FULL,记录请求和响应的头文件,正文和元数据。
默认是NONE,需要什么级别自己改
然后配置文件添加配置
logging:
level:
com.byb.consumer: info
默认是debug,由于一般都是info级别的日志,所以我重写了feign的日志,如果不需要直接改成debug即可,这里的logger是slf4j的,不要导错包
public class FeignLogger extends feign.Logger {
Logger logger;
public FeignLogger() {
this(feign.Logger.class);
}
public FeignLogger(Class<?> clazz) {
this(LoggerFactory.getLogger(clazz));
}
public FeignLogger(String name) {
this(LoggerFactory.getLogger(name));
}
FeignLogger(Logger logger) {
this.logger = logger;
}
/**
* <p>方法描述:打印请求日志 </p >
* @author zlh
* @return
*/
@Override
protected void logRequest(String configKey, Level logLevel, Request request) {
if (logger.isInfoEnabled()) {
super.logRequest(configKey, logLevel, request);
}
}
/**
* <p>方法描述:打印响应日志 </p >
* @author zlh
* @return
*/
@Override
protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
throws IOException {
if (logger.isInfoEnabled()) {
return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
}
return response;
}
/**
* <p>方法描述:打印log日志 </p >
* @author zlh
* @return
*/
@Override
protected void log(String configKey, String format, Object... args) {
if (logger.isInfoEnabled()) {
logger.info(String.format(methodTag(configKey) + format, args));
}
}
}
然后在feign配置类里面添加这个类即可,上面代码中已经添加。
不了解MDC的可以去了解一下,我感觉就是一个存储全局变量的(匹夫之见),还有一个NDC,也可以学学
拦截器和普通的一样,直接使用上面的即可。
注意:MDC底层使用ThreadContext封装了对ThreadLocal的操作,所有需要我们在日志打印之后对其进行remove,也就是在上面的打印日志类中,直接获取全集MDC的traceId然后删除(MDC.remove(“traceId”))
代码大概就只这样,截取一段日志信息
[INFO ] 2019-09-16 02:10:26,858 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[48ac57d0-a6a6-4393-92b4-b62927a1476c] - [TestFeign#testFn1] ---> GET http://ts-provider1/test1 HTTP/1.1
[INFO ] 2019-09-16 02:10:26,859 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[867536eb-3180-477b-84b8-0fb2cc6715d9] - [TestFeign#testFn1] ---> GET http://ts-provider1/test1 HTTP/1.1
[INFO ] 2019-09-16 02:10:26,859 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[3154b819-7fdf-48bc-9fd2-3486125677c4] - [TestFeign#testFn1] ---> GET http://ts-provider1/test1 HTTP/1.1
[INFO ] 2019-09-16 02:10:26,860 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[4b876b06-d8d3-4824-9006-042b5cf2bb13] - [TestFeign#testFn1] <--- HTTP/1.1 200 (5ms)
[INFO ] 2019-09-16 02:10:26,860 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[c5cd5407-7ccc-436e-8471-487afc315651] - [TestFeign#testFn1] <--- HTTP/1.1 200 (6ms)
[INFO ] 2019-09-16 02:10:26,864 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[3154b819-7fdf-48bc-9fd2-3486125677c4] - [TestFeign#testFn1] <--- HTTP/1.1 200 (4ms)
[INFO ] 2019-09-16 02:10:26,864 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[48ac57d0-a6a6-4393-92b4-b62927a1476c] - [TestFeign#testFn1] <--- HTTP/1.1 200 (5ms)
[INFO ] 2019-09-16 02:10:26,865 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[867536eb-3180-477b-84b8-0fb2cc6715d9] - [TestFeign#testFn1] <--- HTTP/1.1 200 (5ms)
[INFO ] 2019-09-16 02:10:26,871 feign.Logger com.byb.consumer.config.FeignLogger.log(FeignLogger.java:51) -[a9d63f1f-f27f-48b4-a4c7-99626b5ff5e4] - [TestFeign#testFn1] ---> GET http://ts-provider1/test1 HTTP/1.1
调一次打印两条日志。
既然你已看见这篇博客证明你的ELK已经搭建成功,不管是tcp发送还是收集日志文件,我们都要对日志进行过滤,分析
过滤参考我的博客:https://blog.csdn.net/zlhmeng/article/details/101449700
界面分析参考我的博客: