From 784e94b7b548b75fd5cfbceb051ba301a3d4165a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A6=82=E6=A2=A6=E6=8A=80=E6=9C=AF?= <596392912@qq.com> Date: Wed, 24 Feb 2021 18:35:53 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E4=BC=98=E5=8C=96=20mica-logging?= =?UTF-8?q?=20=E7=BB=84=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/dreamlu/mica/core/utils/JsonUtil.java | 20 +++ .../dreamlu/mica/core/utils/SystemUtil.java | 60 +++++++ mica-logging/README.md | 26 +-- mica-logging/build.gradle | 2 +- .../logging/config/LoggingInitializer.java | 2 +- .../config/LoggingStartedEventListener.java | 11 +- .../mica/logging/config/LoggingUtil.java | 162 +++++++++++++++--- .../config/MicaLoggingConfiguration.java | 33 ++-- .../logging/config/MicaLoggingProperties.java | 4 +- .../src/main/resources/file-error.xml | 20 --- .../src/main/resources/logback-spring.xml | 12 +- 11 files changed, 255 insertions(+), 97 deletions(-) delete mode 100644 mica-logging/src/main/resources/file-error.xml diff --git a/mica-core/src/main/java/net/dreamlu/mica/core/utils/JsonUtil.java b/mica-core/src/main/java/net/dreamlu/mica/core/utils/JsonUtil.java index 27778c3a..1193638d 100644 --- a/mica-core/src/main/java/net/dreamlu/mica/core/utils/JsonUtil.java +++ b/mica-core/src/main/java/net/dreamlu/mica/core/utils/JsonUtil.java @@ -23,6 +23,8 @@ import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.core.json.JsonReadFeature; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.type.CollectionLikeType; import com.fasterxml.jackson.databind.type.MapType; import lombok.experimental.UtilityClass; @@ -694,6 +696,24 @@ public class JsonUtil { } } + /** + * 创建 ObjectNode + * + * @return ObjectNode + */ + public static ObjectNode createObjectNode() { + return getInstance().createObjectNode(); + } + + /** + * 创建 ArrayNode + * + * @return ArrayNode + */ + public static ArrayNode createArrayNode() { + return getInstance().createArrayNode(); + } + /** * 获取 ObjectMapper 实例 * diff --git a/mica-core/src/main/java/net/dreamlu/mica/core/utils/SystemUtil.java b/mica-core/src/main/java/net/dreamlu/mica/core/utils/SystemUtil.java index b41529f4..98a93f7d 100644 --- a/mica-core/src/main/java/net/dreamlu/mica/core/utils/SystemUtil.java +++ b/mica-core/src/main/java/net/dreamlu/mica/core/utils/SystemUtil.java @@ -2,6 +2,8 @@ package net.dreamlu.mica.core.utils; import org.springframework.lang.Nullable; +import java.util.Objects; + /** * 系统工具类 * @@ -69,9 +71,67 @@ public class SystemUtil { /** * 代码部署于 linux 上,工作默认为 mac 和 Windows + * * @return boolean */ public static boolean isLocalDev() { return !SystemUtil.isLinux(); } + + /** + * 读取 System Property + * + * @param key key + * @return value + */ + @Nullable + public static String getProp(String key) { + return System.getProperty(key); + } + + /** + * 读取 System Property + * + * @param key key + * @param defValue 默认值 + * @return value + */ + public static String getProp(String key, String defValue) { + return System.getProperty(key, defValue); + } + + /** + * 读取 System Property + * + * @param key key + * @param defaultValue defaultValue + * @return value + */ + public static int getPropToInt(String key, int defaultValue) { + return ObjectUtil.toInt(getProp(key), defaultValue); + } + + /** + * 读取 System Property + * + * @param key key + * @param defaultValue defaultValue + * @return value + */ + public static boolean getPropToBool(String key, boolean defaultValue) { + return Objects.requireNonNull(ObjectUtil.toBoolean(getProp(key), defaultValue)); + } + + /** + * 读取 System Property 或者 Env + * + * @param key key + * @return value + */ + @Nullable + public static String getPropOrEnv(String key) { + String value = System.getProperty(key); + return value == null ? System.getenv(key) : value; + } + } diff --git a/mica-logging/README.md b/mica-logging/README.md index f16d464c..6756d2d4 100644 --- a/mica-logging/README.md +++ b/mica-logging/README.md @@ -2,8 +2,9 @@ ## 功能 1. 默认日志配置。 -2. logstash 日志收集。 -3. 启动完成关闭控制台日志。 +2. 打印 json 日志文件。 +3. logstash 日志收集。 +4. 启动完成关闭控制台日志。 ## 依赖引用 ### maven @@ -20,21 +21,6 @@ compile("net.dreamlu:mica-logging:${version}") ``` -## 可选依赖 -### maven -```xml - - net.logstash.logback - logstash-logback-encoder - ${version} - -``` - -### gradle -```groovy -compile("net.logstash.logback:logstash-logback-encoder:${version}") -``` - ## 配置 **特别注意:** 需要配置`服务名`和`环境`,例如: @@ -48,12 +34,12 @@ spring: | 配置项 | 默认值 | 说明 | | ----- | ------ | ------ | -| mica.logging.console.enabled | true | 是否开启控制台日志,默认**开启**。设置为`关闭`时,启动完成后将自动关闭控制台日志 | -| mica.logging.logstash.enabled | false | 是否开启 logstash 日志收集 | +| mica.logging.use-json-format | false | 使用 json 格式化,设置后文件打印 json 日志,可用于 filebeat 收集日志文件 | +| mica.logging.console.close-after-start | false | 是否启动完成后将自动关闭控制台日志,默认**false**。**非开发环境**建议设置为 **true** | +| mica.logging.logstash.enabled | false | 是否开启 logstash 日志收集,直接收集到 logstash | | mica.logging.logstash.host | localhost | logstash host | | mica.logging.logstash.port | 5000 | logstash port | | mica.logging.logstash.queue-size | 512 | logstash 队列大小 | -| mica.logging.use-json-format | false | 使用 json 格式化 | ## 参考 - [jhipster](https://github.com/jhipster/jhipster) \ No newline at end of file diff --git a/mica-logging/build.gradle b/mica-logging/build.gradle index e606b707..ace4c8bf 100644 --- a/mica-logging/build.gradle +++ b/mica-logging/build.gradle @@ -1,8 +1,8 @@ dependencies { api project(":mica-core") + api "net.logstash.logback:logstash-logback-encoder:${logstashVersion}" api "org.springframework.boot:spring-boot-starter-logging" implementation "org.springframework.boot:spring-boot" - implementation "net.logstash.logback:logstash-logback-encoder:${logstashVersion}" compileOnly "org.springframework.cloud:spring-cloud-context" compileOnly "net.dreamlu:mica-auto:${micaAutoVersion}" annotationProcessor "net.dreamlu:mica-auto:${micaAutoVersion}" diff --git a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/LoggingInitializer.java b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/LoggingInitializer.java index 6c75238d..3b46873b 100644 --- a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/LoggingInitializer.java +++ b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/LoggingInitializer.java @@ -34,7 +34,7 @@ public class LoggingInitializer implements ApplicationContextInitializer * Utility methods to add appenders to a {@link LoggerContext}. + * + * @author jhipster + * @author L.cm */ @Slf4j @UtilityClass public class LoggingUtil { + public static final String DEFAULT_LOG_DIR = "logs"; public static final String CONSOLE_APPENDER_NAME = "CONSOLE"; public static final String FILE_APPENDER_NAME = "FILE"; public static final String FILE_ERROR_APPENDER_NAME = "FILE_ERROR"; @@ -68,7 +83,8 @@ public class LoggingUtil { * @param context a {@link LoggerContext} object. * @param customFields a {@link String} object. */ - public static void addJsonConsoleAppender(LoggerContext context, String customFields) { + public static void addJsonConsoleAppender(LoggerContext context, + String customFields) { log.info("Initializing Console loggingProperties"); // More documentation is available at: https://github.com/logstash/logstash-logback-encoder ConsoleAppender consoleAppender = new ConsoleAppender<>(); @@ -80,23 +96,79 @@ public class LoggingUtil { context.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(consoleAppender); } + /** + *

