diff --git a/bin/start_fe.sh b/bin/start_fe.sh index 9d51648ff4fd66..67a6925fea1901 100755 --- a/bin/start_fe.sh +++ b/bin/start_fe.sh @@ -176,6 +176,17 @@ if [[ ! -d "${LOG_DIR}" ]]; then mkdir -p "${LOG_DIR}" fi +STDOUT_LOGGER="${LOG_DIR}/fe.out" +log() { + # same datetime format as in fe.log: 2024-06-03 14:54:41,478 + cur_date=$(date +"%Y-%m-%d %H:%M:%S,$(date +%3N)") + if [[ "${RUN_CONSOLE}" -eq 1 ]]; then + echo "StdoutLogger ${cur_date} $1" + else + echo "StdoutLogger ${cur_date} $1" >>"${STDOUT_LOGGER}" + fi +} + # check java version and choose correct JAVA_OPTS java_version="$( set -e @@ -183,16 +194,16 @@ java_version="$( )" if [[ "${java_version}" -eq 17 ]]; then if [[ -z "${JAVA_OPTS_FOR_JDK_17}" ]]; then - echo "JAVA_OPTS_FOR_JDK_17 is not set in fe.conf" >>"${LOG_DIR}/fe.out" + log "JAVA_OPTS_FOR_JDK_17 is not set in fe.conf" exit 1 fi final_java_opt="${JAVA_OPTS_FOR_JDK_17}" else - echo "ERROR: The jdk_version is ${java_version}, must be 17." >>"${LOG_DIR}/fe.out" + log "ERROR: The jdk_version is ${java_version}, must be 17." exit 1 fi -echo "Using Java version ${java_version}" >>"${LOG_DIR}/fe.out" -echo "${final_java_opt}" >>"${LOG_DIR}/fe.out" +log "Using Java version ${java_version}" +log "${final_java_opt}" # add libs to CLASSPATH DORIS_FE_JAR= @@ -239,7 +250,8 @@ if [[ -n "${JACOCO_COVERAGE_OPT}" ]]; then coverage_opt="${JACOCO_COVERAGE_OPT}" fi -date >>"${LOG_DIR}/fe.out" +CUR_DATE=$(date) +log "start time: ${CUR_DATE}" if [[ "${HELPER}" != "" ]]; then # change it to '-helper' to be compatible with code in Frontend @@ -253,12 +265,12 @@ if [[ "${IMAGE_TOOL}" -eq 1 ]]; then echo "Internal error, USE IMAGE_TOOL like: ./start_fe.sh --image image_path" fi elif [[ "${RUN_DAEMON}" -eq 1 ]]; then - nohup ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} -XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" ${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} "${METADATA_FAILURE_RECOVERY}" "$@" >>"${LOG_DIR}/fe.out" 2>&1 >"${STDOUT_LOGGER}" 2>&1 >"${LOG_DIR}/fe.out" 2>&1 >"${STDOUT_LOGGER}" 2>&1 com.amazonaws aws-java-sdk-s3 + + org.apache.logging.log4j + log4j-web + + + org.apache.logging.log4j + log4j-iostreams + + + org.apache.logging.log4j + log4j-core + doris-fe-common diff --git a/fe/fe-common/src/main/java/org/apache/doris/cloud/security/UrlSecurityChecker.java b/fe/fe-common/src/main/java/org/apache/doris/cloud/security/UrlSecurityChecker.java index 8d4056595e17e0..5f79343d0f9bd4 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/cloud/security/UrlSecurityChecker.java +++ b/fe/fe-common/src/main/java/org/apache/doris/cloud/security/UrlSecurityChecker.java @@ -18,6 +18,7 @@ package org.apache.doris.cloud.security; import org.apache.doris.common.Config; +import org.apache.doris.common.LogUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -38,8 +39,8 @@ public class UrlSecurityChecker extends SecurityChecker { urlSecurityStopCheckMethod = clazz.getMethod("stopSSRFNetHookChecking", String.class); } catch (Exception e) { LOG.warn("security_checker_class_name:{} exception:", Config.security_checker_class_name, e); + LogUtils.stderr("Failed to find com.aliyun.securitysdk.SecurityUtil's method"); e.printStackTrace(); - System.out.println("Failed to find com.aliyun.securitysdk.SecurityUtil's method"); } } diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java index 8420e598d2b661..63e45b3caa81ff 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java +++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java @@ -127,6 +127,13 @@ public class Config extends ConfigBase { @ConfField(description = {"是否压缩 FE 的 Audit 日志", "enable compression for FE audit log file"}) public static boolean audit_log_enable_compress = false; + @ConfField(description = {"是否使用文件记录日志。当使用 --console 启动 FE 时,全部日志同时写入到标准输出和文件。" + + "如果关闭这个选项,不再使用文件记录日志。", + "Whether to use file to record log. When starting FE with --console, " + + "all logs will be written to both standard output and file. " + + "Close this option will no longer use file to record log."}) + public static boolean enable_file_logger = true; + @ConfField(mutable = false, masterOnly = false, description = {"是否检查table锁泄漏", "Whether to check table lock leaky"}) public static boolean check_table_lock_leaky = false; diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/LogUtils.java b/fe/fe-common/src/main/java/org/apache/doris/common/LogUtils.java new file mode 100644 index 00000000000000..2f93cdb8850b53 --- /dev/null +++ b/fe/fe-common/src/main/java/org/apache/doris/common/LogUtils.java @@ -0,0 +1,97 @@ +// 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.doris.common; + +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.Node; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.layout.AbstractStringLayout; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.core.util.StringBuilderWriter; + +import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LogUtils { + + public static final String STDOUT_LOG_MARKER = "StdoutLogger "; + public static final String STDERR_LOG_MARKER = "StderrLogger "; + + private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss,SSS"); + + private static String formattedTime() { + LocalDateTime dateTime = LocalDateTime.now(); + return dateTime.format(TIME_FORMATTER); + } + + // Developer should use `LogUtils.stdout` or `LogUtils.stderr` + // instead of `System.out` and `System.err`. + public static void stdout(String message) { + System.out.println(STDOUT_LOG_MARKER + formattedTime() + " " + message); + } + + public static void stderr(String message) { + System.err.println(STDERR_LOG_MARKER + formattedTime() + " " + message); + } + + // TODO: this custom layout is not used in the codebase, but it is a good example of how to create a custom layout + // 1. Add log4j2.component.properties in fe/conf with content: + // log4j.layoutFactory=org.apache.doris.common.LogUtils$SingleLineExceptionLayout + // 2. Change PatternLayout in Log4jConfig.java to SingleLineExceptionLayout + @Plugin(name = "SingleLineExceptionLayout", category = Node.CATEGORY, + elementType = Layout.ELEMENT_TYPE, printObject = true) + public static class SingleLineExceptionLayout extends AbstractStringLayout { + + private final PatternLayout patternLayout; + + protected SingleLineExceptionLayout(PatternLayout patternLayout, Charset charset) { + super(charset); + this.patternLayout = patternLayout; + } + + @Override + public String toSerializable(LogEvent event) { + StringBuilder result = new StringBuilder(patternLayout.toSerializable(event)); + + if (event.getThrown() != null) { + StringBuilderWriter sw = new StringBuilderWriter(); + event.getThrown().printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString().replace("\n", " ").replace("\r", " "); + result.append(stackTrace); + } + + return result.toString(); + } + + @PluginFactory + public static Layout createLayout( + @PluginAttribute(value = "pattern") String pattern, + @PluginAttribute(value = "charset", defaultString = "UTF-8") Charset charset) { + PatternLayout patternLayout = PatternLayout.newBuilder() + .withPattern(pattern) + .withCharset(charset) + .build(); + return new SingleLineExceptionLayout(patternLayout, charset); + } + } +} diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml index ac697ae6c4e9f2..19ab65db6a9bb5 100644 --- a/fe/fe-core/pom.xml +++ b/fe/fe-core/pom.xml @@ -90,11 +90,6 @@ under the License. fe-common ${project.version} - - org.apache.logging.log4j - log4j-web - ${log4j2.version} - org.springframework.boot spring-boot-devtools diff --git a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java index 583f20687c69f4..3ca39bbfd0690e 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java @@ -24,6 +24,7 @@ import org.apache.doris.common.FeMetaVersion; import org.apache.doris.common.LdapConfig; import org.apache.doris.common.Log4jConfig; +import org.apache.doris.common.LogUtils; import org.apache.doris.common.ThreadPoolManager; import org.apache.doris.common.Version; import org.apache.doris.common.util.JdkUtils; @@ -386,11 +387,11 @@ private static CommandLineOptions parseArgs(String[] args) { } private static void printVersion() { - System.out.println("Build version: " + Version.DORIS_BUILD_VERSION); - System.out.println("Build time: " + Version.DORIS_BUILD_TIME); - System.out.println("Build info: " + Version.DORIS_BUILD_INFO); - System.out.println("Build hash: " + Version.DORIS_BUILD_HASH); - System.out.println("Java compile version: " + Version.DORIS_JAVA_COMPILE_VERSION); + LogUtils.stdout("Build version: " + Version.DORIS_BUILD_VERSION); + LogUtils.stdout("Build time: " + Version.DORIS_BUILD_TIME); + LogUtils.stdout("Build info: " + Version.DORIS_BUILD_INFO); + LogUtils.stdout("Build hash: " + Version.DORIS_BUILD_HASH); + LogUtils.stdout("Java compile version: " + Version.DORIS_JAVA_COMPILE_VERSION); LOG.info("Build version: {}", Version.DORIS_BUILD_VERSION); LOG.info("Build time: {}", Version.DORIS_BUILD_TIME); @@ -413,16 +414,16 @@ private static void checkCommandLineOptions(CommandLineOptions cmdLineOpts) { } else if (cmdLineOpts.runImageTool()) { File imageFile = new File(cmdLineOpts.getImagePath()); if (!imageFile.exists()) { - System.out.println("image does not exist: " + imageFile.getAbsolutePath() + LogUtils.stderr("image does not exist: " + imageFile.getAbsolutePath() + " . Please put an absolute path instead"); System.exit(-1); } else { - System.out.println("Start to load image: "); + LogUtils.stdout("Start to load image: "); try { MetaReader.read(imageFile, Env.getCurrentEnv()); - System.out.println("Load image success. Image file " + cmdLineOpts.getImagePath() + " is valid"); + LogUtils.stdout("Load image success. Image file " + cmdLineOpts.getImagePath() + " is valid"); } catch (Exception e) { - System.out.println("Load image failed. Image file " + cmdLineOpts.getImagePath() + " is invalid"); + LogUtils.stderr("Load image failed. Image file " + cmdLineOpts.getImagePath() + " is invalid"); LOG.warn("", e); } finally { System.exit(0); @@ -481,9 +482,7 @@ private static void tryLockProcess() { + "same time"); } - private static void releaseFileLockAndCloseFileChannel() { - if (processFileLock != null && processFileLock.isValid()) { try { processFileLock.release(); @@ -498,7 +497,6 @@ private static void releaseFileLockAndCloseFileChannel() { LOG.warn("release process lock file failed", ignored); } } - } public static void overwriteConfigs() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java index d49e7dd73b27dc..a91ab2ea5ba434 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java @@ -103,6 +103,7 @@ import org.apache.doris.common.ErrorReport; import org.apache.doris.common.FeConstants; import org.apache.doris.common.FeMetaVersion; +import org.apache.doris.common.LogUtils; import org.apache.doris.common.MetaNotFoundException; import org.apache.doris.common.NereidsSqlCacheManager; import org.apache.doris.common.Pair; @@ -1508,7 +1509,7 @@ private void transferToMaster() { if (Config.enable_check_compatibility_mode) { String msg = "check metadata compatibility successfully"; LOG.info(msg); - System.out.println(msg); + LogUtils.stdout(msg); System.exit(0); } @@ -1612,7 +1613,7 @@ private void transferToMaster() { checkLowerCaseTableNames(); String msg = "master finished to replay journal, can write now."; - Util.stdoutWithTime(msg); + LogUtils.stdout(msg); LOG.info(msg); // for master, there are some new thread pools need to register metric ThreadPoolManager.registerAllThreadPoolMetric(); @@ -2721,7 +2722,7 @@ public void notifyNewFETypeTransfer(FrontendNodeType newType) { try { String msg = "notify new FE type transfer: " + newType; LOG.warn(msg); - Util.stdoutWithTime(msg); + LogUtils.stdout(msg); this.typeTransferQueue.put(newType); } catch (InterruptedException e) { LOG.error("failed to put new FE type: {}", newType, e); @@ -2739,7 +2740,7 @@ protected synchronized void runOneCycle() { newType = typeTransferQueue.take(); } catch (InterruptedException e) { LOG.error("got exception when take FE type from queue", e); - Util.stdoutWithTime("got exception when take FE type from queue. " + e.getMessage()); + LogUtils.stdout("got exception when take FE type from queue. " + e.getMessage()); System.exit(-1); } Preconditions.checkNotNull(newType); @@ -2821,7 +2822,7 @@ protected synchronized void runOneCycle() { // exit if master changed to any other type String msg = "transfer FE type from MASTER to " + newType.name() + ". exit"; LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stdout(msg); System.exit(-1); break; } @@ -6320,13 +6321,13 @@ public void checkReadyOrThrowTException() throws TException { private void replayJournalsAndExit() { replayJournal(-1); LOG.info("check metadata compatibility successfully"); - System.out.println("check metadata compatibility successfully"); + LogUtils.stdout("check metadata compatibility successfully"); if (Config.checkpoint_after_check_compatibility) { String imagePath = dumpImage(); String msg = "the new image file path is: " + imagePath; LOG.info(msg); - System.out.println(msg); + LogUtils.stdout(msg); } System.exit(0); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/Log4jConfig.java b/fe/fe-core/src/main/java/org/apache/doris/common/Log4jConfig.java index 8c840a876bb69a..5395de076ae223 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/Log4jConfig.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/Log4jConfig.java @@ -21,15 +21,18 @@ import com.google.common.base.Strings; import com.google.common.collect.Maps; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.xml.XmlConfiguration; import org.apache.logging.log4j.core.lookup.Interpolator; import org.apache.logging.log4j.core.lookup.StrSubstitutor; +import org.apache.logging.log4j.io.IoBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -54,20 +57,55 @@ private static void getXmlConfByStrategy(final String size, final String age) { } } + // Placeholders + private static final String RUNTIME_LOG_FORMAT_PLACEHOLDER = ""; + private static final String VERBOSE_MODULE_PLACEHOLDER = ""; + private static final String CONSOLE_APPENDER_PLACEHOLDER = ""; + private static final String RUNTIME_LOG_FILE_APPENDER_PLACEHOLDER = ""; + private static final String RUNTIME_LOG_WARN_FILE_APPENDER_PLACEHOLDER = ""; + private static final String AUDIT_CONSOLE_LOGGER_PLACEHOLDER = ""; + private static final String AUDIT_FILE_LOGGER_PLACEHOLDER = ""; + private static final String RUNTIME_LOG_MARKER_PLACEHOLDER = ""; + private static final String AUDIT_LOG_MARKER_PLACEHOLDER = ""; + + // Appender names + private static final String RUNTIME_LOG_CONSOLE_APPENDER = "Console"; + private static final String RUNTIME_LOG_FILE_APPENDER = "Sys"; + private static final String RUNTIME_LOG_WARN_FILE_APPENDER = "SysWF"; + private static final String AUDIT_LOG_CONSOLE_APPENDER = "AuditConsole"; + private static final String AUDIT_LOG_FILE_APPENDER = "AuditFile"; + + // Log patterns + private static final String RUNTIME_LOG_PATTERN + = RUNTIME_LOG_MARKER_PLACEHOLDER + "%d{yyyy-MM-dd HH:mm:ss,SSS} %p (%t|%tid)" + + RUNTIME_LOG_FORMAT_PLACEHOLDER + "%m%n"; + private static final String AUDIT_LOG_PATTERN + = AUDIT_LOG_MARKER_PLACEHOLDER + "%d{yyyy-MM-dd HH:mm:ss,SSS} [%c{1}] %m%n"; + + // Log markers + private static final String RUNTIME_LOG_MARKER = "RuntimeLogger "; + private static final String AUDIT_LOG_MARKER = "AuditLogger "; + + // @formatter:off static { // CHECKSTYLE OFF xmlConfTemplateBuilder.append("\n") .append("\n\n") .append("\n") .append(" \n") - .append(" ") + .append(" \n") .append(" \n") - .append(" %d{yyyy-MM-dd HH:mm:ss,SSS} %p (%t|%tid)%m%n\n") + .append(" " + RUNTIME_LOG_PATTERN + "\n") .append(" \n") .append(" \n") - .append(" \n") + .append(" \n") .append(" \n") - .append(" %d{yyyy-MM-dd HH:mm:ss,SSS} %p (%t|%tid)%m%n\n") + .append(" " + AUDIT_LOG_PATTERN + "\n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" " + RUNTIME_LOG_PATTERN + "\n") .append(" \n") .append(" \n") .append(" \n") @@ -83,9 +121,9 @@ private static void getXmlConfByStrategy(final String size, final String age) { .append(" \n") .append(" \n") .append(" \n") - .append(" \n") + .append(" \n") .append(" \n") - .append(" %d{yyyy-MM-dd HH:mm:ss,SSS} %p (%t|%tid)%m%n\n") + .append(" " + RUNTIME_LOG_PATTERN + "\n") .append(" \n") .append(" \n") .append(" \n") @@ -101,9 +139,9 @@ private static void getXmlConfByStrategy(final String size, final String age) { .append(" \n") .append(" \n") .append(" \n") - .append(" \n") + .append(" \n") .append(" \n") - .append(" %d{yyyy-MM-dd HH:mm:ss,SSS} [%c{1}] %m%n\n") + .append(" " + AUDIT_LOG_PATTERN + "\n") .append(" \n") .append(" \n") .append(" \n") @@ -122,18 +160,20 @@ private static void getXmlConfByStrategy(final String size, final String age) { .append(" \n") .append(" \n") .append(" \n") - .append(" \n") - .append(" \n") - .append(" \n") + .append(" " + RUNTIME_LOG_FILE_APPENDER_PLACEHOLDER + "\n") + .append(" " + RUNTIME_LOG_WARN_FILE_APPENDER_PLACEHOLDER + "\n") + .append(" " + CONSOLE_APPENDER_PLACEHOLDER + "\n") .append(" \n") .append(" \n") - .append(" \n") + .append(" " + AUDIT_FILE_LOGGER_PLACEHOLDER + "\n") + .append(" " + AUDIT_CONSOLE_LOGGER_PLACEHOLDER + "\n") .append(" \n") - .append(" \n") + .append(" " + VERBOSE_MODULE_PLACEHOLDER + "\n") .append(" \n") .append(""); // CHECKSTYLE ON } + // @formatter:on private static StrSubstitutor strSub; private static String sysLogLevel; @@ -210,24 +250,33 @@ private static void reconfig() throws IOException { for (String s : auditModules) { sb.append(""); } - newXmlConfTemplate = newXmlConfTemplate.replaceAll("", - sb.toString()); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(VERBOSE_MODULE_PLACEHOLDER, sb.toString()); if (sysLogMode.equalsIgnoreCase("NORMAL")) { - newXmlConfTemplate = newXmlConfTemplate.replaceAll("", - " [%C{1}.%M():%L] "); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(RUNTIME_LOG_FORMAT_PLACEHOLDER, " [%C{1}.%M():%L] "); } else { - newXmlConfTemplate = newXmlConfTemplate.replaceAll("", " "); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(RUNTIME_LOG_FORMAT_PLACEHOLDER, " "); if (sysLogMode.equalsIgnoreCase("ASYNC")) { newXmlConfTemplate = newXmlConfTemplate.replaceAll("Root", "AsyncRoot"); } } + if (Config.enable_file_logger) { + newXmlConfTemplate = newXmlConfTemplate.replaceAll(RUNTIME_LOG_FILE_APPENDER_PLACEHOLDER, + "\n"); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(RUNTIME_LOG_WARN_FILE_APPENDER_PLACEHOLDER, + "\n"); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(AUDIT_FILE_LOGGER_PLACEHOLDER, + "\n"); + } + if (foreground) { - StringBuilder consoleLogger = new StringBuilder(); - consoleLogger.append("\n"); - newXmlConfTemplate = newXmlConfTemplate.replaceAll("", - consoleLogger.toString()); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(RUNTIME_LOG_MARKER_PLACEHOLDER, RUNTIME_LOG_MARKER); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(AUDIT_LOG_MARKER_PLACEHOLDER, AUDIT_LOG_MARKER); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(CONSOLE_APPENDER_PLACEHOLDER, + "\n"); + newXmlConfTemplate = newXmlConfTemplate.replaceAll(AUDIT_CONSOLE_LOGGER_PLACEHOLDER, + "\n"); } Map properties = Maps.newHashMap(); @@ -256,9 +305,7 @@ private static void reconfig() throws IOException { strSub = new StrSubstitutor(new Interpolator(properties)); newXmlConfTemplate = strSub.replace(newXmlConfTemplate); - System.out.println("====="); - System.out.println(newXmlConfTemplate); - System.out.println("====="); + LogUtils.stdout("=====\n" + newXmlConfTemplate + "\n====="); logXmlConfTemplate = newXmlConfTemplate; SpringLog4j2Config.writeSpringLogConf(customConfDir); @@ -277,6 +324,17 @@ private static void reconfig() throws IOException { } catch (Exception e) { throw new IOException("Error occurred while configuring Log4j", e); } + + redirectStd(); + } + + private static void redirectStd() { + PrintStream logPrintStream = IoBuilder.forLogger(LogManager.getLogger("system.out")).setLevel(Level.INFO) + .buildPrintStream(); + System.setOut(logPrintStream); + PrintStream errorPrintStream = IoBuilder.forLogger(LogManager.getLogger("system.err")).setLevel(Level.ERROR) + .buildPrintStream(); + System.setErr(errorPrintStream); } public static String getLogXmlConfTemplate() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/DocGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/DocGenerator.java index 0a207925fde846..c0a544d825dcce 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/DocGenerator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/DocGenerator.java @@ -19,6 +19,7 @@ import org.apache.doris.common.Config; import org.apache.doris.common.ConfigBase.ConfField; +import org.apache.doris.common.LogUtils; import org.apache.doris.qe.GlobalVariable; import org.apache.doris.qe.SessionVariable; import org.apache.doris.qe.VariableMgr; @@ -148,7 +149,7 @@ private String genFEConfigDoc(Lang lang) throws IllegalAccessException { sortedDoc.put(field.getName(), res); } } catch (Exception e) { - System.out.println("Failed to generate doc for field: " + field.getName()); + LogUtils.stderr("Failed to generate doc for field: " + field.getName()); throw e; } } @@ -204,7 +205,7 @@ private String genSessionVariableDoc(Lang lang) throws IllegalAccessException { sortedDoc.put(field.getAnnotation(VariableMgr.VarAttr.class).name(), res); } } catch (Exception e) { - System.out.println("Failed to generate doc for " + field.getName()); + LogUtils.stderr("Failed to generate doc for " + field.getName()); throw e; } } @@ -217,7 +218,7 @@ private String genSessionVariableDoc(Lang lang) throws IllegalAccessException { sortedDoc.put(field.getAnnotation(VariableMgr.VarAttr.class).name(), res); } } catch (Exception e) { - System.out.println("Failed to generate doc for field: " + field.getName()); + LogUtils.stderr("Failed to generate doc for field: " + field.getName()); throw e; } } @@ -288,7 +289,7 @@ public static void main(String[] args) { sessionVariableDocOutputPath, sessionVariableDocOutputPathCN); try { docGenerator.generate(); - System.out.println("Done!"); + LogUtils.stdout("Done!"); } catch (Exception e) { log.info("failed to generate doc", e); System.exit(-1); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/JdkUtils.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/JdkUtils.java index 34a604eb0d3b76..7d3a0402bcbbb3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/JdkUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/JdkUtils.java @@ -18,6 +18,7 @@ package org.apache.doris.common.util; import org.apache.doris.common.Config; +import org.apache.doris.common.LogUtils; import org.apache.doris.common.Version; import com.google.common.annotations.VisibleForTesting; @@ -42,7 +43,7 @@ public static boolean checkJavaVersion() { int runtimeVersion = JdkUtils.getJavaVersionAsInteger(javaRuntimeVersionStr); if (runtimeVersion < compileVersion) { - System.out.println("The runtime java version " + javaRuntimeVersionStr + " is less than " + LogUtils.stdout("The runtime java version " + javaRuntimeVersionStr + " is less than " + "compile version " + javaCompileVersionStr); return false; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/PlatformName.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/PlatformName.java deleted file mode 100644 index 0953c37196d2ee..00000000000000 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/PlatformName.java +++ /dev/null @@ -1,33 +0,0 @@ -// 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.doris.common.util; - -public class PlatformName { - - private static final String platformName = System.getProperty("os.name") + "-" - + System.getProperty("os.arch") + "-" - + System.getProperty("sun.arch.data.model"); - - public static String getPlatformName() { - return platformName; - } - - public static void main(String[] args) { - System.out.println(platformName); - } -} diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java index 4e4c6a947359fb..e73df139e01a8d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java @@ -424,10 +424,6 @@ public static boolean getBooleanPropertyOrDefault(String valStr, boolean default } } - public static void stdoutWithTime(String msg) { - System.out.println("[" + TimeUtils.longToTimeString(System.currentTimeMillis()) + "] " + msg); - } - // not support encode negative value now public static void encodeVarint64(long source, DataOutput out) throws IOException { assert source >= 0; diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/lakesoul/LakeSoulExternalTable.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/lakesoul/LakeSoulExternalTable.java index 5ba686fc6882b3..46e8d1db47c723 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/lakesoul/LakeSoulExternalTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/lakesoul/LakeSoulExternalTable.java @@ -149,7 +149,6 @@ public Optional initSchema() { TableInfo tableInfo = ((LakeSoulExternalCatalog) catalog).getLakeSoulTable(dbName, name); String tableSchema = tableInfo.getTableSchema(); DBUtil.TablePartitionKeys partitionKeys = DBUtil.parseTableInfoPartitions(tableInfo.getPartitions()); - System.out.println(tableSchema); Schema schema; try { schema = Schema.fromJSON(tableSchema); diff --git a/fe/fe-core/src/main/java/org/apache/doris/ha/BDBStateChangeListener.java b/fe/fe-core/src/main/java/org/apache/doris/ha/BDBStateChangeListener.java index 2ff66a5aad0162..302717c6050e8b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/ha/BDBStateChangeListener.java +++ b/fe/fe-core/src/main/java/org/apache/doris/ha/BDBStateChangeListener.java @@ -18,7 +18,7 @@ package org.apache.doris.ha; import org.apache.doris.catalog.Env; -import org.apache.doris.common.util.Util; +import org.apache.doris.common.LogUtils; import com.google.common.base.Preconditions; import com.sleepycat.je.rep.StateChangeEvent; @@ -57,7 +57,7 @@ public synchronized void stateChange(StateChangeEvent sce) throws RuntimeExcepti default: { String msg = "this node is " + sce.getState().name(); LOG.warn(msg); - Util.stdoutWithTime(msg); + LogUtils.stdout(msg); return; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java index 47a41b8226ad01..d2784a05e70c7a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java @@ -105,8 +105,7 @@ public void setup(File envHome, String selfNodeName, String selfNodeHostPort, DbResetRepGroup resetUtility = new DbResetRepGroup( envHome, PALO_JOURNAL_GROUP, selfNodeName, selfNodeHostPort); resetUtility.reset(); - LOG.warn("WARNING: metadata recovery mode, group has been reset."); - System.out.println("WARNING: metadata recovery mode, group has been reset."); + LOG.warn("metadata recovery mode, group has been reset."); } // set replication config diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java index 0d342a986cd40f..9e78b5eb47a14b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java @@ -20,10 +20,10 @@ import org.apache.doris.catalog.Env; import org.apache.doris.common.Config; import org.apache.doris.common.FeConstants; +import org.apache.doris.common.LogUtils; import org.apache.doris.common.io.DataOutputBuffer; import org.apache.doris.common.io.Writable; import org.apache.doris.common.util.NetUtils; -import org.apache.doris.common.util.Util; import org.apache.doris.journal.Journal; import org.apache.doris.journal.JournalBatch; import org.apache.doris.journal.JournalCursor; @@ -120,7 +120,7 @@ public synchronized void rollJournal() { + "journal id: %d, current db: %s, expected db count: %d", newName, currentDbName, newNameVerify); LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stderr(msg); System.exit(-1); } } @@ -193,7 +193,7 @@ public synchronized long write(JournalBatch batch) throws IOException { String msg = "write bdb failed. will exit. the first journalId: " + firstId + ", bdb database Name: " + currentJournalDB.getDatabaseName(); LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stderr(msg); System.exit(-1); } catch (DatabaseException e) { LOG.error("catch an exception when writing to database. sleep and retry. the first journal id {}", @@ -218,7 +218,7 @@ public synchronized long write(JournalBatch batch) throws IOException { String msg = "write bdb failed. will exit. the first journalId: " + firstId + ", bdb database Name: " + currentJournalDB.getDatabaseName(); LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stderr(msg); System.exit(-1); return 0; // unreachable! } @@ -285,7 +285,7 @@ public synchronized long write(short op, Writable writable) throws IOException { String msg = "write bdb failed. will exit. journalId: " + id + ", bdb database Name: " + currentJournalDB.getDatabaseName(); LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stderr(msg); System.exit(-1); } catch (DatabaseException e) { LOG.error("catch an exception when writing to database. sleep and retry. journal id {}", id, e); @@ -301,7 +301,7 @@ public synchronized long write(short op, Writable writable) throws IOException { String msg = "write bdb failed. will exit. journalId: " + id + ", bdb database Name: " + currentJournalDB.getDatabaseName(); LOG.error(msg); - Util.stdoutWithTime(msg); + LogUtils.stderr(msg); System.exit(-1); } return id; @@ -357,7 +357,7 @@ public JournalEntity read(long journalId) { LOG.warn("", e); } } else { - System.out.println("No record found for key '" + journalId + "'."); + LOG.warn("No record found for key '{}'.", journalId); } } catch (Exception e) { LOG.warn("catch an exception when get JournalEntity. key:{}", journalId, e); diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJournalCursor.java b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJournalCursor.java index 5466df71ddcc8a..8c48cab42c5df6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJournalCursor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJournalCursor.java @@ -46,7 +46,7 @@ public class BDBJournalCursor implements JournalCursor { public static BDBJournalCursor getJournalCursor(BDBEnvironment env, long fromKey, long toKey) { if (toKey < fromKey || fromKey < 0) { - System.out.println("Invalid key range!"); + LOG.warn("Invalid key range! fromKey:{} toKey:{}", fromKey, toKey); return null; } BDBJournalCursor cursor = null; diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBTool.java b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBTool.java index cc9defa378bf57..55c15475282c36 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBTool.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBTool.java @@ -18,6 +18,7 @@ package org.apache.doris.journal.bdbje; import org.apache.doris.catalog.Env; +import org.apache.doris.common.LogUtils; import org.apache.doris.journal.JournalEntity; import org.apache.doris.meta.MetaContext; @@ -66,7 +67,7 @@ public boolean run() { env = new Environment(new File(metaPath), envConfig); } catch (DatabaseException e) { LOG.warn("", e); - System.err.println("Failed to open BDBJE env: " + Env.getCurrentEnv().getBdbDir() + ". exit"); + LogUtils.stderr("Failed to open BDBJE env: " + Env.getCurrentEnv().getBdbDir() + ". exit"); return false; } Preconditions.checkNotNull(env); @@ -75,7 +76,7 @@ public boolean run() { if (options.isListDbs()) { // list all databases List dbNames = env.getDatabaseNames(); - System.out.println(JSONArray.toJSONString(dbNames)); + LogUtils.stdout(JSONArray.toJSONString(dbNames)); return true; } else { // db operations @@ -90,7 +91,7 @@ public boolean run() { // get db stat Map statMap = Maps.newHashMap(); statMap.put("count", String.valueOf(db.count())); - System.out.println(JSONObject.toJSONString(statMap)); + LogUtils.stdout(JSONObject.toJSONString(statMap)); return true; } else { // set from key @@ -99,7 +100,7 @@ public boolean run() { try { fromKey = Long.valueOf(fromKeyStr); } catch (NumberFormatException e) { - System.err.println("Not a valid from key: " + fromKeyStr); + LogUtils.stderr("Not a valid from key: " + fromKeyStr); return false; } @@ -109,13 +110,13 @@ public boolean run() { try { endKey = Long.valueOf(options.getEndKey()); } catch (NumberFormatException e) { - System.err.println("Not a valid end key: " + options.getEndKey()); + LogUtils.stderr("Not a valid end key: " + options.getEndKey()); return false; } } if (fromKey > endKey) { - System.err.println("from key should less than or equal to end key[" + LogUtils.stderr("from key should less than or equal to end key[" + fromKey + " vs. " + endKey + "]"); return false; } @@ -132,7 +133,7 @@ public boolean run() { } } catch (Exception e) { LOG.warn("", e); - System.err.println("Failed to run bdb tools"); + LogUtils.stderr("Failed to run bdb tools"); return false; } return true; @@ -155,15 +156,15 @@ private void getValueByKey(Database db, Long key) entity.readFields(in); } catch (Exception e) { LOG.warn("", e); - System.err.println("Fail to read journal entity for key: " + key + ". reason: " + e.getMessage()); + LogUtils.stderr("Fail to read journal entity for key: " + key + ". reason: " + e.getMessage()); System.exit(-1); } - System.out.println("key: " + key); - System.out.println("op code: " + entity.getOpCode()); - System.out.println("value: " + entity.getData().toString()); + LogUtils.stdout("key: " + key); + LogUtils.stdout("op code: " + entity.getOpCode()); + LogUtils.stdout("value: " + entity.getData().toString()); } else if (status == OperationStatus.NOTFOUND) { - System.out.println("key: " + key); - System.out.println("value: NOT FOUND"); + LogUtils.stdout("key: " + key); + LogUtils.stdout("value: NOT FOUND"); } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournal.java b/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournal.java index 45ae377a40171c..8e39f8a6a616be 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournal.java @@ -84,7 +84,7 @@ public synchronized void rollJournal() { try { storage = new Storage(imageDir); if (journalId.get() == storage.getEditsSeq()) { - System.out.println("Does not need to roll!"); + LOG.warn("Does not need to roll! journalId: {}, editsSeq: {}", journalId.get(), storage.getEditsSeq()); return; } if (outputStream != null) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java b/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java index d570719dd3a13d..d24e394927b1cf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java @@ -50,7 +50,7 @@ public final class LocalJournalCursor implements JournalCursor { public static LocalJournalCursor getJournalCursor(String imageDir, long fromKey, long toKey) { if (toKey < fromKey && toKey != -1 || fromKey < 0) { - System.out.println("Invalid key range!"); + LOG.warn("Invalid fromKey:{} toKey:{}", fromKey, toKey); return null; } long newToKey = toKey; @@ -95,7 +95,7 @@ private LocalJournalCursor(String imageDir, long fromKey, long toKey) throws IOE } if (fileName == null) { - System.out.println("Can not find the key:" + fromKey); + LOG.warn("Can not find the key:{}", fromKey); throw new IOException(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java index 0e58f1bc976ba5..ae3aa52c4f2094 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java @@ -79,9 +79,4 @@ public void execute(JobContext context) { public boolean isOnce() { return false; } - - private void printTraceLog(RuleType ruleType, String traceBefore, String traceAfter) { - System.out.println("========== " + getClass().getSimpleName() + " " + ruleType - + " ==========\nbefore:\n" + traceBefore + "\n\nafter:\n" + traceAfter + "\n"); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/persist/EditLog.java b/fe/fe-core/src/main/java/org/apache/doris/persist/EditLog.java index d440cf77cac5e7..d5177844868373 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/persist/EditLog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/persist/EditLog.java @@ -446,8 +446,7 @@ public static void loadJournal(Env env, Long logId, JournalEntity journal) { Frontend fe = (Frontend) journal.getData(); env.replayDropFrontend(fe); if (fe.getNodeName().equals(Env.getCurrentEnv().getNodeName())) { - System.out.println("current fe " + fe + " is removed. will exit"); - LOG.info("current fe " + fe + " is removed. will exit"); + LOG.warn("current fe {} is removed. will exit", fe); System.exit(-1); } break; diff --git a/fe/pom.xml b/fe/pom.xml index 2eaa31c43cd814..c443a07b001dc1 100644 --- a/fe/pom.xml +++ b/fe/pom.xml @@ -824,6 +824,11 @@ under the License. log4j-core ${log4j2.version} + + org.apache.logging.log4j + log4j-iostreams + ${log4j2.version} + org.apache.logging.log4j log4j-slf4j-impl