Bagaimana untuk melaksanakan pengelogan dalam CompletableFuture di Java
1. Mula-mula gunakan aop untuk menambah requestId pada semua entri permintaan.
@Aspect @Component public class LoggingAspect { /** * AOP注解的Controller类方法必须为 public 或 protect ,千万不能用private!!!!!!!!否则会@Autowired注入的service会报空指针异常。 * 私有方法和字段不属于Spring上下文中的bean属性。 */ @Around("@annotation(org.springframework.web.bind.annotation.GetMapping) || " + "@annotation(org.springframework.web.bind.annotation.PostMapping) || " + "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { // 在logback-spring.xml里对应%X{requestId} MDC.put("requestId", UUID.randomUUID().toString().substring(0, 13)); // Add request ID to MDC try { return joinPoint.proceed(); // Execute method } finally { MDC.remove("requestId"); // Remove request ID from MDC } } }
2. Tentukan logback-spring.xml dan perkenalkan requestId untuk rakaman pautan Kod utama ialah %X{requestId}
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 控制台日志格式 --> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %X{requestId} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <!-- 控制台日志格式 依赖的渲染类 --> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <!-- 输出到控制台 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <!-- 配置日志输出格式 --> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <!-- 使用的字符集 --> <charset>UTF-8</charset> </encoder> </appender> <!-- 定义输出的路径,获取application.yml的source的值 --> <springProperty scope="context" name="LOG_FILE_PATH" source="logging.file-location" default="/var/log/myapp"/> <!-- 2.输出到文件 --> <!-- 2.1 level为 DEBUG 日志,时间滚动输出 --> <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE_PATH}/debug.log</file> <!-- 文件路径 --> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n</pattern><!-- 日志文档输出格式 --> <charset>UTF-8</charset> </encoder> <!-- 日志记录器的滚动策略,按日期,按大小记录 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 每天新开一个文件 --> <fileNamePattern>${LOG_FILE_PATH}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 每天100m新开一个文件 --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!-- 日志文档保留天数 --> <maxHistory>15</maxHistory> <!-- 用来指定日志文件的上限大小,例如设置为1GB的话,那么到了这个值,就会删除旧的日志。 --> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <!-- 此日志文档只记录debug级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>debug</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.2 level为 INFO 日志,时间滚动输出 --> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE_PATH}/info.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE_PATH}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文档只记录info级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>info</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.3 level为 WARN 日志,时间滚动输出 --> <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE_PATH}/warn.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE_PATH}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文档只记录warn级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>warn</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.4 level为 ERROR 日志,时间滚动输出 --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE_PATH}/error.log</file> <!--日志文档输出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{requestId} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE_PATH}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文档只记录ERROR级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 使用异步,一个AsyncAppender只能添加一个appender-ref --> <appender name="ASYNC_DEBUG_FILE" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="DEBUG_FILE"/> </appender> <appender name="ASYNC_INFO_FILE" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="INFO_FILE"/> </appender> <appender name="ASYNC_WARN_FILE" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="WARN_FILE"/> </appender> <appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="ERROR_FILE"/> </appender> <!-- 开启上面的appender --> <root level="info"> <appender-ref ref="CONSOLE" /> <appender-ref ref="ASYNC_DEBUG_FILE" /> <appender-ref ref="ASYNC_INFO_FILE" /> <appender-ref ref="ASYNC_WARN_FILE" /> <appender-ref ref="ASYNC_ERROR_FILE" /> </root> </configuration>
2 lihat kekuatan log
private final ExecutorService executorService = Executors.newFixedThreadPool(4); @GetMapping("saveUser") public String saveUser() { log.info("进入了saveUser"); // 异步 CompletableFuture.runAsync(()-> b(), executorService); log.info("退出了saveUser"); return "Ok"; } private void b() { log.info("进入了b"); }
Lognya adalah seperti berikut sesuaikan kelas urutan untuk menyimpan konteks MDC
3. Tentukan kelas pelaksanaan thread dan simpan MDC konteks dalam pembina2023-04-19 11:51:59.309 21dbaad3-3158 INFO 23044 --- [p-nio-80-exec-1] c.h.m. api.CompletableFutureApi : Memasukkan saveUser
2023-04 -19 11:51:59.312 21dbaad3-3158 INFO 23044 --- [p-nio-80-exec-1] c.h.m.api.CompletableFutureApiser>2: 04-19 11:51:59.312 INFO 23 044 - -- [pool-1-thread-1] c.h.m.api.CompletableFutureApi : Dimasukkan b
public static class MdcTaskWrapper implements Runnable { private final Runnable task; private final Map<String, String> contextMap; public MdcTaskWrapper(Runnable task) { this.task = task; this.contextMap = MDC.getCopyOfContextMap(); } @Override public void run() { if (contextMap != null) { MDC.setContextMap(contextMap); } try { task.run(); } finally { MDC.clear(); } } }
2023-04-19 11:58:27.581 4ab037ab-9816 -INFO-6816 - [p-nio-80-exec-5] c.h.m. api.CompletableFutureApi : Memasukkan saveUser
2023-04-19 11:58:27.582 4ab037ab-92cb INFO 6816 --- [p-nio-80-exec ] c.h.m.api.CompletableFutureApi : Exited saveUser2023-04-19 11:58:27.582 4ab037ab-92cb INFO 6816 --- [pool-1-thread-1] c.h.m.apiture.Api🜎>
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan pengelogan dalam CompletableFuture di Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Spring Boot memudahkan penciptaan aplikasi Java yang mantap, berskala, dan siap pengeluaran, merevolusi pembangunan Java. Pendekatan "Konvensyen Lebih Konfigurasi", yang wujud pada ekosistem musim bunga, meminimumkan persediaan manual, Allo
