diff --git a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/PlaceholderConfigurerSupport.java b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/PlaceholderConfigurerSupport.java index 493d6b8e2b0f629b0dd5ed037abed2f1dd1bdf78..7f96b25dd458d1e214ef9df6b2fb19764d666fa4 100644 --- a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/PlaceholderConfigurerSupport.java +++ b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/PlaceholderConfigurerSupport.java @@ -31,4 +31,5 @@ public class PlaceholderConfigurerSupport { /** Default value separator: {@value} */ public static final String DEFAULT_VALUE_SEPARATOR = ":"; + } 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 145f1d26fbe220562c3624ca6d1bcd180826e36c..d5cb7686c8cc1be25abd5971ca326ed6bdbfae5a 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 @@ -21,6 +21,7 @@ package org.apache.skywalking.apm.agent.core.conf; 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.WriterFactory; import java.util.HashMap; @@ -169,6 +170,28 @@ public class Config { * The log level. Default is debug. */ public static LogLevel LEVEL = LogLevel.DEBUG; + + /** + * The log output. Default is FILE. + */ + public static LogOutput OUTPUT = LogOutput.FILE; + + /** + * 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 specifiers: + * %thread = ThreadName + * %level = LogLevel {@link LogLevel} + * %timestamp = The now() who format is 'yyyy-MM-dd HH:mm:ss:SSS' + * %class = SimpleName of TargetClass + * %msg = Message of user input + * %throwable = Throwable of user input + * %agent_name = ServiceName of Agent {@link Agent#SERVICE_NAME} + * + * @see org.apache.skywalking.apm.agent.core.logging.core.PatternLogger#DEFAULT_CONVERTER_MAP + * + */ + public static String PATTERN = "%level %timestamp %thread %class : %msg %throwable"; } public static class Plugin { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/LogManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/LogManager.java index 3f3b2e81455d86159d928a835cb162c46ba92d4f..a8afb250fccfe50b3b7b632921c41d4dd5d0adef 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/LogManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/api/LogManager.java @@ -19,7 +19,7 @@ package org.apache.skywalking.apm.agent.core.logging.api; -import org.apache.skywalking.apm.agent.core.logging.core.EasyLogResolver; +import org.apache.skywalking.apm.agent.core.logging.core.PatternLogResolver; /** * LogManager is the {@link LogResolver} implementation manager. By using {@link LogResolver}, {@link @@ -34,7 +34,7 @@ import org.apache.skywalking.apm.agent.core.logging.core.EasyLogResolver; *

Created by xin on 2016/11/10. */ public class LogManager { - private static LogResolver RESOLVER = new EasyLogResolver(); + private static LogResolver RESOLVER = new PatternLogResolver(); public static void setLogResolver(LogResolver resolver) { LogManager.RESOLVER = resolver; 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 new file mode 100644 index 0000000000000000000000000000000000000000..05612263f62e137292359d76b7a277039d6a3bc1 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java @@ -0,0 +1,31 @@ +/* + * 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; + + +/** + * The Converter, It is used to convert the LogEvent to the String. + * @author alvin + */ +public interface Converter { + + String convert(LogEvent logEvent); + +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogEvent.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..7783134e666d92c469cbd58af2ecd17ecb906fd2 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogEvent.java @@ -0,0 +1,72 @@ +/* + * 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; + +/** + * The representation of logging events. This instance is pass around to the List of Converter. + * + * @author alvin + */ +public class LogEvent { + + public LogEvent(LogLevel level, String message, Throwable throwable, String targetClass) { + this.level = level; + this.message = message; + this.throwable = throwable; + this.targetClass = targetClass; + } + + private LogLevel level; + private String message; + private Throwable throwable; + private String targetClass; + + public String getTargetClass() { + return targetClass; + } + + public void setTargetClass(String targetClass) { + this.targetClass = targetClass; + } + + public LogLevel getLevel() { + return level; + } + + public void setLevel(LogLevel level) { + this.level = level; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Throwable getThrowable() { + return throwable; + } + + public void setThrowable(Throwable throwable) { + this.throwable = throwable; + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogOutput.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogOutput.java new file mode 100644 index 0000000000000000000000000000000000000000..556654cc0d0cc4dcdf358cb84624e873ea50c7a3 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogOutput.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * @author alvin + */ +public enum LogOutput { + FILE, CONSOLE +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..743364eff62a8eda40370c74053b8917953ce526 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java @@ -0,0 +1,195 @@ +/* + * 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.logging.core.coverts.LiteralConverter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Parser of LogPattern. It is used to parse a pattern to the List of Converter. + * @author alvin + */ +public class Parser { + private final Map> convertMaps; + + enum State { + LITERAL_STATE, KEYWORD_STATE + } + + + public static final char ESCAPE_CHAR = '\\'; + public static final char PERCENT_CHAR = '%'; + + private final String pattern; + private final int patternLength; + private int pointer = 0; + private State state = State.LITERAL_STATE; + + + public Parser(String pattern, Map> convertMaps) { + if (pattern == null || pattern.length() == 0) { + throw new IllegalArgumentException("null or empty pattern string not allowed"); + } + this.convertMaps = convertMaps; + this.pattern = pattern; + this.patternLength = pattern.length(); + } + + public List parse() { + List patternConverters = new ArrayList(); + StringBuilder buf = new StringBuilder(); + while (pointer < patternLength) { + char c = pattern.charAt(pointer); + pointer++; + switch (state) { + case LITERAL_STATE: + handleLiteralState(c, buf, patternConverters); + break; + case KEYWORD_STATE: + handleKeywordState(c, buf, patternConverters); + break; + default: + } + } + + switch (state) { + case LITERAL_STATE: + addConverter(buf, patternConverters, LiteralConverter.class); + break; + case KEYWORD_STATE: + addConverterWithKeyword(buf, patternConverters); + break; + default: + } + return combineLiteral(patternConverters); + } + + private List combineLiteral(List patternConverters) { + List converterList = new ArrayList(); + StringBuilder stringBuilder = new StringBuilder(); + for (Converter patternConverter : patternConverters) { + if (patternConverter instanceof LiteralConverter) { + stringBuilder.append(patternConverter.convert(null)); + } else { + if (stringBuilder.length() > 0) { + converterList.add(new LiteralConverter(stringBuilder.toString())); + stringBuilder.setLength(0); + } + converterList.add(patternConverter); + } + } + return converterList; + } + + private void handleKeywordState(char c, StringBuilder buf, List patternConverters) { + if (Character.isJavaIdentifierPart(c)) { + buf.append(c); + } else if (c == PERCENT_CHAR) { + addConverterWithKeyword(buf, patternConverters); + } else { + addConverterWithKeyword(buf, patternConverters); + if (c == ESCAPE_CHAR) { + escape("%", buf); + } else { + buf.append(c); + } + state = State.LITERAL_STATE; + } + } + + private void addConverterWithKeyword(StringBuilder buf, List patternConverters) { + String keyword = buf.toString(); + if (convertMaps.containsKey(keyword)) { + addConverter(buf, patternConverters, convertMaps.get(keyword)); + } else { + buf.insert(0, "%"); + addConverter(buf, patternConverters, LiteralConverter.class); + } + } + + private void handleLiteralState(char c, StringBuilder buf, List patternConverters) { + switch (c) { + case ESCAPE_CHAR: + escape("%", buf); + break; + case PERCENT_CHAR: + addConverter(buf, patternConverters, LiteralConverter.class); + state = State.KEYWORD_STATE; + break; + default: + buf.append(c); + } + + } + + private void escape(String escapeChars, StringBuilder buf) { + if (pointer < patternLength) { + char next = pattern.charAt(pointer++); + escape(escapeChars, buf, next); + } + } + + private void addConverter(StringBuilder buf, List patternConverters, Class aClass) { + if (buf.length() > 0) { + String result = buf.toString(); + if (LiteralConverter.class.equals(aClass)) { + patternConverters.add(new LiteralConverter(result)); + } else { + try { + patternConverters.add(aClass.newInstance()); + } catch (Exception e) { + throw new IllegalStateException("Create Converter error. Class: " + aClass, e); + } + } + buf.setLength(0); + } + } + + private void escape(String escapeChars, StringBuilder buf, char next) { + if (escapeChars.indexOf(next) >= 0) { + buf.append(next); + } else { + switch (next) { + case '_': + // the \_ sequence is swallowed + break; + case '\\': + buf.append(next); + break; + case 't': + buf.append('\t'); + break; + case 'r': + buf.append('\r'); + break; + case 'n': + buf.append('\n'); + break; + default: + throw new IllegalArgumentException("Illegal char " + next + ". It not allowed as escape characters."); + } + } + } + + +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolver.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolver.java similarity index 77% rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolver.java rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolver.java index 238cd56e5339eb77fae9385e706b319b39185f11..328cc513e9cddf5b98765b1a4d82d28b40594b3d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolver.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolver.java @@ -19,19 +19,22 @@ 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.api.LogResolver; /** - * Created by wusheng on 2016/11/26. + * @author alvin */ -public class EasyLogResolver implements LogResolver { +public class PatternLogResolver implements LogResolver { + @Override public ILog getLogger(Class clazz) { - return new EasyLogger(clazz); + return new PatternLogger(clazz, Config.Logging.PATTERN); } - @Override public ILog getLogger(String clazz) { - return new EasyLogger(clazz); + @Override + public ILog getLogger(String clazz) { + return new PatternLogger(clazz, Config.Logging.PATTERN); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java similarity index 60% rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java index c548b9aa9e842b38c26d3c15f4a460c9c07bc716..a03341cdbabb3a39c78e7cc5f19ab7375ec6c89d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogger.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogger.java @@ -16,36 +16,75 @@ * */ - package org.apache.skywalking.apm.agent.core.logging.core; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.regex.Matcher; import org.apache.skywalking.apm.agent.core.conf.Config; -import org.apache.skywalking.apm.agent.core.conf.Constants; 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; + /** - * The EasyLogger is a simple implementation of {@link ILog}. + * 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. * - * @author wusheng + * @author alvin */ -public class EasyLogger implements ILog { +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 static final String DEFAULT_PATTERN = "%level %timestamp %thread %class : %msg %throwable"; + + private String pattern; + private List converters; private String targetClass; - public EasyLogger(Class targetClass) { - this.targetClass = targetClass.getSimpleName(); + public PatternLogger(Class targetClass, String pattern) { + this(targetClass.getSimpleName(), pattern); } - public EasyLogger(String targetClass) { + public PatternLogger(String targetClass, String pattern) { this.targetClass = targetClass; + this.setPattern(pattern); + } + + public String getPattern() { + return pattern; } + public void setPattern(String pattern) { + if (StringUtil.isEmpty(pattern)) { + 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)); } @@ -68,30 +107,6 @@ public class EasyLogger implements ILog { return tmpMessage; } - String format(LogLevel level, String message, Throwable t) { - return StringUtil.join(' ', level.name(), - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()), - Thread.currentThread().getName(), - targetClass, - ": ", - message, - t == null ? "" : format(t) - ); - } - - String format(Throwable t) { - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - t.printStackTrace(new java.io.PrintWriter(buf, true)); - String expMessage = buf.toString(); - try { - buf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - return Constants.LINE_SEPARATOR + expMessage; - } - @Override public void info(String format) { if (isInfoEnable()) @@ -168,4 +183,14 @@ public class EasyLogger implements ILog { logger(LogLevel.ERROR, format, null); } } + + + String format(LogLevel level, String message, Throwable t) { + LogEvent logEvent = new LogEvent(level, message, t, targetClass); + StringBuilder stringBuilder = new StringBuilder(); + for (Converter converter : 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/WriterFactory.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java index 4bc357d2dfb0d0027a573c216fabe030cfada659..8c9a619ffa86f6afdea6bfc7e4c0901c0c02950a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java @@ -27,7 +27,7 @@ import org.apache.skywalking.apm.util.StringUtil; public class WriterFactory { public static IWriter getLogWriter() { - if (SnifferConfigInitializer.isInitCompleted() && AgentPackagePath.isPathFound()) { + if (!useConsole() && SnifferConfigInitializer.isInitCompleted() && AgentPackagePath.isPathFound()) { if (StringUtil.isEmpty(Config.Logging.DIR)) { try { Config.Logging.DIR = AgentPackagePath.getPath() + "/logs"; @@ -40,4 +40,8 @@ public class WriterFactory { return SystemOutWriter.INSTANCE; } } + + private static boolean useConsole() { + return LogOutput.CONSOLE == Config.Logging.OUTPUT; + } } 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/coverts/AgentNameConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..3b47c809941aff2be460d8be4fe59766eb228f3b --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/AgentNameConverter.java @@ -0,0 +1,35 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * + * @author alvin + */ +public class AgentNameConverter implements Converter { + @Override + public String convert(LogEvent logEvent) { + return Config.Agent.SERVICE_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/coverts/ClassConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..650b2c4c8dc0f0991e87ae0045585c954b390704 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ClassConverter.java @@ -0,0 +1,36 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * Just return logEvent.getTargetClass(). + * @author alvin + */ +public class ClassConverter implements Converter { + + + @Override + public String convert(LogEvent logEvent) { + return logEvent.getTargetClass(); + } +} 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/coverts/DateConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..c4cbc4f52e929d79e16ab189208eb3ca8c48e346 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/DateConverter.java @@ -0,0 +1,39 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * The Converter is used to return a now date with format. + * + * @author alvin + */ +public class DateConverter implements Converter { + + @Override + public String convert(LogEvent logEvent) { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()); + } +} 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/coverts/LevelConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..83e57b82f3fbdd4388e06189cfc1c5c6451f0ad3 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LevelConverter.java @@ -0,0 +1,34 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * Just return logEvent.getLevel().name() + * @author alvin + */ +public class LevelConverter implements Converter { + @Override + public String convert(LogEvent logEvent) { + return logEvent.getLevel().name(); + } +} 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/coverts/LiteralConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..2fbb413438920b320d482bfd6350b1cf3e8c0cdd --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LiteralConverter.java @@ -0,0 +1,41 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * This Converter is used to return the literal. + * @author alvin + */ +public class LiteralConverter implements Converter { + + private final String literal; + + public LiteralConverter(String literal) { + this.literal = literal; + } + + @Override + public String convert(LogEvent logEvent) { + return literal; + } +} 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/coverts/MessageConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..4bd34b36000a4bd5a495983372a6efe1c397ccc4 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/MessageConverter.java @@ -0,0 +1,34 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * Just return the logEvent.getMessage() + * @author alvin + */ +public class MessageConverter implements Converter { + @Override + public String convert(LogEvent logEvent) { + return logEvent.getMessage(); + } +} 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/coverts/ThreadConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..6fc2ba9ace1a73ba91787397505ca49b6f45cd2a --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThreadConverter.java @@ -0,0 +1,34 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +/** + * Just return the Thread.currentThread().getName() + * @author alvin + */ +public class ThreadConverter implements Converter { + @Override + public String convert(LogEvent logEvent) { + return Thread.currentThread().getName(); + } +} 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/coverts/ThrowableConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..09797e11f96e619f9c2667dd08e2c5d3a1415d46 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThrowableConverter.java @@ -0,0 +1,51 @@ +/* + * 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.coverts; + +import org.apache.skywalking.apm.agent.core.conf.Constants; +import org.apache.skywalking.apm.agent.core.logging.core.Converter; +import org.apache.skywalking.apm.agent.core.logging.core.LogEvent; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Return the StackTrace of String with logEvent.getThrowable() + * @author alvin + */ +public class ThrowableConverter implements Converter { + @Override + public String convert(LogEvent logEvent) { + Throwable t = logEvent.getThrowable(); + return t == null ? "" : format(t); + } + + public static String format(Throwable t) { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + t.printStackTrace(new java.io.PrintWriter(buf, true)); + String expMessage = buf.toString(); + try { + buf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return Constants.LINE_SEPARATOR + expMessage; + } +} diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolverTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolverTest.java similarity index 84% rename from apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolverTest.java rename to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolverTest.java index 5e4bea48df015696bb442724c00ff162726582e2..3cdb748255fe772c7802b72bcc68a1bc8b65ec8e 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLogResolverTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLogResolverTest.java @@ -23,11 +23,13 @@ import org.junit.Assert; import org.junit.Test; /** - * Created by wusheng on 2017/2/28. + * @author alvin */ -public class EasyLogResolverTest { +public class PatternLogResolverTest { + @Test public void testGetLogger() { - Assert.assertTrue(new EasyLogResolver().getLogger(EasyLogResolverTest.class) instanceof EasyLogger); + Assert.assertTrue(new PatternLogResolver().getLogger(PatternLoggerTest.class) instanceof PatternLogger); } -} + +} \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLoggerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java similarity index 64% rename from apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLoggerTest.java rename to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java index e3a7d2226f12b1843f9561d101045078a9ab5549..f940b091265cc59f66d04937f6ea8f3b9ff4dfc0 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/EasyLoggerTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/PatternLoggerTest.java @@ -19,22 +19,29 @@ package org.apache.skywalking.apm.agent.core.logging.core; +import com.google.common.collect.Lists; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.conf.Constants; +import org.hamcrest.core.StringContains; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; -import org.apache.skywalking.apm.agent.core.conf.Constants; import java.io.PrintStream; +import java.util.List; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.times; /** - * Created by wusheng on 2017/2/28. + * @author alvin */ -public class EasyLoggerTest { +public class PatternLoggerTest { + + public static final String PATTERN = "%timestamp+0800 %level [%agent_name,,,] [%thread] %class:-1 %msg %throwable"; + private static PrintStream OUT_REF; private static PrintStream ERR_REF; @@ -42,18 +49,21 @@ public class EasyLoggerTest { public static void initAndHoldOut() { OUT_REF = System.out; ERR_REF = System.err; + Config.Agent.SERVICE_NAME = "testAppFromConfig"; } + @Test public void testLog() { PrintStream output = Mockito.mock(PrintStream.class); System.setOut(output); PrintStream err = Mockito.mock(PrintStream.class); System.setErr(err); - EasyLogger logger = new EasyLogger(EasyLoggerTest.class) { + PatternLogger logger = new PatternLogger(PatternLoggerTest.class, PATTERN) { @Override protected void logger(LogLevel level, String message, Throwable e) { - SystemOutWriter.INSTANCE.write(format(level, message, e)); + String r = format(level, message, e); + SystemOutWriter.INSTANCE.write(r); } }; @@ -83,7 +93,7 @@ public class EasyLoggerTest { System.setOut(output); PrintStream err = Mockito.mock(PrintStream.class); System.setErr(err); - EasyLogger logger = new EasyLogger(EasyLoggerTest.class) { + PatternLogger logger = new PatternLogger(PatternLoggerTest.class, PATTERN) { @Override protected void logger(LogLevel level, String message, Throwable e) { SystemOutWriter.INSTANCE.write(format(level, message, e)); @@ -111,18 +121,45 @@ public class EasyLoggerTest { } @Test - public void testFormat() { + public void testLogOk_whenPatternHasKeyword() { + final List strings = Lists.newArrayList(); + PatternLogger logger = new PatternLogger(PatternLoggerTest.class, "logmsg: %%%%%%!@#$\\%^&*() %{this is message} \\\\ \\n\\t \t\n %%msg") { + @Override + protected void logger(LogLevel level, String message, Throwable e) { + String r = format(level, message, e); + strings.add(r); + } + }; + logger.info("msg"); + Assert.assertThat(strings.get(0), StringContains.containsString("logmsg: %%%%%%!@#$%^&*() %{this is message} \\ \n\t \t\n %msg")); + } + + @Test + public void testLogFormat() { + final List strings = Lists.newArrayList(); + PatternLogger logger = new PatternLogger(PatternLoggerTest.class, PATTERN) { + @Override + protected void logger(LogLevel level, String message, Throwable e) { + String r = format(level, message, e); + strings.add(r); + } + }; NullPointerException exception = new NullPointerException(); - EasyLogger logger = new EasyLogger(EasyLoggerTest.class); - String formatLines = logger.format(exception); + logger.error("hello world", exception); + logger.error("hello world", null); + String formatLines = strings.get(0); String[] lines = formatLines.split(Constants.LINE_SEPARATOR); + Assert.assertThat(lines[0], StringContains.containsString("ERROR [testAppFromConfig,,,] [main] PatternLoggerTest:-1 hello world ")); Assert.assertEquals("java.lang.NullPointerException", lines[1]); - Assert.assertEquals("\tat org.apache.skywalking.apm.agent.core.logging.core.EasyLoggerTest.testFormat(EasyLoggerTest.java:115)", lines[2]); + Assert.assertThat(lines[2], StringContains.containsString("PatternLoggerTest.testLogFormat")); + Assert.assertEquals(strings.get(1).split(Constants.LINE_SEPARATOR).length, 1); } + @AfterClass public static void reset() { System.setOut(OUT_REF); System.setErr(ERR_REF); } + } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aca5164c8fb8feca6065a79b22fd7f39379e88a2 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java @@ -0,0 +1,69 @@ +/* + * 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.boot.AgentPackagePath; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.junit.Assert.assertTrue; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(value = {SnifferConfigInitializer.class, AgentPackagePath.class}) +public class WriterFactoryTest { + + @Test + public void alwaysReturnSystemLogWriteWithSetLoggingDir() { + Config.Logging.OUTPUT = LogOutput.CONSOLE; + PowerMockito.mockStatic(SnifferConfigInitializer.class); + PowerMockito.mockStatic(AgentPackagePath.class); + BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); + BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); + + assertTrue(SnifferConfigInitializer.isInitCompleted()); + assertTrue(AgentPackagePath.isPathFound()); + + IWriter logWriter = WriterFactory.getLogWriter(); + PowerMockito.verifyStatic(); + assertTrue(logWriter instanceof SystemOutWriter); + } + + @Test + public void returnFileWriterWriteWithBlankLoggingDir() { + Config.Logging.OUTPUT = LogOutput.FILE; + PowerMockito.mockStatic(SnifferConfigInitializer.class); + PowerMockito.mockStatic(AgentPackagePath.class); + BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); + BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); + + assertTrue(SnifferConfigInitializer.isInitCompleted()); + assertTrue(AgentPackagePath.isPathFound()); + + IWriter logWriter = WriterFactory.getLogWriter(); + PowerMockito.verifyStatic(); + assertTrue(logWriter instanceof FileWriter); + } +} \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index 4d7e556ff21349ee23aa02cb98284b6f36e28603..3dfb2dfca40f0c22c7fe195c9b7c69fddc7df314 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -82,7 +82,9 @@ property key | Description | Default | `collector.backend_service`|Collector SkyWalking trace receiver service addresses.|`127.0.0.1:11800`| `logging.level`|The log level. Default is debug.|`DEBUG`| `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 "system.out" to output logs.|`""`| +`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.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`| `jvm.buffer_size`|The buffer size of collected JVM info.|`60 * 10`| `buffer.channel_size`|The buffer channel size.|`5`|