From ffe1df579f26e3822b3def3e5620eca3f267442e Mon Sep 17 00:00:00 2001
From: Alvin <329772643@qq.com>
Date: Wed, 14 Aug 2019 14:31:24 +0800
Subject: [PATCH] Enhance agent logger. (#3250)
* Add pattern logger to replace the easy logger.
* Doc update
* Support console log
---
.../util/PlaceholderConfigurerSupport.java | 1 +
.../apm/agent/core/conf/Config.java | 23 +++
.../agent/core/logging/api/LogManager.java | 4 +-
.../agent/core/logging/core/Converter.java | 31 +++
.../apm/agent/core/logging/core/LogEvent.java | 72 +++++++
.../agent/core/logging/core/LogOutput.java | 27 +++
.../apm/agent/core/logging/core/Parser.java | 195 ++++++++++++++++++
...gResolver.java => PatternLogResolver.java} | 13 +-
.../{EasyLogger.java => PatternLogger.java} | 99 +++++----
.../core/logging/core/WriterFactory.java | 6 +-
.../core/coverts/AgentNameConverter.java | 35 ++++
.../logging/core/coverts/ClassConverter.java | 36 ++++
.../logging/core/coverts/DateConverter.java | 39 ++++
.../logging/core/coverts/LevelConverter.java | 34 +++
.../core/coverts/LiteralConverter.java | 41 ++++
.../core/coverts/MessageConverter.java | 34 +++
.../logging/core/coverts/ThreadConverter.java | 34 +++
.../core/coverts/ThrowableConverter.java | 51 +++++
...rTest.java => PatternLogResolverTest.java} | 10 +-
...LoggerTest.java => PatternLoggerTest.java} | 57 ++++-
.../core/logging/core/WriterFactoryTest.java | 69 +++++++
.../setup/service-agent/java-agent/README.md | 2 +
22 files changed, 854 insertions(+), 59 deletions(-)
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Converter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogEvent.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/LogOutput.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/Parser.java
rename apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/{EasyLogResolver.java => PatternLogResolver.java} (77%)
rename apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/{EasyLogger.java => PatternLogger.java} (60%)
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/AgentNameConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ClassConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/DateConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LevelConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/LiteralConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/MessageConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThreadConverter.java
create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/coverts/ThrowableConverter.java
rename apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/{EasyLogResolverTest.java => PatternLogResolverTest.java} (84%)
rename apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/{EasyLoggerTest.java => PatternLoggerTest.java} (64%)
create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java
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 493d6b8e2b..7f96b25dd4 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 145f1d26fb..d5cb7686c8 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 3f3b2e8145..a8afb250fc 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 0000000000..05612263f6
--- /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 0000000000..7783134e66
--- /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 0000000000..556654cc0d
--- /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 0000000000..743364eff6
--- /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 extends Converter> 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 238cd56e53..328cc513e9 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 c548b9aa9e..a03341cdba 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 4bc357d2df..8c9a619ffa 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 0000000000..3b47c80994
--- /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 0000000000..650b2c4c8d
--- /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 0000000000..c4cbc4f52e
--- /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 0000000000..83e57b82f3
--- /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 0000000000..2fbb413438
--- /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 0000000000..4bd34b3600
--- /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 0000000000..6fc2ba9ace
--- /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 0000000000..09797e11f9
--- /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 5e4bea48df..3cdb748255 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 e3a7d2226f..f940b09126 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 0000000000..aca5164c8f
--- /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 4d7e556ff2..3dfb2dfca4 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`|
--
GitLab