核心内容摘要
久久内射明星换脸技术揭秘:从AI幻象到虚拟现实的终极跨越
前言从文章标题就知道这篇文章是介绍些什么。
这是我一位朋友的问题反馈图片好像是的确实这种现象是普遍存在的。
有时候一个业务调用链场景很长调了各种各样的方法看日志的时候各个接口的日志穿插确实让人头大。
模糊匹配搜索日志能解决吗 能解决一点点。
但是不能完全呈现出整个链路相关的日志。
那要做到方便很显然我们需要的是把同一次的业务调用链上的日志串起来。
什么效果 先看一个实现后的效果图图片这样下来我们再配合模糊匹配查找日志效果不就刚刚的了。
cat -n info.log |grep a415ad50dbf84e99b1b56a31aacd209c或者grep -10 a415ad50dbf84e99b1b56a31aacd209c info.log 10是指上下10行不多说开整。
正文惯例先看一眼这次实战最终工程的结构图片①pom.xml 依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-logging/artifactId /dependency !--lombok配置-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version
1.
1
10/version /dependency /dependencies②整合logback打印日志logback-spring.xml (简单配置下)?xml version
0 encodingUTF-8? configuration debugfalse !--日志存储路径-- property namelog valueD:/test/log / !-- 控制台输出 -- appender nameconsole classch.qos.logback.core.ConsoleAppender encoder classch.qos.logback.classic.encoder.PatternLayoutEncoder !--输出格式化-- pattern[%X{TRACE_ID}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern /encoder /appender !-- 按天生成日志文件 -- appender namefile classch.qos.logback.core.rolling.RollingFileAppender rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy !--日志文件名-- FileNamePattern${log}/%d{yyyy-MM-dd}.log/FileNamePattern !--保留天数-- MaxHistory30/MaxHistory /rollingPolicy encoder classch.qos.logback.classic.encoder.PatternLayoutEncoder pattern[%X{TRACE_ID}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern /encoder !--日志文件最大的大小-- triggeringPolicy classch.qos.logback.core.rolling.SizeBasedTriggeringPolicy MaxFileSize10MB/MaxFileSize /triggeringPolicy /appender !-- 日志输出级别 -- root levelINFO appender-ref refconsole / appender-ref reffile / /root /configurationapplication.ymlserver: port: 8826 logging: config: classpath:logback-spring.xml③自定义日志拦截器 LogInterceptor.java用途每一次链路线程维度添加最终的链路ID TRACE_ID。
import org.slf4j.MDC; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.UUID; /** * Author: JCccc * Date:
10:45 * Description: */ publicclass LogInterceptor implements HandlerInterceptor { privatestaticfinal String TRACE_ID TRACE_ID; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String tid UUID.randomUUID().toString().replace(-, ); //可以考虑让客户端传入链路ID但需保证一定的复杂度唯一性如果没使用默认UUID自动生成 if (!StringUtils.isEmpty(request.getHeader(TRACE_ID))){ tidrequest.getHeader(TRACE_ID); } MDC.put(TRACE_ID, tid); returntrue; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Nullable Exception ex) { MDC.remove(TRACE_ID); } }MDC(Mapped Diagnostic Context)诊断上下文映射是Slf4j提供的一个支持动态打印日志信息的工具。
WebConfigurerAdapter.java 添加拦截器import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * Author: JCccc * Date:
10:47 * Description: */ Configuration publicclass WebConfigurerAdapter implements WebMvcConfigurer { Bean public LogInterceptor logInterceptor() { returnnew LogInterceptor(); } Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(logInterceptor()); //可以具体制定哪些需要拦截哪些不拦截其实也可以使用自定义注解更灵活完成 // .addPathPatterns(/**) // .excludePathPatterns(/testxx.html); } }ps: 其实这个拦截的部分改为使用自定义注解aop也是很灵活的。
到这时候其实已经完成就是这么简单。
我们写个测试接口看下效果PostMapping(doTest) public String doTest(RequestParam(name) String name) throws InterruptedException { log.info(入参 name{},name); testTrace(); log.info(调用结束 name{},name); returnHello,name; } private void testTrace(){ log.info(这是一行info日志); log.error(这是一行error日志); testTrace2(); } private void testTrace2(){ log.info(这也是一行info日志); }效果OK的图片还没完。
接下来看一个场景 使用子线程的场景故意写一个异步线程加入这个调用里面图片再次执行看开效果显然子线程丢失了trackId图片所以我们需要针对子线程使用情形做调整思路 将父线程的trackId传递下去给子线程即可。
①ThreadPoolConfig.java 定义线程池交给spring管理import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import java.util.concurrent.Executor; /** * Author: JCccc * Date: