diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml
index 7fb14f49a..2ba5a7235 100644
--- a/apm-commons/apm-datacarrier/pom.xml
+++ b/apm-commons/apm-datacarrier/pom.xml
@@ -27,4 +27,12 @@
apm-datacarrier
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ test
+
+
+
diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml
index 0a1a6dfaf..93967be75 100644
--- a/apm-commons/apm-util/pom.xml
+++ b/apm-commons/apm-util/pom.xml
@@ -33,4 +33,12 @@
UTF-8
+
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ test
+
+
diff --git a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java
index 163f46b6b..d313ba8c8 100644
--- a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java
+++ b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java
@@ -149,7 +149,7 @@ public class ConfigInitializer {
String propertyStringKey = propertyKey.toString();
if (propertyStringKey.startsWith(prefix) && propertyStringKey.endsWith(suffix)) {
String itemKey = propertyStringKey.substring(
- prefix.length(), propertyStringKey.length() - suffix.length());
+ prefix.length(), propertyStringKey.length() - suffix.length());
Object keyObj;
Object valueObj;
diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml
index 375a94b3b..0d1d27ff4 100644
--- a/apm-sniffer/apm-agent-core/pom.xml
+++ b/apm-sniffer/apm-agent-core/pom.xml
@@ -104,6 +104,11 @@
${ststem-rules.version}
test
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ test
+
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
index e43f11662..47b8ebea3 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
@@ -20,9 +20,11 @@ package org.apache.skywalking.apm.agent.core.conf;
import java.util.HashMap;
import java.util.Map;
+
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.logging.core.LogLevel;
import org.apache.skywalking.apm.agent.core.logging.core.LogOutput;
+import org.apache.skywalking.apm.agent.core.logging.core.ResolverType;
import org.apache.skywalking.apm.agent.core.logging.core.WriterFactory;
import org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ClassCacheMode;
import org.apache.skywalking.apm.util.Length;
@@ -249,6 +251,11 @@ public class Config {
*/
public static LogOutput OUTPUT = LogOutput.FILE;
+ /**
+ * The log resolver type. Default is PATTERN which will create PatternLogResolver later.
+ */
+ public static ResolverType RESOLVER = ResolverType.PATTERN;
+
/**
* The log patten. Default is "%level %timestamp %thread %class : %msg %throwable". Each conversion specifiers
* starts with a percent sign '%' and fis followed by conversion word. There are some default conversion
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java
index d5fbd6a98..06b82c488 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java
@@ -32,6 +32,8 @@ import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException;
import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
+import org.apache.skywalking.apm.agent.core.logging.core.JsonLogResolver;
+import org.apache.skywalking.apm.agent.core.logging.core.PatternLogResolver;
import org.apache.skywalking.apm.util.ConfigInitializer;
import org.apache.skywalking.apm.util.PropertyPlaceholderHelper;
import org.apache.skywalking.apm.util.StringUtil;
@@ -40,7 +42,7 @@ import org.apache.skywalking.apm.util.StringUtil;
* The SnifferConfigInitializer initializes all configs in several way.
*/
public class SnifferConfigInitializer {
- private static final ILog LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
+ private static ILog LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
private static final String SPECIFIED_CONFIG_PATH = "skywalking_config";
private static final String DEFAULT_CONFIG_FILE_NAME = "/config/agent.config";
private static final String ENV_KEY_PREFIX = "skywalking.";
@@ -90,6 +92,9 @@ public class SnifferConfigInitializer {
}
initializeConfig(Config.class);
+ // reconfigure logger after config initialization
+ configureLogger();
+ LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {
throw new ExceptionInInitializerError("`agent.service_name` is missing.");
@@ -207,4 +212,15 @@ public class SnifferConfigInitializer {
}
throw new ConfigNotFoundException("Failed to load agent.config.");
}
+
+ static void configureLogger() {
+ switch (Config.Logging.RESOLVER) {
+ case JSON:
+ LogManager.setLogResolver(new JsonLogResolver());
+ break;
+ case PATTERN:
+ default:
+ LogManager.setLogResolver(new PatternLogResolver());
+ }
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java
new file mode 100644
index 000000000..d58abf409
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java
@@ -0,0 +1,185 @@
+/*
+ * 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.skywalking.apm.agent.core.logging.core;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.AgentNameConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.ClassConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.DateConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.LevelConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.MessageConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.ThreadConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.ThrowableConverter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+/**
+ * An abstract class to simplify the real implementation of the loggers.
+ * It hold the class name of the logger, and is responsible for log level check,
+ * message interpolation, etc.
+ */
+public abstract class AbstractLogger implements ILog {
+ public static final Map> DEFAULT_CONVERTER_MAP = new HashMap<>();
+ protected List converters = new ArrayList<>();
+
+ static {
+ DEFAULT_CONVERTER_MAP.put("thread", ThreadConverter.class);
+ DEFAULT_CONVERTER_MAP.put("level", LevelConverter.class);
+ DEFAULT_CONVERTER_MAP.put("agent_name", AgentNameConverter.class);
+ DEFAULT_CONVERTER_MAP.put("timestamp", DateConverter.class);
+ DEFAULT_CONVERTER_MAP.put("msg", MessageConverter.class);
+ DEFAULT_CONVERTER_MAP.put("throwable", ThrowableConverter.class);
+ DEFAULT_CONVERTER_MAP.put("class", ClassConverter.class);
+ }
+
+ protected final String targetClass;
+
+ public AbstractLogger(String targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ @Override
+ public void info(String message) {
+ if (this.isInfoEnable()) {
+ this.logger(LogLevel.INFO, message, null);
+ }
+ }
+
+ @Override
+ public void info(String message, Object... objects) {
+ if (this.isInfoEnable()) {
+ this.logger(LogLevel.INFO, replaceParam(message, objects), null);
+ }
+ }
+
+ @Override
+ public void warn(String message, Object... objects) {
+ if (this.isWarnEnable()) {
+ this.logger(LogLevel.WARN, replaceParam(message, objects), null);
+ }
+ }
+
+ @Override
+ public void warn(Throwable throwable, String message, Object... objects) {
+ if (this.isWarnEnable()) {
+ this.logger(LogLevel.WARN, replaceParam(message, objects), throwable);
+ }
+ }
+
+ @Override
+ public void error(String message, Throwable throwable) {
+ if (this.isErrorEnable()) {
+ this.logger(LogLevel.ERROR, message, throwable);
+ }
+ }
+
+ @Override
+ public void error(Throwable throwable, String message, Object... objects) {
+ if (this.isErrorEnable()) {
+ this.logger(LogLevel.ERROR, replaceParam(message, objects), throwable);
+ }
+ }
+
+ @Override
+ public void error(String message) {
+ if (this.isErrorEnable()) {
+ this.logger(LogLevel.ERROR, message, null);
+ }
+ }
+
+ @Override
+ public void debug(String message) {
+ if (this.isDebugEnable()) {
+ this.logger(LogLevel.DEBUG, message, null);
+ }
+ }
+
+ @Override
+ public void debug(String message, Object... objects) {
+ if (this.isDebugEnable()) {
+ this.logger(LogLevel.DEBUG, replaceParam(message, objects), null);
+ }
+ }
+
+ @Override
+ public void debug(Throwable throwable, String message, Object... objects) {
+ if (this.isDebugEnable()) {
+ this.logger(LogLevel.DEBUG, replaceParam(message, objects), throwable);
+ }
+ }
+
+ public boolean isDebugEnable() {
+ return LogLevel.DEBUG.compareTo(Config.Logging.LEVEL) >= 0;
+ }
+
+ public boolean isInfoEnable() {
+ return LogLevel.INFO.compareTo(Config.Logging.LEVEL) >= 0;
+ }
+
+ public boolean isWarnEnable() {
+ return LogLevel.WARN.compareTo(Config.Logging.LEVEL) >= 0;
+ }
+
+ public boolean isErrorEnable() {
+ return LogLevel.ERROR.compareTo(Config.Logging.LEVEL) >= 0;
+ }
+
+ protected String replaceParam(String message, Object... parameters) {
+ if (message == null) {
+ return message;
+ }
+ int startSize = 0;
+ int parametersIndex = 0;
+ int index;
+ String tmpMessage = message;
+ while ((index = message.indexOf("{}", startSize)) != -1) {
+ if (parametersIndex >= parameters.length) {
+ break;
+ }
+ /**
+ * @Fix the Illegal group reference issue
+ */
+ tmpMessage = tmpMessage.replaceFirst("\\{\\}", Matcher.quoteReplacement(String.valueOf(parameters[parametersIndex++])));
+ startSize = index + 2;
+ }
+ return tmpMessage;
+ }
+
+ protected void logger(LogLevel level, String message, Throwable e) {
+ WriterFactory.getLogWriter().write(this.format(level, message, e));
+ }
+
+ /**
+ * The abstract method left for real loggers.
+ * Any implementation MUST return string, which will be directly transferred to log destination,
+ * i.e. log files OR stdout
+ *
+ * @param level log level
+ * @param message log message, which has been interpolated with user-defined parameters.
+ * @param e throwable if exists
+ * @return string representation of the log, for example, raw json string for {@link JsonLogger}
+ */
+ protected abstract String format(LogLevel level, String message, Throwable e);
+
+}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java
index 504d816d9..88fa58e6b 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java
@@ -19,10 +19,12 @@
package org.apache.skywalking.apm.agent.core.logging.core;
/**
- * The Converter, It is used to convert the LogEvent to the String.
+ * The Converter, it is used to convert the LogEvent to the String.
+ * For JsonLogger, the `getKey()` method is used to generate the key for json.
*/
public interface Converter {
String convert(LogEvent logEvent);
+ String getKey();
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogResolver.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogResolver.java
new file mode 100644
index 000000000..44dd8e2cd
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogResolver.java
@@ -0,0 +1,37 @@
+/*
+ * 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.skywalking.apm.agent.core.logging.core;
+
+import com.google.gson.Gson;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.api.LogResolver;
+
+public class JsonLogResolver implements LogResolver {
+ private static final Gson GSON = new Gson();
+
+ @Override
+ public ILog getLogger(Class> aClass) {
+ return new JsonLogger(aClass, GSON);
+ }
+
+ @Override
+ public ILog getLogger(String s) {
+ return new JsonLogger(s, GSON);
+ }
+}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogger.java
new file mode 100644
index 000000000..cffd49313
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLogger.java
@@ -0,0 +1,80 @@
+/*
+ * 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.skywalking.apm.agent.core.logging.core;
+
+import com.google.gson.Gson;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.LiteralConverter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An alternative logger for the SkyWalking agent. The default layout is
+ * {
+ * "@timestamp": "", // timestamp
+ * "logger": "", // name of the Logger
+ * "level": "", // info|debug|warn|error
+ * "thread": "", // thread where the log method is called
+ * "message": "", // your log message
+ * "throwable": "",
+ * "agent_name" "service_name"
+ * }
+ */
+public class JsonLogger extends AbstractLogger {
+ private final Gson gson;
+
+ public JsonLogger(Class> targetClass, Gson gson) {
+ this(targetClass.getSimpleName(), gson);
+ }
+
+ /**
+ * In the Constructor, the instances of converters are created,
+ * except those {@link LiteralConverter} since this class is used
+ * only the literals in {@link PatternLogger} ,
+ * and thus should not be added to the json log.
+ *
+ * @param targetClass the logger class
+ * @param gson instance of Gson works as json serializer
+ */
+ public JsonLogger(String targetClass, Gson gson) {
+ super(targetClass);
+ this.gson = gson;
+ for (Map.Entry> entry : DEFAULT_CONVERTER_MAP.entrySet()) {
+ final Class extends Converter> converterClass = entry.getValue();
+ try {
+ if (converters instanceof LiteralConverter) {
+ continue;
+ }
+ converters.add(converterClass.newInstance());
+ } catch (IllegalAccessException | InstantiationException e) {
+ throw new IllegalStateException("Create Converter error. Class: " + converterClass, e);
+ }
+ }
+ }
+
+ @Override
+ protected String format(LogLevel level, String message, Throwable e) {
+ LogEvent logEvent = new LogEvent(level, message, e, this.targetClass);
+ Map log = new HashMap<>();
+ for (Converter converter : this.converters) {
+ log.put(converter.getKey(), converter.convert(logEvent));
+ }
+ return this.gson.toJson(log);
+ }
+}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java
index 8f3fa9bb2..28b10f32b 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java
@@ -18,7 +18,7 @@
package org.apache.skywalking.apm.agent.core.logging.core;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.LiteralConverter;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.LiteralConverter;
import java.util.ArrayList;
import java.util.List;
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java
index 9bad76e91..6ebb002c5 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java
@@ -18,53 +18,25 @@
package org.apache.skywalking.apm.agent.core.logging.core;
-import org.apache.skywalking.apm.agent.core.conf.Config;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.AgentNameConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.ClassConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.DateConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.LevelConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.MessageConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.ThreadConverter;
-import org.apache.skywalking.apm.agent.core.logging.core.coverts.ThrowableConverter;
import org.apache.skywalking.apm.util.StringUtil;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-
/**
* A flexible Logger configurable with pattern string. This is default implementation of {@link ILog} This can parse a
* pattern to the List of converter with Parser. We package LogEvent with message, level,timestamp ..., passing around
* to the List of converter to concat actually Log-String.
*/
-public class PatternLogger implements ILog {
-
- public static final Map> DEFAULT_CONVERTER_MAP = new HashMap>();
-
- static {
- DEFAULT_CONVERTER_MAP.put("thread", ThreadConverter.class);
- DEFAULT_CONVERTER_MAP.put("level", LevelConverter.class);
- DEFAULT_CONVERTER_MAP.put("agent_name", AgentNameConverter.class);
- DEFAULT_CONVERTER_MAP.put("timestamp", DateConverter.class);
- DEFAULT_CONVERTER_MAP.put("msg", MessageConverter.class);
- DEFAULT_CONVERTER_MAP.put("throwable", ThrowableConverter.class);
- DEFAULT_CONVERTER_MAP.put("class", ClassConverter.class);
- }
-
+public class PatternLogger extends AbstractLogger {
public static final String DEFAULT_PATTERN = "%level %timestamp %thread %class : %msg %throwable";
private String pattern;
- private List converters;
- private String targetClass;
- public PatternLogger(Class targetClass, String pattern) {
+ public PatternLogger(Class> targetClass, String pattern) {
this(targetClass.getSimpleName(), pattern);
}
public PatternLogger(String targetClass, String pattern) {
- this.targetClass = targetClass;
+ super(targetClass);
this.setPattern(pattern);
}
@@ -77,122 +49,14 @@ public class PatternLogger implements ILog {
pattern = DEFAULT_PATTERN;
}
this.pattern = pattern;
- converters = new Parser(pattern, DEFAULT_CONVERTER_MAP).parse();
- }
-
- protected void logger(LogLevel level, String message, Throwable e) {
- WriterFactory.getLogWriter().write(format(level, message, e));
- }
-
- private String replaceParam(String message, Object... parameters) {
- if (message == null) {
- return message;
- }
- int startSize = 0;
- int parametersIndex = 0;
- int index;
- String tmpMessage = message;
- while ((index = message.indexOf("{}", startSize)) != -1) {
- if (parametersIndex >= parameters.length) {
- break;
- }
- /**
- * @Fix the Illegal group reference issue
- */
- tmpMessage = tmpMessage.replaceFirst("\\{\\}", Matcher.quoteReplacement(String.valueOf(parameters[parametersIndex++])));
- startSize = index + 2;
- }
- return tmpMessage;
+ this.converters = new Parser(pattern, DEFAULT_CONVERTER_MAP).parse();
}
@Override
- public void info(String format) {
- if (isInfoEnable())
- logger(LogLevel.INFO, format, null);
- }
-
- @Override
- public void info(String format, Object... arguments) {
- if (isInfoEnable())
- logger(LogLevel.INFO, replaceParam(format, arguments), null);
- }
-
- @Override
- public void warn(String format, Object... arguments) {
- if (isWarnEnable())
- logger(LogLevel.WARN, replaceParam(format, arguments), null);
- }
-
- @Override
- public void warn(Throwable e, String format, Object... arguments) {
- if (isWarnEnable())
- logger(LogLevel.WARN, replaceParam(format, arguments), e);
- }
-
- @Override
- public void error(String format, Throwable e) {
- if (isErrorEnable())
- logger(LogLevel.ERROR, format, e);
- }
-
- @Override
- public void error(Throwable e, String format, Object... arguments) {
- if (isErrorEnable())
- logger(LogLevel.ERROR, replaceParam(format, arguments), e);
- }
-
- @Override
- public boolean isDebugEnable() {
- return LogLevel.DEBUG.compareTo(Config.Logging.LEVEL) >= 0;
- }
-
- @Override
- public boolean isInfoEnable() {
- return LogLevel.INFO.compareTo(Config.Logging.LEVEL) >= 0;
- }
-
- @Override
- public boolean isWarnEnable() {
- return LogLevel.WARN.compareTo(Config.Logging.LEVEL) >= 0;
- }
-
- @Override
- public boolean isErrorEnable() {
- return LogLevel.ERROR.compareTo(Config.Logging.LEVEL) >= 0;
- }
-
- @Override
- public void debug(String format) {
- if (isDebugEnable()) {
- logger(LogLevel.DEBUG, format, null);
- }
- }
-
- @Override
- public void debug(String format, Object... arguments) {
- if (isDebugEnable()) {
- logger(LogLevel.DEBUG, replaceParam(format, arguments), null);
- }
- }
-
- @Override
- public void error(String format) {
- if (isErrorEnable()) {
- logger(LogLevel.ERROR, format, null);
- }
- }
-
- @Override
- public void debug(final Throwable t, final String format, final Object... arguments) {
- if (isDebugEnable()) {
- logger(LogLevel.DEBUG, replaceParam(format, arguments), t);
- }
- }
-
- String format(LogLevel level, String message, Throwable t) {
+ protected String format(LogLevel level, String message, Throwable t) {
LogEvent logEvent = new LogEvent(level, message, t, targetClass);
StringBuilder stringBuilder = new StringBuilder();
- for (Converter converter : converters) {
+ for (Converter converter : this.converters) {
stringBuilder.append(converter.convert(logEvent));
}
return stringBuilder.toString();
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/ResolverType.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/ResolverType.java
new file mode 100644
index 000000000..25548b4f2
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/ResolverType.java
@@ -0,0 +1,23 @@
+/*
+ * 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.skywalking.apm.agent.core.logging.core;
+
+public enum ResolverType {
+ JSON, PATTERN
+}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/AgentNameConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/AgentNameConverter.java
similarity index 88%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/AgentNameConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/AgentNameConverter.java
index 0c690a197..67d74bb8d 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/AgentNameConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/AgentNameConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.conf.Config;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
@@ -27,4 +27,9 @@ public class AgentNameConverter implements Converter {
public String convert(LogEvent logEvent) {
return Config.Agent.SERVICE_NAME;
}
+
+ @Override
+ public String getKey() {
+ return "agent_name";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ClassConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ClassConverter.java
similarity index 88%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ClassConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ClassConverter.java
index 3bcf5a2cb..150be5463 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ClassConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ClassConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -30,4 +30,9 @@ public class ClassConverter implements Converter {
public String convert(LogEvent logEvent) {
return logEvent.getTargetClass();
}
+
+ @Override
+ public String getKey() {
+ return "logger";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/DateConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/DateConverter.java
similarity index 89%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/DateConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/DateConverter.java
index 7487556fb..8bfcdc623 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/DateConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/DateConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -33,4 +33,9 @@ public class DateConverter implements Converter {
public String convert(LogEvent logEvent) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date());
}
+
+ @Override
+ public String getKey() {
+ return "@timestamp";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LevelConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LevelConverter.java
similarity index 88%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LevelConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LevelConverter.java
index f016cf3b8..2614b44b6 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LevelConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LevelConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -29,4 +29,9 @@ public class LevelConverter implements Converter {
public String convert(LogEvent logEvent) {
return logEvent.getLevel().name();
}
+
+ @Override
+ public String getKey() {
+ return "level";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LiteralConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LiteralConverter.java
similarity index 90%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LiteralConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LiteralConverter.java
index 411b31a1a..fd9d0355c 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LiteralConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/LiteralConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -36,4 +36,9 @@ public class LiteralConverter implements Converter {
public String convert(LogEvent logEvent) {
return literal;
}
+
+ @Override
+ public String getKey() {
+ return "";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/MessageConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/MessageConverter.java
similarity index 88%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/MessageConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/MessageConverter.java
index 106c26630..97a3f6fa6 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/MessageConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/MessageConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -29,4 +29,9 @@ public class MessageConverter implements Converter {
public String convert(LogEvent logEvent) {
return logEvent.getMessage();
}
+
+ @Override
+ public String getKey() {
+ return "message";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThreadConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThreadConverter.java
similarity index 88%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThreadConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThreadConverter.java
index 45e421dee..888c237ac 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThreadConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThreadConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
import org.apache.skywalking.apm.agent.core.logging.core.LogEvent;
@@ -29,4 +29,9 @@ public class ThreadConverter implements Converter {
public String convert(LogEvent logEvent) {
return Thread.currentThread().getName();
}
+
+ @Override
+ public String getKey() {
+ return "thread";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThrowableConverter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThrowableConverter.java
similarity index 92%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThrowableConverter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThrowableConverter.java
index 106782936..f8cc316ed 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThrowableConverter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/converters/ThrowableConverter.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.skywalking.apm.agent.core.logging.core.coverts;
+package org.apache.skywalking.apm.agent.core.logging.core.converters;
import org.apache.skywalking.apm.agent.core.conf.Constants;
import org.apache.skywalking.apm.agent.core.logging.core.Converter;
@@ -46,4 +46,9 @@ public class ThrowableConverter implements Converter {
}
return Constants.LINE_SEPARATOR + expMessage;
}
+
+ @Override
+ public String getKey() {
+ return "throwable";
+ }
}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLoggerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLoggerTest.java
new file mode 100644
index 000000000..1747d2e88
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/JsonLoggerTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.skywalking.apm.agent.core.logging.core;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.logging.core.converters.ThrowableConverter;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import static org.mockito.Mockito.times;
+
+public class JsonLoggerTest {
+ @BeforeClass
+ public static void initAndHoldOut() {
+ Config.Agent.SERVICE_NAME = "testAppFromConfig";
+ }
+
+ @Test
+ public void testLog() {
+ final IWriter output = Mockito.mock(IWriter.class);
+ JsonLogger logger = new JsonLogger(JsonLoggerTest.class, new Gson()) {
+ @Override
+ protected void logger(LogLevel level, String message, Throwable e) {
+ output.write(format(level, message, e));
+ }
+ };
+
+ Assert.assertTrue(logger.isDebugEnable());
+ Assert.assertTrue(logger.isInfoEnable());
+ Assert.assertTrue(logger.isWarnEnable());
+ Assert.assertTrue(logger.isErrorEnable());
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(String.class);
+ logger.debug("hello world");
+ Mockito.verify(output, times(1)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "DEBUG", null));
+ logger.debug("hello {}", "world");
+ Mockito.verify(output, times(2)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "DEBUG", null));
+ logger.info("hello world");
+ Mockito.verify(output, times(3)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "INFO", null));
+ logger.info("hello {}", "world");
+ Mockito.verify(output, times(4)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "INFO", null));
+
+ logger.warn("hello {}", "world");
+ Mockito.verify(output, times(5)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "WARN", null));
+ logger.warn("hello world");
+ Mockito.verify(output, times(6)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "WARN", null));
+ logger.error("hello world");
+ Mockito.verify(output, times(7)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "ERROR", null));
+ Throwable t = new NullPointerException();
+ logger.error("hello world", t);
+ Mockito.verify(output, times(8)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "ERROR", t));
+ logger.error(t, "hello {}", "world");
+ Mockito.verify(output, times(9)).write(argument.capture());
+ Assert.assertThat(argument.getValue(), createMatcher("hello world", "ERROR", t));
+ }
+
+ private static class LogMatcher extends TypeSafeDiagnosingMatcher {
+ private static final Gson GSON = new Gson();
+ private static final Type MAP_TYPE = new TypeToken
\ No newline at end of file
diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml
index f13ce0f20..dc252632d 100644
--- a/apm-sniffer/apm-test-tools/pom.xml
+++ b/apm-sniffer/apm-test-tools/pom.xml
@@ -47,5 +47,10 @@
${project.version}
provided
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ test
+
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index cbdf94e90..44cb374ac 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -96,7 +96,8 @@ property key | Description | Default |
`logging.file_name`|Log file name.|`skywalking-api.log`|
`logging.output`| Log output. Default is FILE. Use CONSOLE means output to stdout. |`FILE`|
`logging.dir`|Log files directory. Default is blank string, means, use "{theSkywalkingAgentJarDir}/logs " to output logs. {theSkywalkingAgentJarDir} is the directory where the skywalking agent jar file is located |`""`|
-`logging.pattern `|logging format. There are all conversion specifiers:
* `%level` means log level.
* `%timestamp` means now of time with format `yyyy-MM-dd HH:mm:ss:SSS`.
* `%thread` means name of current thread.
* `%msg` means some message which user logged.
* `%class` means SimpleName of TargetClass.
* `%throwable` means a throwable which user called.
* `%agent_name` means `agent.service_name` |`%level %timestamp %thread %class : %msg %throwable`|
+`logging.resolver`|Logger resolver: `PATTERN` or `JSON`. The default is `PATTERN`, which uses `logging.pattern` to print traditional text logs. `JSON` resolver prints logs in JSON format. |`PATTERN`|
+`logging.pattern `|Logging format. There are all conversion specifiers:
* `%level` means log level.
* `%timestamp` means now of time with format `yyyy-MM-dd HH:mm:ss:SSS`.
* `%thread` means name of current thread.
* `%msg` means some message which user logged.
* `%class` means SimpleName of TargetClass.
* `%throwable` means a throwable which user called.
* `%agent_name` means `agent.service_name`. Only apply to the `PatternLogger`. |`%level %timestamp %thread %class : %msg %throwable`|
`logging.max_file_size`|The max size of log file. If the size is bigger than this, archive the current file, and write into a new file.|`300 * 1024 * 1024`|
`logging.max_history_files`|The max history log files. When rollover happened, if log files exceed this number,then the oldest file will be delete. Negative or zero means off, by default.|`-1`|
`jvm.buffer_size`|The buffer size of collected JVM info.|`60 * 10`|
diff --git a/pom.xml b/pom.xml
index cad5f0d08..667fdcdc5 100755
--- a/pom.xml
+++ b/pom.xml
@@ -250,6 +250,7 @@
${jmh.version}
test
+
org.projectlombok
lombok
@@ -290,6 +291,12 @@
${powermock.version}
test
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+ test
+
@@ -588,7 +595,9 @@
org/apache/skywalking/oap/server/core/remote/grpc/proto/*.java,
org/apache/skywalking/oal/rt/grammar/*.java,
org/apache/skywalking/oap/server/exporter/grpc/*.java,
- org/apache/skywalking/oap/server/configuration/service/*.java
+ org/apache/skywalking/oap/server/configuration/service/*.java,
+ **/generated/*_jmhType*.java,
+ **/generated/*_jmhTest.java
import.control=apm-checkstyle/importControl.xml