From 939a9120616df94150532703c3653ba6b236fc9f Mon Sep 17 00:00:00 2001 From: makaikai Date: Tue, 2 Aug 2022 21:15:17 +0800 Subject: [PATCH 1/4] add trace log --- src/main/java/org/slf4j/impl/Constant.java | 5 + src/main/java/org/slf4j/impl/MDC.java | 229 ++++++++++++++++++ .../java/org/slf4j/impl/SimpleLogger.java | 9 + .../slf4j/impl/SimpleLoggerConfiguration.java | 2 + src/test/java/com/blade/log/LoggerTest.java | 28 +++ .../resources/application-test.properties | 3 +- src/test/resources/application.properties | 3 +- 7 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/slf4j/impl/MDC.java diff --git a/src/main/java/org/slf4j/impl/Constant.java b/src/main/java/org/slf4j/impl/Constant.java index 32d8955..29cd1ac 100644 --- a/src/main/java/org/slf4j/impl/Constant.java +++ b/src/main/java/org/slf4j/impl/Constant.java @@ -106,6 +106,11 @@ public interface Constant { */ String DISABLE_COLOR = SYSTEM_PREFIX + "disable-color"; + /** + * logger.open-trace-id + */ + String OPEN_TRACE_ID = SYSTEM_PREFIX + "open-trace-id"; + Map LOG_DESC_MAP = new HashMap() { private static final long serialVersionUID = -8216579733086302246L; diff --git a/src/main/java/org/slf4j/impl/MDC.java b/src/main/java/org/slf4j/impl/MDC.java new file mode 100644 index 0000000..7d9268a --- /dev/null +++ b/src/main/java/org/slf4j/impl/MDC.java @@ -0,0 +1,229 @@ +package org.slf4j.impl; + +import org.slf4j.helpers.BasicMDCAdapter; +import org.slf4j.helpers.NOPMDCAdapter; +import org.slf4j.helpers.Util; +import org.slf4j.spi.MDCAdapter; + +import java.io.Closeable; +import java.util.Map; + +/** + * use {@link BasicMDCAdapter} as default {@link MDCAdapter} to save some info + * like trace id ... + * @author makaikai + * @DATE 2022/8/2 + */ +public class MDC { + + + static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA"; + static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder"; + static MDCAdapter mdcAdapter; + + /** + * An adapter to remove the key when done. + */ + public static class MDCCloseable implements Closeable { + private final String key; + + private MDCCloseable(String key) { + this.key = key; + } + + public void close() { + org.slf4j.MDC.remove(this.key); + } + } + + private MDC() { + } + + /** + * 使用@base + * + * @return MDCAdapter + * @throws NoClassDefFoundError in case no binding is available + * @since 1.7.14 + */ + private static MDCAdapter bwCompatibleGetMDCAdapterFromBinder() throws NoClassDefFoundError { + try { + return new BasicMDCAdapter(); + } catch (NoSuchMethodError nsme) { + // binding is probably a version of SLF4J older than 1.7.14 + return StaticMDCBinder.SINGLETON.getMDCA(); + } + } + + static { + try { + mdcAdapter = bwCompatibleGetMDCAdapterFromBinder(); + } catch (NoClassDefFoundError ncde) { + mdcAdapter = new NOPMDCAdapter(); + String msg = ncde.getMessage(); + if (msg != null && msg.contains("StaticMDCBinder")) { + Util.report("Failed to load class \"org.slf4j.impl.StaticMDCBinder\"."); + Util.report("Defaulting to no-operation MDCAdapter implementation."); + Util.report("See " + NO_STATIC_MDC_BINDER_URL + " for further details."); + } else { + throw ncde; + } + } catch (Exception e) { + // we should never get here + Util.report("MDC binding unsuccessful.", e); + } + } + + /** + * Put a diagnostic context value (the val parameter) as identified with the + * key parameter into the current thread's diagnostic context map. The + * key parameter cannot be null. The val parameter + * can be null only if the underlying implementation supports it. + * + *

+ * This method delegates all work to the MDC of the underlying logging system. + * + * @param key non-null key + * @param val value to put in the map + * + * @throws IllegalArgumentException + * in case the "key" parameter is null + */ + public static void put(String key, String val) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("key parameter cannot be null"); + } + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + mdcAdapter.put(key, val); + } + + /** + * Put a diagnostic context value (the val parameter) as identified with the + * key parameter into the current thread's diagnostic context map. The + * key parameter cannot be null. The val parameter + * can be null only if the underlying implementation supports it. + * + *

+ * This method delegates all work to the MDC of the underlying logging system. + *

+ * This method return a Closeable object who can remove key when + * close is called. + * + *

+ * Useful with Java 7 for example : + * + * try(MDC.MDCCloseable closeable = MDC.putCloseable(key, value)) { + * .... + * } + * + * + * @param key non-null key + * @param val value to put in the map + * @return a Closeable who can remove key when close + * is called. + * + * @throws IllegalArgumentException + * in case the "key" parameter is null + */ + public static MDCCloseable putCloseable(String key, String val) throws IllegalArgumentException { + put(key, val); + return new MDCCloseable(key); + } + + /** + * Get the diagnostic context identified by the key parameter. The + * key parameter cannot be null. + * + *

+ * This method delegates all work to the MDC of the underlying logging system. + * + * @param key + * @return the string value identified by the key parameter. + * @throws IllegalArgumentException + * in case the "key" parameter is null + */ + public static String get(String key) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("key parameter cannot be null"); + } + + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + return mdcAdapter.get(key); + } + + /** + * Remove the diagnostic context identified by the key parameter using + * the underlying system's MDC implementation. The key parameter + * cannot be null. This method does nothing if there is no previous value + * associated with key. + * + * @param key + * @throws IllegalArgumentException + * in case the "key" parameter is null + */ + public static void remove(String key) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("key parameter cannot be null"); + } + + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + mdcAdapter.remove(key); + } + + /** + * Clear all entries in the MDC of the underlying implementation. + */ + public static void clear() { + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + mdcAdapter.clear(); + } + + /** + * Return a copy of the current thread's context map, with keys and values of + * type String. Returned value may be null. + * + * @return A copy of the current thread's context map. May be null. + * @since 1.5.1 + */ + public static Map getCopyOfContextMap() { + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + return mdcAdapter.getCopyOfContextMap(); + } + + /** + * Set the current thread's context map by first clearing any existing map and + * then copying the map passed as parameter. The context map passed as + * parameter must only contain keys and values of type String. + * + * @param contextMap + * must contain only keys and values of type String + * @since 1.5.1 + */ + public static void setContextMap(Map contextMap) { + if (mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); + } + mdcAdapter.setContextMap(contextMap); + } + + /** + * Returns the MDCAdapter instance currently in use. + * + * @return the MDcAdapter instance currently in use. + * @since 1.4.2 + */ + public static MDCAdapter getMDCAdapter() { + return mdcAdapter; + } + +} diff --git a/src/main/java/org/slf4j/impl/SimpleLogger.java b/src/main/java/org/slf4j/impl/SimpleLogger.java index cb983b4..7724d4d 100755 --- a/src/main/java/org/slf4j/impl/SimpleLogger.java +++ b/src/main/java/org/slf4j/impl/SimpleLogger.java @@ -260,6 +260,15 @@ private void log(int level, String message, Throwable t) { buf.append(threadName); } + if(CONFIG_PARAMS.openTraceId){ + String traceId = MDC.get("traceId"); + if(null != traceId){ + buf.append("[traceId: "); + buf.append(traceId); + buf.append("] "); + } + } + // Append the name of the impl instance if so configured if (CONFIG_PARAMS.showShortLogName) { if (shortLogName == null) { diff --git a/src/main/java/org/slf4j/impl/SimpleLoggerConfiguration.java b/src/main/java/org/slf4j/impl/SimpleLoggerConfiguration.java index 1119613..e3f8136 100755 --- a/src/main/java/org/slf4j/impl/SimpleLoggerConfiguration.java +++ b/src/main/java/org/slf4j/impl/SimpleLoggerConfiguration.java @@ -38,6 +38,7 @@ public class SimpleLoggerConfiguration { boolean showDateTime = true; boolean showConsole = true; boolean disableColor = false; + boolean openTraceId = false; int defaultLogLevel = SimpleLogger.LOG_LEVEL_INFO; FileRunner fileRunner; @@ -56,6 +57,7 @@ void init() { this.showThreadName = getBoolProp(Constant.SHOW_THREAD_NAME_KEY, showThreadName); this.showConsole = getBoolProp(Constant.SHOW_CONSOLE_KEY, showConsole); this.disableColor = getBoolProp(Constant.DISABLE_COLOR, disableColor); + this.openTraceId = getBoolProp(OPEN_TRACE_ID,openTraceId); String dateTimeFormatStr = getStringProp(Constant.DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR_DEFAULT); this.levelInBrackets = getBoolProp(Constant.LEVEL_IN_BRACKETS_KEY, levelInBrackets); diff --git a/src/test/java/com/blade/log/LoggerTest.java b/src/test/java/com/blade/log/LoggerTest.java index 5a5b1dd..bb146a7 100644 --- a/src/test/java/com/blade/log/LoggerTest.java +++ b/src/test/java/com/blade/log/LoggerTest.java @@ -2,7 +2,12 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Test; +import org.slf4j.impl.MDC; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** @@ -40,4 +45,27 @@ public void testError() { } } + + @Test + public void testMDCLog() throws InterruptedException { + log.info("Hello World"); + MDC.put("traceId", UUID.randomUUID().toString()); + + new Thread(()->{ + log.info("Thread ,test traceId"); + }).start(); + + Executors.newFixedThreadPool(1).execute(()->{ + log.info("newFixedThreadPool,test traceId"); + }); + + CompletableFuture.runAsync(()->{ + log.info("CompletableFuture ,test traceId"); + }).join(); + + TimeUnit.SECONDS.sleep(10); + MDC.clear(); + log.info("Hello World"); + + } } diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties index 6222303..84c4de2 100644 --- a/src/test/resources/application-test.properties +++ b/src/test/resources/application-test.properties @@ -1,4 +1,5 @@ com.blade.logger.rootLevel=error com.blade.logger.dir=./logs com.blade.logger.name=app -com.blade.logger.console=false \ No newline at end of file +com.blade.logger.console=false +logger.open-trace-id=true \ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index dc22039..792750a 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,4 +1,5 @@ logger.root-level=debug logger.dir=./logs logger.name=app -logger.console=true \ No newline at end of file +logger.console=true +logger.open-trace-id = true \ No newline at end of file From 737f0f2a2d60a3ff20e3252b001afad382ff2ca0 Mon Sep 17 00:00:00 2001 From: makaikai Date: Tue, 2 Aug 2022 21:40:13 +0800 Subject: [PATCH 2/4] add multithreading test --- src/test/java/com/blade/log/LoggerTest.java | 43 ++++++++++++++------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/blade/log/LoggerTest.java b/src/test/java/com/blade/log/LoggerTest.java index bb146a7..76c24a9 100644 --- a/src/test/java/com/blade/log/LoggerTest.java +++ b/src/test/java/com/blade/log/LoggerTest.java @@ -48,24 +48,39 @@ public void testError() { @Test public void testMDCLog() throws InterruptedException { - log.info("Hello World"); - MDC.put("traceId", UUID.randomUUID().toString()); - new Thread(()->{ - log.info("Thread ,test traceId"); - }).start(); + ExecutorService executorService = Executors.newFixedThreadPool(3); + executorService.execute(this::testMDCLogAsyn); + executorService.execute(this::testMDCLogAsyn); + TimeUnit.SECONDS.sleep(10); + System.out.println("over"); + } - Executors.newFixedThreadPool(1).execute(()->{ - log.info("newFixedThreadPool,test traceId"); - }); + private void testMDCLogAsyn() { + try { - CompletableFuture.runAsync(()->{ - log.info("CompletableFuture ,test traceId"); - }).join(); + log.info("Hello World"); + MDC.put("traceId", UUID.randomUUID().toString()); + + new Thread(()->{ + log.info("Thread ,test traceId"); + }).start(); + + Executors.newFixedThreadPool(1).execute(()->{ + log.info("newFixedThreadPool,test traceId"); + }); + + CompletableFuture.runAsync(()->{ + log.info("CompletableFuture ,test traceId"); + }).join(); + + TimeUnit.SECONDS.sleep(5); + MDC.clear(); + log.info("Hello World"); + }catch (Exception e){ + log.error("eee", e); + } - TimeUnit.SECONDS.sleep(10); - MDC.clear(); - log.info("Hello World"); } } From 91e6fa97597214eac1c74d74b792192747c85520 Mon Sep 17 00:00:00 2001 From: makaikai Date: Tue, 2 Aug 2022 21:44:40 +0800 Subject: [PATCH 3/4] mod method name --- src/test/java/com/blade/log/LoggerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/blade/log/LoggerTest.java b/src/test/java/com/blade/log/LoggerTest.java index 76c24a9..81eb6c6 100644 --- a/src/test/java/com/blade/log/LoggerTest.java +++ b/src/test/java/com/blade/log/LoggerTest.java @@ -50,13 +50,13 @@ public void testError() { public void testMDCLog() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(3); - executorService.execute(this::testMDCLogAsyn); - executorService.execute(this::testMDCLogAsyn); + executorService.execute(this::testMDCLogAsync); + executorService.execute(this::testMDCLogAsync); TimeUnit.SECONDS.sleep(10); System.out.println("over"); } - private void testMDCLogAsyn() { + private void testMDCLogAsync() { try { log.info("Hello World"); From 7f96a073462198d2434c5bb20f298c74ad1269e0 Mon Sep 17 00:00:00 2001 From: makaikai Date: Tue, 2 Aug 2022 21:51:43 +0800 Subject: [PATCH 4/4] add annotation --- src/main/java/org/slf4j/impl/MDC.java | 2 +- src/test/java/com/blade/log/LoggerTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/slf4j/impl/MDC.java b/src/main/java/org/slf4j/impl/MDC.java index 7d9268a..efa5a2b 100644 --- a/src/main/java/org/slf4j/impl/MDC.java +++ b/src/main/java/org/slf4j/impl/MDC.java @@ -40,7 +40,7 @@ private MDC() { } /** - * 使用@base + * 使用{@link BasicMDCAdapter} 作为默认的MDCAdapter * * @return MDCAdapter * @throws NoClassDefFoundError in case no binding is available diff --git a/src/test/java/com/blade/log/LoggerTest.java b/src/test/java/com/blade/log/LoggerTest.java index 81eb6c6..d040074 100644 --- a/src/test/java/com/blade/log/LoggerTest.java +++ b/src/test/java/com/blade/log/LoggerTest.java @@ -62,22 +62,22 @@ private void testMDCLogAsync() { log.info("Hello World"); MDC.put("traceId", UUID.randomUUID().toString()); - new Thread(()->{ + new Thread(() -> { log.info("Thread ,test traceId"); }).start(); - Executors.newFixedThreadPool(1).execute(()->{ + Executors.newFixedThreadPool(1).execute(() -> { log.info("newFixedThreadPool,test traceId"); }); - CompletableFuture.runAsync(()->{ + CompletableFuture.runAsync(() -> { log.info("CompletableFuture ,test traceId"); }).join(); TimeUnit.SECONDS.sleep(5); MDC.clear(); log.info("Hello World"); - }catch (Exception e){ + } catch (Exception e) { log.error("eee", e); }