diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java index 7ab0188d66b..8826c3708d4 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java @@ -20,7 +20,6 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository; -import org.apache.dubbo.common.utils.ConcurrentHashSet; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; @@ -35,10 +34,10 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Iterator; import java.util.Map; -import java.util.Set; +import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -75,10 +74,12 @@ public class AccessLogFilter implements Filter { // It's safe to declare it as singleton since it runs on single thread only private final DateFormat fileNameFormatter = new SimpleDateFormat(FILE_DATE_FORMAT); - private final Map> logEntries = new ConcurrentHashMap<>(); + private final Map> logEntries = new ConcurrentHashMap<>(); private AtomicBoolean scheduled = new AtomicBoolean(); + private static final String LINE_SEPARATOR = "line.separator"; + /** * Default constructor initialize demon thread for writing into access log file with names with access log key * defined in url accesslog @@ -104,7 +105,7 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { try { String accessLogKey = invoker.getUrl().getParameter(ACCESS_LOG_KEY); if (ConfigUtils.isNotEmpty(accessLogKey)) { - AccessLogData logData = AccessLogData.newLogData(); + AccessLogData logData = AccessLogData.newLogData(); logData.buildAccessLogData(invoker, inv); log(accessLogKey, logData); } @@ -115,20 +116,20 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { } private void log(String accessLog, AccessLogData accessLogData) { - Set logSet = logEntries.computeIfAbsent(accessLog, k -> new ConcurrentHashSet<>()); + Queue logQueue = logEntries.computeIfAbsent(accessLog, k -> new ConcurrentLinkedQueue<>()); - if (logSet.size() < LOG_MAX_BUFFER) { - logSet.add(accessLogData); + if (logQueue.size() < LOG_MAX_BUFFER) { + logQueue.add(accessLogData); } else { logger.warn("AccessLog buffer is full. Do a force writing to file to clear buffer."); //just write current logSet to file. - writeLogSetToFile(accessLog, logSet); + writeLogSetToFile(accessLog, logQueue); //after force writing, add accessLogData to current logSet - logSet.add(accessLogData); + logQueue.add(accessLogData); } } - private void writeLogSetToFile(String accessLog, Set logSet) { + private void writeLogSetToFile(String accessLog, Queue logSet) { try { if (ConfigUtils.isDefault(accessLog)) { processWithServiceLogger(logSet); @@ -148,23 +149,24 @@ private void writeLogSetToFile(String accessLog, Set logSet) { private void writeLogToFile() { if (!logEntries.isEmpty()) { - for (Map.Entry> entry : logEntries.entrySet()) { + for (Map.Entry> entry : logEntries.entrySet()) { String accessLog = entry.getKey(); - Set logSet = entry.getValue(); + Queue logSet = entry.getValue(); writeLogSetToFile(accessLog, logSet); } } } - private void processWithAccessKeyLogger(Set logSet, File file) throws IOException { - try (FileWriter writer = new FileWriter(file, true)) { - for (Iterator iterator = logSet.iterator(); - iterator.hasNext(); - iterator.remove()) { - writer.write(iterator.next().getLogMessage()); - writer.write(System.getProperty("line.separator")); + private void processWithAccessKeyLogger(Queue logQueue, File file) throws IOException { + FileWriter writer = new FileWriter(file, true); + try { + while (!logQueue.isEmpty()) { + writer.write(logQueue.poll().getLogMessage()); + writer.write(System.getProperty(LINE_SEPARATOR)); } + } finally { writer.flush(); + writer.close(); } } @@ -180,11 +182,9 @@ private AccessLogData buildAccessLogData(Invoker invoker, Invocation inv) { return logData; } - private void processWithServiceLogger(Set logSet) { - for (Iterator iterator = logSet.iterator(); - iterator.hasNext(); - iterator.remove()) { - AccessLogData logData = iterator.next(); + private void processWithServiceLogger(Queue logQueue) { + while (!logQueue.isEmpty()) { + AccessLogData logData = logQueue.poll(); LoggerFactory.getLogger(LOG_KEY + "." + logData.getServiceName()).info(logData.getLogMessage()); } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java index 7cb7ccde250..fb58a69fdcf 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java @@ -30,7 +30,7 @@ import java.lang.reflect.Field; import java.util.Map; -import java.util.Set; +import java.util.Queue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -69,7 +69,7 @@ public void testDefault() throws NoSuchFieldException, IllegalAccessException { accessLogFilter.invoke(invoker, invocation); - Map> logs = (Map>) field.get(accessLogFilter); + Map> logs = (Map>) field.get(accessLogFilter); assertFalse(logs.isEmpty()); assertFalse(logs.get("true").isEmpty()); AccessLogData log = logs.get("true").iterator().next();