From 4236f0bc123c417146e4fa989c30711be7da8a2e Mon Sep 17 00:00:00 2001 From: suntaiming Date: Mon, 22 Jan 2024 09:20:28 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A4=8D=E5=86=99Log4jLogger=EF=BC=8C?= =?UTF-8?q?=E9=80=82=E9=85=8Dstatic=20final=E4=BF=AE=E9=A5=B0=E7=9A=84Logg?= =?UTF-8?q?er=E4=BD=BF=E7=94=A8=E6=83=85=E5=86=B5=EF=BC=8C=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E5=BD=93=E5=89=8D=E7=BA=BF=E7=A8=8B=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E7=B1=BB=E5=8A=A0=E8=BD=BD=E5=99=A8=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=8E=B7=E5=8F=96Logger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/logging/slf4j/Log4jLogger.java | 460 ++++++++++++++++++ 1 file changed, 460 insertions(+) create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java new file mode 100644 index 000000000..d4c8235fe --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java @@ -0,0 +1,460 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.slf4j; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.apache.logging.log4j.message.SimpleMessage; +import org.apache.logging.log4j.spi.ExtendedLogger; +import org.apache.logging.log4j.spi.LoggerContext; +import org.apache.logging.log4j.util.LoaderUtil; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; +import org.slf4j.impl.StaticMarkerBinder; +import org.slf4j.spi.LocationAwareLogger; + +/** + * SLF4J logger implementation that uses Log4j. + */ +public class Log4jLogger implements LocationAwareLogger, Serializable { + + public static final String FQCN = Log4jLogger.class.getName(); + + private static final long serialVersionUID = 7869000638091304316L; + private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT"); + private static final EventDataConverter CONVERTER = createConverter(); + + private final boolean eventLogger; + private transient final Map loggerMap = new ConcurrentHashMap<>(); + private static final Map LOGGER_CONTEXT_MAP = new ConcurrentHashMap<>(); + private final String name; + + public Log4jLogger(final ExtendedLogger logger, final String name) { + this.eventLogger = "EventLogger".equals(name); + this.name = name; + } + + @Override + public void trace(final String format) { + getLogger().logIfEnabled(FQCN, Level.TRACE, null, format); + } + + @Override + public void trace(final String format, final Object o) { + getLogger().logIfEnabled(FQCN, Level.TRACE, null, format, o); + } + + @Override + public void trace(final String format, final Object arg1, final Object arg2) { + getLogger().logIfEnabled(FQCN, Level.TRACE, null, format, arg1, arg2); + } + + @Override + public void trace(final String format, final Object... args) { + getLogger().logIfEnabled(FQCN, Level.TRACE, null, format, args); + } + + @Override + public void trace(final String format, final Throwable t) { + getLogger().logIfEnabled(FQCN, Level.TRACE, null, format, t); + } + + @Override + public boolean isTraceEnabled() { + return getLogger().isEnabled(Level.TRACE, null, null); + } + + @Override + public boolean isTraceEnabled(final Marker marker) { + return getLogger().isEnabled(Level.TRACE, getMarker(marker), null); + } + + @Override + public void trace(final Marker marker, final String s) { + getLogger().logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s); + } + + @Override + public void trace(final Marker marker, final String s, final Object o) { + getLogger().logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o); + } + + @Override + public void trace(final Marker marker, final String s, final Object o, final Object o1) { + getLogger().logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o, o1); + } + + @Override + public void trace(final Marker marker, final String s, final Object... objects) { + getLogger().logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, objects); + } + + @Override + public void trace(final Marker marker, final String s, final Throwable throwable) { + getLogger().logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, throwable); + } + + @Override + public void debug(final String format) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, null, format); + } + + @Override + public void debug(final String format, final Object o) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, null, format, o); + } + + @Override + public void debug(final String format, final Object arg1, final Object arg2) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, null, format, arg1, arg2); + } + + @Override + public void debug(final String format, final Object... args) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, null, format, args); + } + + @Override + public void debug(final String format, final Throwable t) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, null, format, t); + } + + @Override + public boolean isDebugEnabled() { + return getLogger().isEnabled(Level.DEBUG, null, null); + } + + @Override + public boolean isDebugEnabled(final Marker marker) { + return getLogger().isEnabled(Level.DEBUG, getMarker(marker), null); + } + + @Override + public void debug(final Marker marker, final String s) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s); + } + + @Override + public void debug(final Marker marker, final String s, final Object o) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o); + } + + @Override + public void debug(final Marker marker, final String s, final Object o, final Object o1) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o, o1); + } + + @Override + public void debug(final Marker marker, final String s, final Object... objects) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, objects); + } + + @Override + public void debug(final Marker marker, final String s, final Throwable throwable) { + getLogger().logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, throwable); + } + + @Override + public void info(final String format) { + getLogger().logIfEnabled(FQCN, Level.INFO, null, format); + } + + @Override + public void info(final String format, final Object o) { + getLogger().logIfEnabled(FQCN, Level.INFO, null, format, o); + } + + @Override + public void info(final String format, final Object arg1, final Object arg2) { + getLogger().logIfEnabled(FQCN, Level.INFO, null, format, arg1, arg2); + } + + @Override + public void info(final String format, final Object... args) { + getLogger().logIfEnabled(FQCN, Level.INFO, null, format, args); + } + + @Override + public void info(final String format, final Throwable t) { + getLogger().logIfEnabled(FQCN, Level.INFO, null, format, t); + } + + @Override + public boolean isInfoEnabled() { + return getLogger().isEnabled(Level.INFO, null, null); + } + + @Override + public boolean isInfoEnabled(final Marker marker) { + return getLogger().isEnabled(Level.INFO, getMarker(marker), null); + } + + @Override + public void info(final Marker marker, final String s) { + getLogger().logIfEnabled(FQCN, Level.INFO, getMarker(marker), s); + } + + @Override + public void info(final Marker marker, final String s, final Object o) { + getLogger().logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o); + } + + @Override + public void info(final Marker marker, final String s, final Object o, final Object o1) { + getLogger().logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o, o1); + } + + @Override + public void info(final Marker marker, final String s, final Object... objects) { + getLogger().logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, objects); + } + + @Override + public void info(final Marker marker, final String s, final Throwable throwable) { + getLogger().logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, throwable); + } + + @Override + public void warn(final String format) { + getLogger().logIfEnabled(FQCN, Level.WARN, null, format); + } + + @Override + public void warn(final String format, final Object o) { + getLogger().logIfEnabled(FQCN, Level.WARN, null, format, o); + } + + @Override + public void warn(final String format, final Object arg1, final Object arg2) { + getLogger().logIfEnabled(FQCN, Level.WARN, null, format, arg1, arg2); + } + + @Override + public void warn(final String format, final Object... args) { + getLogger().logIfEnabled(FQCN, Level.WARN, null, format, args); + } + + @Override + public void warn(final String format, final Throwable t) { + getLogger().logIfEnabled(FQCN, Level.WARN, null, format, t); + } + + @Override + public boolean isWarnEnabled() { + return getLogger().isEnabled(Level.WARN, null, null); + } + + @Override + public boolean isWarnEnabled(final Marker marker) { + return getLogger().isEnabled(Level.WARN, getMarker(marker), null); + } + + @Override + public void warn(final Marker marker, final String s) { + getLogger().logIfEnabled(FQCN, Level.WARN, getMarker(marker), s); + } + + @Override + public void warn(final Marker marker, final String s, final Object o) { + getLogger().logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o); + } + + @Override + public void warn(final Marker marker, final String s, final Object o, final Object o1) { + getLogger().logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o, o1); + } + + @Override + public void warn(final Marker marker, final String s, final Object... objects) { + getLogger().logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, objects); + } + + @Override + public void warn(final Marker marker, final String s, final Throwable throwable) { + getLogger().logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, throwable); + } + + @Override + public void error(final String format) { + getLogger().logIfEnabled(FQCN, Level.ERROR, null, format); + } + + @Override + public void error(final String format, final Object o) { + getLogger().logIfEnabled(FQCN, Level.ERROR, null, format, o); + } + + @Override + public void error(final String format, final Object arg1, final Object arg2) { + getLogger().logIfEnabled(FQCN, Level.ERROR, null, format, arg1, arg2); + } + + @Override + public void error(final String format, final Object... args) { + getLogger().logIfEnabled(FQCN, Level.ERROR, null, format, args); + } + + @Override + public void error(final String format, final Throwable t) { + getLogger().logIfEnabled(FQCN, Level.ERROR, null, format, t); + } + + @Override + public boolean isErrorEnabled() { + return getLogger().isEnabled(Level.ERROR, null, null); + } + + @Override + public boolean isErrorEnabled(final Marker marker) { + return getLogger().isEnabled(Level.ERROR, getMarker(marker), null); + } + + @Override + public void error(final Marker marker, final String s) { + getLogger().logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s); + } + + @Override + public void error(final Marker marker, final String s, final Object o) { + getLogger().logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o); + } + + @Override + public void error(final Marker marker, final String s, final Object o, final Object o1) { + getLogger().logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o, o1); + } + + @Override + public void error(final Marker marker, final String s, final Object... objects) { + getLogger().logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, objects); + } + + @Override + public void error(final Marker marker, final String s, final Throwable throwable) { + getLogger().logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, throwable); + } + + @Override + public void log(final Marker marker, final String fqcn, final int level, final String message, final Object[] params, Throwable throwable) { + final Level log4jLevel = getLevel(level); + final org.apache.logging.log4j.Marker log4jMarker = getMarker(marker); + ExtendedLogger logger = getLogger(); + + if (!logger.isEnabled(log4jLevel, log4jMarker, message, params)) { + return; + } + final Message msg; + if (CONVERTER != null && eventLogger && marker != null && marker.contains(EVENT_MARKER)) { + msg = CONVERTER.convertEvent(message, params, throwable); + } else if (params == null) { + msg = new SimpleMessage(message); + } else { + msg = new ParameterizedMessage(message, params, throwable); + if (throwable != null) { + throwable = msg.getThrowable(); + } + } + logger.logMessage(fqcn, log4jLevel, log4jMarker, msg, throwable); + } + + private static org.apache.logging.log4j.Marker getMarker(final Marker marker) { + if (marker == null) { + return null; + } else if (marker instanceof Log4jMarker) { + return ((Log4jMarker) marker).getLog4jMarker(); + } else { + final Log4jMarkerFactory factory = (Log4jMarkerFactory) StaticMarkerBinder.SINGLETON.getMarkerFactory(); + return ((Log4jMarker) factory.getMarker(marker)).getLog4jMarker(); + } + } + + @Override + public String getName() { + return name; + } + + /** + * Always treat de-serialization as a full-blown constructor, by validating the final state of + * the de-serialized object. + */ + private void readObject(final ObjectInputStream aInputStream) throws ClassNotFoundException, IOException { + // always perform the default de-serialization first + aInputStream.defaultReadObject(); + } + + /** + * This is the default implementation of writeObject. Customise if necessary. + */ + private void writeObject(final ObjectOutputStream aOutputStream) throws IOException { + // perform the default serialization for all non-transient, non-static fields + aOutputStream.defaultWriteObject(); + } + + private static EventDataConverter createConverter() { + try { + LoaderUtil.loadClass("org.slf4j.ext.EventData"); + return new EventDataConverter(); + } catch (final ClassNotFoundException cnfe) { + return null; + } + } + + private static Level getLevel(final int i) { + switch (i) { + case TRACE_INT: + return Level.TRACE; + case DEBUG_INT: + return Level.DEBUG; + case INFO_INT: + return Level.INFO; + case WARN_INT: + return Level.WARN; + case ERROR_INT: + return Level.ERROR; + } + return Level.ERROR; + } + + /** + * 根据当前线程上下文类加载器获取logger + * + * @return ExtendedLogger + */ + private ExtendedLogger getLogger() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + LoggerContext loggerContext = LOGGER_CONTEXT_MAP.get(classLoader); + if (loggerContext == null) { + loggerContext = LogManager.getContext(Thread.currentThread().getContextClassLoader(), false); + LOGGER_CONTEXT_MAP.put(classLoader, loggerContext); + } + ExtendedLogger extendedLogger = loggerMap.get(classLoader); + if (extendedLogger == null) { + extendedLogger = loggerContext.getLogger(this.name); + loggerMap.put(classLoader, extendedLogger); + } + return extendedLogger; + } +} From 463e781ce686dc3a833b82d14b64a07805229881 Mon Sep 17 00:00:00 2001 From: suntaiming Date: Tue, 23 Jan 2024 11:30:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/logging/slf4j/Log4jLogger.java | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java index d4c8235fe..c7bd3f576 100644 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java @@ -1,18 +1,18 @@ /* * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with + * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache license, Version 2.0 + * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the license for the specific language governing permissions and - * limitations under the license. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.logging.slf4j; @@ -41,16 +41,18 @@ */ public class Log4jLogger implements LocationAwareLogger, Serializable { - public static final String FQCN = Log4jLogger.class.getName(); + public static final String FQCN = Log4jLogger.class + .getName(); - private static final long serialVersionUID = 7869000638091304316L; - private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT"); - private static final EventDataConverter CONVERTER = createConverter(); + private static final long serialVersionUID = 7869000638091304316L; + private static final Marker EVENT_MARKER = MarkerFactory + .getMarker("EVENT"); + private static final EventDataConverter CONVERTER = createConverter(); - private final boolean eventLogger; - private transient final Map loggerMap = new ConcurrentHashMap<>(); - private static final Map LOGGER_CONTEXT_MAP = new ConcurrentHashMap<>(); - private final String name; + private final boolean eventLogger; + private transient final Map loggerMap = new ConcurrentHashMap<>(); + private static final Map LOGGER_CONTEXT_MAP = new ConcurrentHashMap<>(); + private final String name; public Log4jLogger(final ExtendedLogger logger, final String name) { this.eventLogger = "EventLogger".equals(name); @@ -358,7 +360,8 @@ public void error(final Marker marker, final String s, final Throwable throwable } @Override - public void log(final Marker marker, final String fqcn, final int level, final String message, final Object[] params, Throwable throwable) { + public void log(final Marker marker, final String fqcn, final int level, final String message, + final Object[] params, Throwable throwable) { final Level log4jLevel = getLevel(level); final org.apache.logging.log4j.Marker log4jMarker = getMarker(marker); ExtendedLogger logger = getLogger(); @@ -386,7 +389,8 @@ private static org.apache.logging.log4j.Marker getMarker(final Marker marker) { } else if (marker instanceof Log4jMarker) { return ((Log4jMarker) marker).getLog4jMarker(); } else { - final Log4jMarkerFactory factory = (Log4jMarkerFactory) StaticMarkerBinder.SINGLETON.getMarkerFactory(); + final Log4jMarkerFactory factory = (Log4jMarkerFactory) StaticMarkerBinder.SINGLETON + .getMarkerFactory(); return ((Log4jMarker) factory.getMarker(marker)).getLog4jMarker(); } } @@ -400,7 +404,8 @@ public String getName() { * Always treat de-serialization as a full-blown constructor, by validating the final state of * the de-serialized object. */ - private void readObject(final ObjectInputStream aInputStream) throws ClassNotFoundException, IOException { + private void readObject(final ObjectInputStream aInputStream) throws ClassNotFoundException, + IOException { // always perform the default de-serialization first aInputStream.defaultReadObject(); } @@ -447,7 +452,8 @@ private ExtendedLogger getLogger() { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); LoggerContext loggerContext = LOGGER_CONTEXT_MAP.get(classLoader); if (loggerContext == null) { - loggerContext = LogManager.getContext(Thread.currentThread().getContextClassLoader(), false); + loggerContext = LogManager.getContext(Thread.currentThread().getContextClassLoader(), + false); LOGGER_CONTEXT_MAP.put(classLoader, loggerContext); } ExtendedLogger extendedLogger = loggerMap.get(classLoader); From c43ff00ea5e73f54799c884f4cf0d628df3a14d6 Mon Sep 17 00:00:00 2001 From: suntaiming Date: Thu, 8 Feb 2024 11:03:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?log4j2=E7=9A=84samples=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E4=B8=AAcase=E5=8F=8Alog4j2=E7=9A=84=E9=80=82=E9=85=8D?= =?UTF-8?q?=E5=8E=9F=E7=90=86=E8=A1=A5=E5=85=85=E9=80=82=E9=85=8D=E7=9A=84?= =?UTF-8?q?=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contribution-guidelines/runtime/logj42.md | 78 +++++++++++++++++- .../logging/imgs/biz1-3-log.png | Bin 0 -> 49108 bytes .../logging/imgs/biz2-3-log.png | Bin 0 -> 51048 bytes .../logging/log4j2/README.md | 27 +++++- .../logging/log4j2/base/pom.xml | 6 +- .../logging/base/rest/SampleController.java | 4 + .../src/main/resources/application.properties | 1 + .../base/src/main/resources/log4j2-spring.xml | 8 ++ .../logging/log4j2/biz1/pom.xml | 6 ++ .../logging/biz1/rest/SampleController.java | 6 ++ .../src/main/resources/application.properties | 1 + .../biz1/src/main/resources/log4j2-spring.xml | 8 ++ .../logging/log4j2/biz2/pom.xml | 6 ++ .../logging/biz2/rest/SampleController.java | 4 + .../src/main/resources/application.properties | 1 + .../biz2/src/main/resources/log4j2-spring.xml | 8 ++ .../sofa-serverless-adapter-log4j2/pom.xml | 3 + .../org/apache/logging/slf4j/Log4jLogger.java | 11 ++- 18 files changed, 166 insertions(+), 12 deletions(-) create mode 100644 samples/springboot-samples/logging/imgs/biz1-3-log.png create mode 100644 samples/springboot-samples/logging/imgs/biz2-3-log.png diff --git a/docs/content/zh-cn/docs/contribution-guidelines/runtime/logj42.md b/docs/content/zh-cn/docs/contribution-guidelines/runtime/logj42.md index ac976abe7..01ede6181 100644 --- a/docs/content/zh-cn/docs/contribution-guidelines/runtime/logj42.md +++ b/docs/content/zh-cn/docs/contribution-guidelines/runtime/logj42.md @@ -48,9 +48,55 @@ weight: 1 根据上面判断通过 bundle 的方式配置在多模块里不可行,因为 ResourceBundleLookup 可能只存在于基座中,导致始终只能拿到基座的 application.properties,导致模块的日志配置路径与基座相同,模块日志都打到基座中。所以需要改造成使用 ContextMapLookup。 +## static final修饰的Logger导致三方组件下沉基座后日志打印不能正常隔离 +如: +```java +private static final Logger LOG = LoggerFactory.getLogger(CacheManager.class); +``` +1. static final修饰的变量只会在类加载的时候初始化话一次 +2. 组件依赖下沉基座后,类加载器使用的为基座的类加载器,初始化log实例时使用的是基座的log配置,所以会打印到基座文件中,不能正常隔离 + +具体获取log源码如下: +```java +//org.apache.logging.log4j.spi.AbstractLoggerAdapter +@Override +public L getLogger(final String name) { + //关键是LoggerContext获取是否正确,往下追 + final LoggerContext context = getContext(); + final ConcurrentMap loggers = getLoggersInContext(context); + final L logger = loggers.get(name); + if (logger != null) { + return logger; + } + loggers.putIfAbsent(name, newLogger(name, context)); + return loggers.get(name); +} + +//获取LoggerContext +protected LoggerContext getContext() { + Class anchor = LogManager.getFactory().isClassLoaderDependent() ? StackLocatorUtil.getCallerClass(Log4jLoggerFactory.class, CALLER_PREDICATE) : null; + LOGGER.trace("Log4jLoggerFactory.getContext() found anchor {}", anchor); + return anchor == null ? LogManager.getContext(false) : this.getContext(anchor); +} + +//获取LoggerContext,关键在这里 +protected LoggerContext getContext(final Class callerClass) { + ClassLoader cl = null; + if (callerClass != null) { + //会优先使用当前类相关的类加载器,这里肯定是基座的类加载,所以返回的是基座的LoggerContext + cl = callerClass.getClassLoader(); + } + if (cl == null) { + cl = LoaderUtil.getThreadContextClassLoader(); + } + return LogManager.getContext(cl, false); +} + +``` + ## 预期多模块合并下的日志 基座与模块都能使用独立的日志配置、配置值,完全独立。但由于上述分析中,存在两处可能导致模块无法正常初始化的逻辑,故这里需要多 log4j2 进行适配。 - +static修饰的log在三方组件下沉基座后也会导致相关日志不能正常隔离打印,所以这里也需要做 log4j2 进行适配。 ### 多模块适配点 1. getLoggerContext() 能拿到模块自身的 LoggerContext ![](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/149473/1696938182575-51ce1066-21f0-47bb-8bdb-c3c7d0814ca3.png) @@ -58,7 +104,35 @@ weight: 1 a. 模块启动时将 application.properties 的值设置到 ThreadContext 中 b. 日志配置时,只能使用 ctx:xxx:xxx 的配置方式 - +3. LoggerFactory.getLogger()获取的是org.apache.logging.slf4j.Log4jLogger实例,他是一个包装类,所以有一定操作空间, +针对Log4jLogger进行复写改造,根据当前线程上下文类加载器动态获取底层ExtendedLogger对象 + ```java +public class Log4JLogger implements LocationAwareLogger, Serializable { + private transient final Map loggerMap = new ConcurrentHashMap<>(); + private static final Map LOGGER_CONTEXT_MAP = new ConcurrentHashMap<>(); + + pubblic void info(final String format, final Object o) { + //每次调用都获取对应的ExtendedLogger + getLogger().logIfEnabled(FQCN, Level.INFO, null, format, o); + } + + //根据当前线程类加载器动态获取ExtendedLogger + private ExtendedLogger getLogger() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + ExtendedLogger extendedLogger = loggerMap.get(classLoader); + if (extendedLogger == null) { + LoggerContext loggerContext = LOGGER_CONTEXT_MAP.get(classLoader); + if (loggerContext == null) { + loggerContext = LogManager.getContext(classLoader, false); + LOGGER_CONTEXT_MAP.put(classLoader, loggerContext); + } + extendedLogger = loggerContext.getLogger(this.name); + loggerMap.put(classLoader, extendedLogger); + } + return extendedLogger; + } + } +``` ## 模块改造方式 [详细查看源码](https://github.com/sofastack/sofa-serverless/tree/master/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/com/alipay/sofa/serverless/log4j2) diff --git a/samples/springboot-samples/logging/imgs/biz1-3-log.png b/samples/springboot-samples/logging/imgs/biz1-3-log.png new file mode 100644 index 0000000000000000000000000000000000000000..3694c8158bf1f21d062262a05826e52ea8b3ae57 GIT binary patch literal 49108 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≦d;7DcYOj|Ziv%nDHz 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 literal 0 HcmV?d00001 diff --git a/samples/springboot-samples/logging/imgs/biz2-3-log.png b/samples/springboot-samples/logging/imgs/biz2-3-log.png new file mode 100644 index 0000000000000000000000000000000000000000..00220cead9cfb415cd20a5e3f94085e9787ca31a GIT binary patch literal 51048 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 T$?%Q(&|fGeCMQ}dtmFMZ7h+4I literal 0 HcmV?d00001 diff --git a/samples/springboot-samples/logging/log4j2/README.md b/samples/springboot-samples/logging/log4j2/README.md index d89d37b6a..53bd569d4 100644 --- a/samples/springboot-samples/logging/log4j2/README.md +++ b/samples/springboot-samples/logging/log4j2/README.md @@ -45,6 +45,13 @@ base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加 + + + net.sf.ehcache + ehcache + + + ``` ### biz @@ -58,6 +65,14 @@ biz 包含两个模块,分别为 biz1 和 biz2, 都是普通 springboot,修 provided + + + net.sf.ehcache + ehcache + provided + + + com.alipay.sofa @@ -142,11 +157,17 @@ curl http://localhost:8080/biz2 2. 检查内容2, `./samples/logging/log4j2/logs/` 目录里的日志分布在符合如下情况 ![img_2.png](../imgs/logs-structure.png) -- biz1 的应用日志在 `./samples/logging/log4j2/logs/biz1/` 目录下 -- biz2 的应用日志在 `./samples/logging/log4j2/logs/biz2/` 目录下 -- base 的应用日志在 `./samples/logging/log4j2/logs/base/` 目录下 +3.三方组件(这里如ehcache)依赖下沉基座后日志正常隔离打印 +![img_1.png](../imgs/biz1-3-log.png) +![img.png](../imgs/biz2-3-log.png) + +- biz1 的应用及三方组件(ehcache)日志在 `./samples/logging/log4j2/logs/biz1/` 目录下 +- biz2 的应用及三方组件(ehcache)日志在 `./samples/logging/log4j2/logs/biz2/` 目录下 +- base 的应用及三方组件(ehcache)日志在 `./samples/logging/log4j2/logs/base/` 目录下 - biz1, biz2, base 的框架日志(如 spring sofaArk arklet等),统一合并在同一个目录文件里 ## 注意事项 这里主要使用简单应用做验证,如果复杂应用,需要注意模块做好瘦身,基座有的依赖,模块尽可能设置成 provided,尽可能使用基座的依赖。 + + diff --git a/samples/springboot-samples/logging/log4j2/base/pom.xml b/samples/springboot-samples/logging/log4j2/base/pom.xml index ce3aa4a94..081afe127 100644 --- a/samples/springboot-samples/logging/log4j2/base/pom.xml +++ b/samples/springboot-samples/logging/log4j2/base/pom.xml @@ -30,7 +30,6 @@ com.alipay.sofa web-ark-plugin - org.springframework.boot spring-boot-starter-web @@ -58,6 +57,11 @@ disruptor ${disruptor.version} + + + net.sf.ehcache + ehcache + diff --git a/samples/springboot-samples/logging/log4j2/base/src/main/java/com/alipay/sofa/logging/base/rest/SampleController.java b/samples/springboot-samples/logging/log4j2/base/src/main/java/com/alipay/sofa/logging/base/rest/SampleController.java index bea04773a..37b6d8d8c 100644 --- a/samples/springboot-samples/logging/log4j2/base/src/main/java/com/alipay/sofa/logging/base/rest/SampleController.java +++ b/samples/springboot-samples/logging/log4j2/base/src/main/java/com/alipay/sofa/logging/base/rest/SampleController.java @@ -1,6 +1,7 @@ package com.alipay.sofa.logging.base.rest; import com.alipay.sofa.logging.base.facade.SampleService; +import net.sf.ehcache.CacheManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -26,6 +27,9 @@ public String hello() { sampleService.service(); + CacheManager.create(); + CacheManager.create(); + return String.format("hello to %s deploy", appName); } } diff --git a/samples/springboot-samples/logging/log4j2/base/src/main/resources/application.properties b/samples/springboot-samples/logging/log4j2/base/src/main/resources/application.properties index d3e3ff999..016543415 100644 --- a/samples/springboot-samples/logging/log4j2/base/src/main/resources/application.properties +++ b/samples/springboot-samples/logging/log4j2/base/src/main/resources/application.properties @@ -4,4 +4,5 @@ logging.path=./logging/log4j2/logs/ logging.level.com.alipay.sofa=DEBUG logging.level.root=INFO logging.level.com.alipay.sofa.arklet=INFO +logging.level.net.sf.ehcache=DEBUG logging.config=classpath:log4j2-spring.xml diff --git a/samples/springboot-samples/logging/log4j2/base/src/main/resources/log4j2-spring.xml b/samples/springboot-samples/logging/log4j2/base/src/main/resources/log4j2-spring.xml index 45f80b375..fea3012cb 100644 --- a/samples/springboot-samples/logging/log4j2/base/src/main/resources/log4j2-spring.xml +++ b/samples/springboot-samples/logging/log4j2/base/src/main/resources/log4j2-spring.xml @@ -92,6 +92,14 @@ + + + + + + + diff --git a/samples/springboot-samples/logging/log4j2/biz1/pom.xml b/samples/springboot-samples/logging/log4j2/biz1/pom.xml index 3a64670e5..a00e10ca0 100644 --- a/samples/springboot-samples/logging/log4j2/biz1/pom.xml +++ b/samples/springboot-samples/logging/log4j2/biz1/pom.xml @@ -45,6 +45,12 @@ ${sofa.serverless.runtime.version} provided + + + net.sf.ehcache + ehcache + provided + diff --git a/samples/springboot-samples/logging/log4j2/biz1/src/main/java/com/alipay/sofa/logging/biz1/rest/SampleController.java b/samples/springboot-samples/logging/log4j2/biz1/src/main/java/com/alipay/sofa/logging/biz1/rest/SampleController.java index e28bbc90a..d4c21febf 100644 --- a/samples/springboot-samples/logging/log4j2/biz1/src/main/java/com/alipay/sofa/logging/biz1/rest/SampleController.java +++ b/samples/springboot-samples/logging/log4j2/biz1/src/main/java/com/alipay/sofa/logging/biz1/rest/SampleController.java @@ -1,5 +1,6 @@ package com.alipay.sofa.logging.biz1.rest; +import net.sf.ehcache.CacheManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -12,6 +13,7 @@ public class SampleController { private static final Logger LOGGER = LoggerFactory.getLogger(SampleController.class); + @Autowired private ApplicationContext applicationContext; @@ -19,6 +21,10 @@ public class SampleController { public String hello() { String appName = applicationContext.getApplicationName(); LOGGER.info("{} web test: into sample controller", appName); + + CacheManager.create(); + CacheManager.create(); + return String.format("hello to %s deploy", appName); } } diff --git a/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/application.properties b/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/application.properties index 256534db0..2b076af90 100644 --- a/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/application.properties +++ b/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/application.properties @@ -4,4 +4,5 @@ logging.path=./logging/log4j2/logs/ logging.level.com.alipay.sofa=DEBUG logging.level.root=INFO logging.level.com.alipay.sofa.arklet=INFO +logging.level.net.sf.ehcache=DEBUG logging.config=classpath:log4j2-spring.xml diff --git a/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/log4j2-spring.xml b/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/log4j2-spring.xml index 45f80b375..fea3012cb 100644 --- a/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/log4j2-spring.xml +++ b/samples/springboot-samples/logging/log4j2/biz1/src/main/resources/log4j2-spring.xml @@ -92,6 +92,14 @@ + + + + + + + diff --git a/samples/springboot-samples/logging/log4j2/biz2/pom.xml b/samples/springboot-samples/logging/log4j2/biz2/pom.xml index eb7ba2d66..a121edb16 100644 --- a/samples/springboot-samples/logging/log4j2/biz2/pom.xml +++ b/samples/springboot-samples/logging/log4j2/biz2/pom.xml @@ -45,6 +45,12 @@ ${sofa.serverless.runtime.version} provided + + + net.sf.ehcache + ehcache + provided + diff --git a/samples/springboot-samples/logging/log4j2/biz2/src/main/java/com/alipay/sofa/logging/biz2/rest/SampleController.java b/samples/springboot-samples/logging/log4j2/biz2/src/main/java/com/alipay/sofa/logging/biz2/rest/SampleController.java index 84102a22c..d117e79c8 100644 --- a/samples/springboot-samples/logging/log4j2/biz2/src/main/java/com/alipay/sofa/logging/biz2/rest/SampleController.java +++ b/samples/springboot-samples/logging/log4j2/biz2/src/main/java/com/alipay/sofa/logging/biz2/rest/SampleController.java @@ -1,5 +1,6 @@ package com.alipay.sofa.logging.biz2.rest; +import net.sf.ehcache.CacheManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -19,6 +20,9 @@ public class SampleController { public String hello() { String appName = applicationContext.getApplicationName(); LOGGER.info("{} web test: into sample controller", appName); + + CacheManager.create(); + CacheManager.create(); return String.format("hello to %s deploy", appName); } } diff --git a/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/application.properties b/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/application.properties index 811879704..c24c59a79 100644 --- a/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/application.properties +++ b/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/application.properties @@ -4,4 +4,5 @@ logging.path=./logging/log4j2/logs/ logging.level.com.alipay.sofa=DEBUG logging.level.root=INFO logging.level.com.alipay.sofa.arklet=INFO +logging.level.net.sf.ehcache=DEBUG logging.config=classpath:log4j2-spring.xml diff --git a/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/log4j2-spring.xml b/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/log4j2-spring.xml index 45f80b375..fea3012cb 100644 --- a/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/log4j2-spring.xml +++ b/samples/springboot-samples/logging/log4j2/biz2/src/main/resources/log4j2-spring.xml @@ -92,6 +92,14 @@ + + + + + + + diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/pom.xml b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/pom.xml index ddab63580..ca88c868b 100644 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/pom.xml +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/pom.xml @@ -60,6 +60,9 @@ org.springframework.boot.logging.log4j2.Log4J2LoggingSystem + + org.apache.logging.slf4j.Log4jLogger + diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java index c7bd3f576..3e558ae6c 100644 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-log4j2/src/main/java/org/apache/logging/slf4j/Log4jLogger.java @@ -450,14 +450,13 @@ private static Level getLevel(final int i) { */ private ExtendedLogger getLogger() { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - LoggerContext loggerContext = LOGGER_CONTEXT_MAP.get(classLoader); - if (loggerContext == null) { - loggerContext = LogManager.getContext(Thread.currentThread().getContextClassLoader(), - false); - LOGGER_CONTEXT_MAP.put(classLoader, loggerContext); - } ExtendedLogger extendedLogger = loggerMap.get(classLoader); if (extendedLogger == null) { + LoggerContext loggerContext = LOGGER_CONTEXT_MAP.get(classLoader); + if (loggerContext == null) { + loggerContext = LogManager.getContext(classLoader, false); + LOGGER_CONTEXT_MAP.put(classLoader, loggerContext); + } extendedLogger = loggerContext.getLogger(this.name); loggerMap.put(classLoader, extendedLogger); }