This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push: new 60236a2 Add feature to control the maximum agent log files (#3475) 60236a2 is described below commit 60236a27d6a5b409451a91d3de1c2115a6ed2ff6 Author: wuguangkuo <wuguang...@126.com> AuthorDate: Thu Sep 19 14:12:17 2019 +0800 Add feature to control the maximum agent log files (#3475) * Add feature to control the maximum history agent log files. --- .../skywalking/apm/agent/core/conf/Config.java | 6 +++ .../apm/agent/core/logging/core/FileWriter.java | 59 +++++++++++++++++++--- .../agent/core/logging/core/FileWriterTest.java | 29 ++++++++++- apm-sniffer/config/agent.config | 4 ++ docs/en/setup/service-agent/java-agent/README.md | 1 + 5 files changed, 90 insertions(+), 9 deletions(-) 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 5a8eca4..a19f75d 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 @@ -176,6 +176,12 @@ public class Config { public static int MAX_FILE_SIZE = 300 * 1024 * 1024; /** + * The max history log files. When rollover happened, if log files exceed this number, + * then the oldest file will be delete. Negative or zero means off, by default. + */ + public static int MAX_HISTORY_FILES = -1; + + /** * The log level. Default is debug. */ public static LogLevel LEVEL = LogLevel.DEBUG; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java index 279df37..00faa4f 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java @@ -19,21 +19,22 @@ package org.apache.skywalking.apm.agent.core.logging.core; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; +import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.conf.Constants; +import org.apache.skywalking.apm.util.RunnableWithExceptionProtection; + +import java.io.*; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.Date; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; -import org.apache.skywalking.apm.agent.core.conf.Config; -import org.apache.skywalking.apm.agent.core.conf.Constants; -import org.apache.skywalking.apm.util.RunnableWithExceptionProtection; +import java.util.regex.Pattern; /** * The <code>FileWriter</code> support async file output, by using a queue as buffer. @@ -46,6 +47,7 @@ public class FileWriter implements IWriter { private FileOutputStream fileOutputStream; private ArrayBlockingQueue logBuffer; private volatile int fileSize; + private Pattern filenamePattern = Pattern.compile(Config.Logging.FILE_NAME + "\\.\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}"); public static FileWriter get() { if (INSTANCE == null) { @@ -134,6 +136,47 @@ public class FileWriter implements IWriter { return null; } }); + + if (Config.Logging.MAX_HISTORY_FILES > 0) { + deleteExpiredFiles(); + } + } + } + + /** + * load history log file name array + * @return history log file name array + */ + private String[] getHistoryFilePath() { + File path = new File(Config.Logging.DIR); + String[] pathArr = path.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return filenamePattern.matcher(name).matches(); + } + }); + + return pathArr; + } + + /** + * delete expired log files + */ + private void deleteExpiredFiles() { + String[] historyFileArr = getHistoryFilePath(); + if (historyFileArr != null && historyFileArr.length > Config.Logging.MAX_HISTORY_FILES) { + + Arrays.sort(historyFileArr, new Comparator<String>() { + @Override + public int compare(String o1, String o2) { + return o2.compareTo(o1); + } + }); + + for (int i = Config.Logging.MAX_HISTORY_FILES; i < historyFileArr.length; i++) { + File expiredFile = new File(Config.Logging.DIR, historyFileArr[i]); + expiredFile.delete(); + } } } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriterTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriterTest.java index 3967e7c..3275419 100755 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriterTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriterTest.java @@ -26,7 +26,12 @@ import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.conf.Constants; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; +import java.util.UUID; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; /** * @author wusheng @@ -37,7 +42,8 @@ public class FileWriterTest { public static void beforeTestFile() throws IOException { Config.Logging.MAX_FILE_SIZE = 10; File directory = new File(System.getProperty("java.io.tmpdir", "/tmp")); - Config.Logging.DIR = directory.getCanonicalPath() + Constants.PATH_SEPARATOR + "/log-test/"; + String dirName4Unique = UUID.randomUUID().toString(); + Config.Logging.DIR = directory.getCanonicalPath() + Constants.PATH_SEPARATOR + "log-test_" + dirName4Unique; } @Test @@ -50,6 +56,27 @@ public class FileWriterTest { Thread.sleep(10000L); } + @Test + public void testDeleteWhenRollover() throws InterruptedException { + Config.Logging.MAX_HISTORY_FILES = 3; + FileWriter writer = FileWriter.get(); + for (int i = 0; i < 4; i++) { + writer.write("abcdefghij"); + Thread.sleep(1000); + } + + final Pattern filenamePattern = Pattern.compile(Config.Logging.FILE_NAME + "\\.\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}"); + File path = new File(Config.Logging.DIR); + String[] pathArr = path.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return filenamePattern.matcher(name).matches(); + } + }); + + assertEquals(3, pathArr.length); + } + @AfterClass public static void clear() { Config.Logging.MAX_FILE_SIZE = 300 * 1024 * 1024; diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 3507ede..6e03ff2 100644 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -56,5 +56,9 @@ logging.level=${SW_LOGGING_LEVEL:DEBUG} # Logging max_file_size, default: 300 * 1024 * 1024 = 314572800 # logging.max_file_size=${SW_LOGGING_MAX_FILE_SIZE:314572800} +# The max history log files. When rollover happened, if log files exceed this number, +# then the oldest file will be delete. Negative or zero means off, by default. +# logging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:-1} + # mysql plugin configuration # plugin.mysql.trace_sql_parameters=${SW_MYSQL_TRACE_SQL_PARAMETERS:false} \ 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 e3fa37d..8d798e0 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -88,6 +88,7 @@ property key | Description | Default | `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: <br> * `%level` means log level. <br> * `%timestamp` means now of time with format `yyyy-MM-dd HH:mm:ss:SSS`.<br> * `%thread` means name of current thread.<br> * `%msg` means some message which user logged. <br> * `%class` means SimpleName of TargetClass. <br> * `%throwable` means a throwable which user called. <br> * `%agent_name` m [...] `logging.max_file_size`|The max size of log file. If the size is bigger than this, archive the current file, and write into a new file.|`300 * 1024 * 1024`| +`logging.max_history_files`|The max history log files. When rollover happened, if log files exceed this number,then the oldest file will be delete. Negative or zero means off, by default.|`-1`| `jvm.buffer_size`|The buffer size of collected JVM info.|`60 * 10`| `buffer.channel_size`|The buffer channel size.|`5`| `buffer.buffer_size`|The buffer size.|`300`|