addJsonConsoleAppender.

+ * + * @param context a {@link LoggerContext} object. + * @param customFields a {@link String} object. + */ + public static void addAllFileAppender(LoggerContext context, + String logFile, + boolean useJsonFormat, + String customFields) { + log.info("Initializing {} file loggingProperties", logFile); + // More documentation is available at: https://github.com/logstash/logstash-logback-encoder + RollingFileAppender allFileAppender = new RollingFileAppender<>(); + allFileAppender.setContext(context); + if (useJsonFormat) { + allFileAppender.setEncoder(compositeJsonEncoder(context, customFields)); + } else { + allFileAppender.setEncoder(patternLayoutEncoder(context)); + } + allFileAppender.setName(FILE_APPENDER_NAME); + allFileAppender.setFile(logFile); + allFileAppender.setRollingPolicy(rollingPolicy(context, logFile)); + allFileAppender.start(); + context.getLogger(Logger.ROOT_LOGGER_NAME).detachAppender(FILE_APPENDER_NAME); + context.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(allFileAppender); + } + + /** + *

addJsonConsoleAppender.

+ * + * @param context a {@link LoggerContext} object. + * @param customFields a {@link String} object. + */ + public static void addErrorFileAppender(LoggerContext context, + String logFile, + boolean useJsonFormat, + String customFields) { + log.info("Initializing {} file loggingProperties", logFile); + // More documentation is available at: https://github.com/logstash/logstash-logback-encoder + RollingFileAppender errorFileAppender = new RollingFileAppender<>(); + errorFileAppender.setContext(context); + errorFileAppender.addFilter(errorLevelFilter(context)); + if (useJsonFormat) { + errorFileAppender.setEncoder(compositeJsonEncoder(context, customFields)); + } else { + errorFileAppender.setEncoder(patternLayoutEncoder(context)); + } + errorFileAppender.setName(FILE_ERROR_APPENDER_NAME); + errorFileAppender.setFile(logFile); + errorFileAppender.setRollingPolicy(rollingPolicy(context, logFile)); + errorFileAppender.start(); + context.getLogger(Logger.ROOT_LOGGER_NAME).detachAppender(FILE_ERROR_APPENDER_NAME); + context.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(errorFileAppender); + } + /** *

addLogstashTcpSocketAppender.

* * @param context a {@link LoggerContext} object. * @param customFields a {@link String} object. - * @param logstashProperties a {@link net.dreamlu.mica.logging.config.MicaLoggingProperties.Logstash} object. + * @param logStashProperties a {@link net.dreamlu.mica.logging.config.MicaLoggingProperties.Logstash} object. */ - public static void addLogstashTcpSocketAppender(LoggerContext context, String customFields, - MicaLoggingProperties.Logstash logstashProperties) { - log.info("Initializing Logstash loggingProperties"); + public static void addLogStashTcpSocketAppender(LoggerContext context, + String customFields, + MicaLoggingProperties.Logstash logStashProperties) { + log.info("Initializing LogStash loggingProperties"); // More documentation is available at: https://github.com/logstash/logstash-logback-encoder LogstashTcpSocketAppender logStashAppender = new LogstashTcpSocketAppender(); - logStashAppender.addDestinations(new InetSocketAddress(logstashProperties.getHost(), logstashProperties.getPort())); + logStashAppender.addDestinations(new InetSocketAddress(logStashProperties.getHost(), logStashProperties.getPort())); logStashAppender.setContext(context); logStashAppender.setEncoder(logstashEncoder(customFields)); logStashAppender.setName(ASYNC_LOG_STASH_APPENDER_NAME); - logStashAppender.setQueueSize(logstashProperties.getQueueSize()); + logStashAppender.setQueueSize(logStashProperties.getQueueSize()); logStashAppender.start(); context.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(logStashAppender); } @@ -108,13 +180,49 @@ public class LoggingUtil { * @param customFields a {@link String} object. * @param properties a {@link net.dreamlu.mica.logging.config.MicaLoggingProperties} object. */ - public static void addContextListener(LoggerContext context, String customFields, MicaLoggingProperties properties) { - LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener(properties, customFields); + public static void addContextListener(LoggerContext context, + String logFile, + String logErrorFile, + String customFields, + MicaLoggingProperties properties) { + LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener(logFile, logErrorFile, customFields, properties); loggerContextListener.setContext(context); context.addListener(loggerContextListener); } - private static LoggingEventCompositeJsonEncoder compositeJsonEncoder(LoggerContext context, String customFields) { + private static RollingPolicy rollingPolicy(LoggerContext context, + String logErrorFile) { + SizeAndTimeBasedRollingPolicy rollingPolicy = new SizeAndTimeBasedRollingPolicy<>(); + rollingPolicy.setContext(context); + rollingPolicy.setCleanHistoryOnStart(SystemUtil.getPropToBool(LogbackLoggingSystemProperties.ROLLINGPOLICY_CLEAN_HISTORY_ON_START, false)); + rollingPolicy.setFileNamePattern(logErrorFile + ".%d{yyyy-MM-dd}.%i.gz}"); + rollingPolicy.setMaxFileSize(FileSize.valueOf(SystemUtil.getProp(LogbackLoggingSystemProperties.ROLLINGPOLICY_MAX_FILE_SIZE, "10MB"))); + rollingPolicy.setMaxHistory(SystemUtil.getPropToInt(LogbackLoggingSystemProperties.ROLLINGPOLICY_MAX_HISTORY, 7)); + rollingPolicy.setTotalSizeCap(FileSize.valueOf(SystemUtil.getProp(LogbackLoggingSystemProperties.ROLLINGPOLICY_TOTAL_SIZE_CAP, "0"))); + rollingPolicy.start(); + return rollingPolicy; + } + + private static ThresholdFilter errorLevelFilter(LoggerContext context) { + final ThresholdFilter filter = new ThresholdFilter(); + filter.setContext(context); + filter.setLevel(Level.ERROR.levelStr); + filter.start(); + return filter; + } + + private static Encoder patternLayoutEncoder(LoggerContext context) { + PatternLayoutEncoder encoder = new PatternLayoutEncoder(); + encoder.setContext(context); + encoder.setPattern(context.getProperty(LoggingSystemProperties.FILE_LOG_PATTERN)); + String charsetName = SystemUtil.getProp(LogbackLoggingSystemProperties.FILE_LOG_CHARSET, "default"); + encoder.setCharset(Charset.forName(charsetName)); + encoder.start(); + return encoder; + } + + private static LoggingEventCompositeJsonEncoder compositeJsonEncoder(LoggerContext context, + String customFields) { final LoggingEventCompositeJsonEncoder compositeJsonEncoder = new LoggingEventCompositeJsonEncoder(); compositeJsonEncoder.setContext(context); compositeJsonEncoder.setProviders(jsonProviders(context, customFields)); @@ -129,7 +237,8 @@ public class LoggingUtil { return logstashEncoder; } - private static LoggingEventJsonProviders jsonProviders(LoggerContext context, String customFields) { + private static LoggingEventJsonProviders jsonProviders(LoggerContext context, + String customFields) { final LoggingEventJsonProviders jsonProviders = new LoggingEventJsonProviders(); jsonProviders.addArguments(new ArgumentsJsonProvider()); jsonProviders.addContext(new ContextJsonProvider<>()); @@ -182,12 +291,19 @@ public class LoggingUtil { * This listener ensures that the programmatic configuration is also re-applied after reset. */ private static class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener { - private final MicaLoggingProperties loggingProperties; + private final String logFile; + private final String logErrorFile; private final String customFields; + private final MicaLoggingProperties loggingProperties; - private LogbackLoggerContextListener(MicaLoggingProperties loggingProperties, String customFields) { + private LogbackLoggerContextListener(String logFile, + String logErrorFile, + String customFields, + MicaLoggingProperties loggingProperties) { this.loggingProperties = loggingProperties; this.customFields = customFields; + this.logFile = logFile; + this.logErrorFile = logErrorFile; } @Override @@ -197,21 +313,23 @@ public class LoggingUtil { @Override public void onStart(LoggerContext context) { - if (this.loggingProperties.isUseJsonFormat()) { - addJsonConsoleAppender(context, customFields); - } if (this.loggingProperties.getLogstash().isEnabled()) { - addLogstashTcpSocketAppender(context, customFields, loggingProperties.getLogstash()); + addLogStashTcpSocketAppender(context, customFields, loggingProperties.getLogstash()); + } else { + boolean useJsonFormat = loggingProperties.isUseJsonFormat(); + addAllFileAppender(context, logFile, useJsonFormat, customFields); + addErrorFileAppender(context, logErrorFile, useJsonFormat, customFields); } } @Override public void onReset(LoggerContext context) { - if (this.loggingProperties.isUseJsonFormat()) { - addJsonConsoleAppender(context, customFields); - } if (this.loggingProperties.getLogstash().isEnabled()) { - addLogstashTcpSocketAppender(context, customFields, loggingProperties.getLogstash()); + addLogStashTcpSocketAppender(context, customFields, loggingProperties.getLogstash()); + } else { + boolean useJsonFormat = loggingProperties.isUseJsonFormat(); + addAllFileAppender(context, logFile, useJsonFormat, customFields); + addErrorFileAppender(context, logErrorFile, useJsonFormat, customFields); } } diff --git a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingConfiguration.java b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingConfiguration.java index 1eaa87ef..76c7e717 100644 --- a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingConfiguration.java +++ b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingConfiguration.java @@ -41,23 +41,32 @@ public class MicaLoggingConfiguration { @Autowired public MicaLoggingConfiguration(Environment environment, MicaLoggingProperties loggingProperties) { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + // 1. 服务名和环境和日志目录 String appName = environment.getRequiredProperty(MicaConstant.SPRING_APP_NAME_KEY); String profile = environment.getRequiredProperty(MicaConstant.ACTIVE_PROFILES_PROPERTY); - Map map = new HashMap<>(); - map.put("appName", appName); - map.put("profile", profile); - map.put("timestamp", "%date{\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\"}"); - String customFields = JsonUtil.toJson(map); + // 2. 生成日志文件的文件 + String logDir = environment.getProperty("logging.file.path", LoggingUtil.DEFAULT_LOG_DIR); + String logFile = logDir + '/' + appName + "all.log"; + String logErrorFile = logDir + '/' + appName + "error.log"; + // 3. logStash 配置 MicaLoggingProperties.Logstash logStashProperties = loggingProperties.getLogstash(); - if (loggingProperties.isUseJsonFormat()) { - LoggingUtil.addJsonConsoleAppender(context, customFields); - } + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + // 4. json 自定义字段 + Map customFields = new HashMap<>(); + customFields.put("appName", appName); + customFields.put("profile", profile); + customFields.put("timestamp", "%date{\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\"}"); + String customFieldsJson = JsonUtil.toJson(customFields); + // 是否采用 json 格式化 + boolean useJsonFormat = loggingProperties.isUseJsonFormat(); if (logStashProperties.isEnabled()) { - LoggingUtil.addLogstashTcpSocketAppender(context, customFields, logStashProperties); + LoggingUtil.addLogStashTcpSocketAppender(context, customFieldsJson, logStashProperties); + } else { + LoggingUtil.addAllFileAppender(context, logFile, useJsonFormat, customFieldsJson); + LoggingUtil.addErrorFileAppender(context, logErrorFile, useJsonFormat, customFieldsJson); } - if (loggingProperties.isUseJsonFormat() || logStashProperties.isEnabled()) { - LoggingUtil.addContextListener(context, customFields, loggingProperties); + if (useJsonFormat || logStashProperties.isEnabled()) { + LoggingUtil.addContextListener(context, logFile, logErrorFile, customFieldsJson, loggingProperties); } } diff --git a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingProperties.java b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingProperties.java index b2ca1d52..92cd2c73 100644 --- a/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingProperties.java +++ b/mica-logging/src/main/java/net/dreamlu/mica/logging/config/MicaLoggingProperties.java @@ -43,9 +43,9 @@ public class MicaLoggingProperties { @Setter public static class Console { /** - * 是否开启控制台日志 + * 是否启动完成后关闭控制台日志,适用于,正式环境 */ - private boolean enabled = true; + private boolean closeAfterStart = false; } @Getter diff --git a/mica-logging/src/main/resources/file-error.xml b/mica-logging/src/main/resources/file-error.xml deleted file mode 100644 index eaf714df..00000000 --- a/mica-logging/src/main/resources/file-error.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - Error - - - ${FILE_LOG_PATTERN} - - ${LOG_ERROR_FILE} - - ${LOG_FILE_CLEAN_HISTORY_ON_START:-false} - ${LOG_ERROR_FILE}.%d{yyyy-MM-dd}.%i.gz} - ${LOG_FILE_MAX_SIZE:-10MB} - ${LOG_FILE_MAX_HISTORY:-7} - ${LOG_FILE_TOTAL_SIZE_CAP:-0} - - - diff --git a/mica-logging/src/main/resources/logback-spring.xml b/mica-logging/src/main/resources/logback-spring.xml index 3f2ff57d..84cc54f9 100644 --- a/mica-logging/src/main/resources/logback-spring.xml +++ b/mica-logging/src/main/resources/logback-spring.xml @@ -1,21 +1,13 @@ - - - + - - - + - - - - -- GitLab