diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61d50f7bda..23fab77fe4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,11 +20,11 @@ jobs: uses: actions/setup-java@v3 with: java-version: ${{ matrix.java }} - distribution: 'adopt' + distribution: 'temurin' architecture: x64 - name: Test with Maven - run: mvn test + run: mvn --batch-mode test - name: Build with Maven run: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V -DminimumPriority=1 diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandler.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandler.java index b74def65d3..bd5992ccd6 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandler.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandler.java @@ -18,14 +18,12 @@ import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; import java.io.UnsupportedEncodingException; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.logging.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.StreamHandler; /** * This Handler publishes log records to console by using {@link java.util.logging.StreamHandler}. @@ -41,6 +39,19 @@ * @author cdfive */ class ConsoleHandler extends Handler { + private static final ThreadPoolExecutor executor = new ThreadPoolExecutor( + 1, + 5, + 1, + TimeUnit.HOURS, + new ArrayBlockingQueue<>(1024), + new NamedThreadFactory("sentinel-console-log-executor", true), + new LogRejectedExecutionHandler() + ); + + static { + executor.allowCoreThreadTimeOut(true); + } /** * A Handler which publishes log records to System.out. @@ -52,21 +63,11 @@ class ConsoleHandler extends Handler { */ private StreamHandler stderrHandler; - private ExecutorService executor; + private AtomicReference> lastFuture = new AtomicReference<>(); public ConsoleHandler() { this.stdoutHandler = new StreamHandler(System.out, new CspFormatter()); this.stderrHandler = new StreamHandler(System.err, new CspFormatter()); - - int corePoolSize = 1; - int maximumPoolSize = 1; - long keepAliveTime = 0; - /**insure the log can be recorded*/ - int queueSize = 1024; - RejectedExecutionHandler handler = new LogRejectedExecutionHandler(); - executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, - keepAliveTime, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(queueSize), - new NamedThreadFactory("sentinel-console-log-executor", true), handler); } @Override @@ -83,7 +84,7 @@ public synchronized void setEncoding(String encoding) throws SecurityException, @Override public void publish(LogRecord record) { - executor.execute(new LogTask(record,stdoutHandler,stderrHandler)); + lastFuture.set(executor.submit(new LogTask(record, stdoutHandler, stderrHandler))); } @Override @@ -94,16 +95,18 @@ public void flush() { @Override public void close() throws SecurityException { - /**not need to record log if process is killed.*/ - executor.shutdown(); + Future future = lastFuture.get(); + if (future != null) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } stdoutHandler.close(); stderrHandler.close(); } - public ExecutorService getExecutor() { - return executor; - } - static class LogRejectedExecutionHandler implements RejectedExecutionHandler { /** diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/DateFileLogHandler.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/DateFileLogHandler.java index 0fb13a4f3f..f6c7715524 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/DateFileLogHandler.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/DateFileLogHandler.java @@ -20,14 +20,11 @@ import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; -import java.util.ArrayDeque; import java.util.Calendar; import java.util.Date; -import java.util.Queue; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.FileHandler; import java.util.logging.Formatter; @@ -43,7 +40,20 @@ public SimpleDateFormat initialValue() { } }; - private ExecutorService executor; + private static final ThreadPoolExecutor executor = new ThreadPoolExecutor( + 1, + 5, + 1, + TimeUnit.HOURS, + new ArrayBlockingQueue(1024), + new NamedThreadFactory("sentinel-datafile-log-executor", true), + new ThreadPoolExecutor.DiscardOldestPolicy() + ); + + static { + // allow all thread could be stopped + executor.allowCoreThreadTimeOut(true); + } private volatile FileHandler handler; @@ -66,22 +76,10 @@ public SimpleDateFormat initialValue() { this.append = append; rotateDate(); this.initialized = true; - - int corePoolSize = 1; - int maximumPoolSize = 1; - long keepAliveTime = 0; - /**insure the log can be recorded*/ - int queueSize = 1024; - RejectedExecutionHandler handler = new LogRejectedExecutionHandler(); - executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, - keepAliveTime, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(queueSize), - new NamedThreadFactory("sentinel-datafile-log-executor", true), handler); } @Override public void close() throws SecurityException { - /**not need to record log if process is killed.*/ - executor.shutdown(); handler.close(); } diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandlerTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandlerTest.java index 4783a058eb..4bd1abeae0 100644 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandlerTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/log/jul/ConsoleHandlerTest.java @@ -51,12 +51,7 @@ public void testInfoPublish() { // Test INFO level, should log to stdout logRecord = new LogRecord(Level.INFO, "test info message"); consoleHandler.publish(logRecord); - try { - consoleHandler.getExecutor().shutdown(); - consoleHandler.getExecutor().awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } + consoleHandler.close(); assertEquals(cspFormatter.format(logRecord), baosOut.toString()); assertEquals("", baosErr.toString()); @@ -80,12 +75,7 @@ public void testWarnPublish() { // Test INFO level, should log to stderr logRecord = new LogRecord(Level.WARNING, "test warning message"); consoleHandler.publish(logRecord); - try { - consoleHandler.getExecutor().shutdown(); - consoleHandler.getExecutor().awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } + consoleHandler.close(); assertEquals(cspFormatter.format(logRecord), baosErr.toString()); assertEquals("", baosOut.toString()); @@ -111,12 +101,7 @@ public void testFinePublish() { // java.util.logging.StreamHandler.level=FINE logRecord = new LogRecord(Level.FINE, "test fine message"); consoleHandler.publish(logRecord); - try { - consoleHandler.getExecutor().shutdown(); - consoleHandler.getExecutor().awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } + consoleHandler.close(); assertEquals("", baosOut.toString()); assertEquals("", baosErr.toString()); @@ -139,12 +124,7 @@ public void testSeverePublish() { // Test SEVERE level, should log to stderr logRecord = new LogRecord(Level.SEVERE, "test severe message"); consoleHandler.publish(logRecord); - try { - consoleHandler.getExecutor().shutdown(); - consoleHandler.getExecutor().awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } + consoleHandler.close(); assertEquals(cspFormatter.format(logRecord), baosErr.toString()); assertEquals("", baosOut.toString());