From 2406634ed8b957e0cbee4d0a4100068d573b85c5 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Sat, 21 Aug 2021 17:01:42 +0200 Subject: [PATCH] Add timeout & interval to sysout catcher (#6383) --- ... => 0730-Add-System.out-err-catcher.patch} | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) rename patches/server/{0730-Add-System.out.println-catcher.patch => 0730-Add-System.out-err-catcher.patch} (60%) diff --git a/patches/server/0730-Add-System.out.println-catcher.patch b/patches/server/0730-Add-System.out-err-catcher.patch similarity index 60% rename from patches/server/0730-Add-System.out.println-catcher.patch rename to patches/server/0730-Add-System.out-err-catcher.patch index c2171fb57..692d2e41b 100644 --- a/patches/server/0730-Add-System.out.println-catcher.patch +++ b/patches/server/0730-Add-System.out-err-catcher.patch @@ -1,15 +1,15 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: underscore11code Date: Fri, 23 Jul 2021 23:01:42 -0700 -Subject: [PATCH] Add System.out.println catcher +Subject: [PATCH] Add System.out/err catcher diff --git a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java new file mode 100644 -index 0000000000000000000000000000000000000000..fd2af675d32e497fabd35f57b9e7c53ece97e6bd +index 0000000000000000000000000000000000000000..88608afed45f25f822121214f87e9f9b53143104 --- /dev/null +++ b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java -@@ -0,0 +1,56 @@ +@@ -0,0 +1,94 @@ +package io.papermc.paper.logging; + +import org.bukkit.Bukkit; @@ -19,17 +19,36 @@ index 0000000000000000000000000000000000000000..fd2af675d32e497fabd35f57b9e7c53e + +import java.io.OutputStream; +import java.io.PrintStream; ++import java.util.Objects; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentMap; ++import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +public final class SysoutCatcher { + private static final boolean SUPPRESS_NAGS = Boolean.getBoolean("io.papermc.paper.suppress.sout.nags"); ++ // Nanoseconds between nag at most; if interval is caught first, this is reset. ++ // <= 0 for disabling. ++ private static final long NAG_TIMEOUT = TimeUnit.MILLISECONDS.toNanos( ++ Long.getLong("io.papermc.paper.sout.nags.timeout", TimeUnit.MINUTES.toMillis(5L))); ++ // Count since last nag; if timeout is first, this is reset. ++ // <= 0 for disabling. ++ private static final long NAG_INTERVAL = Long.getLong("io.papermc.paper.sout.nags.interval", 200L); ++ ++ // We don't particularly care about how correct this is at any given moment; let's do it on a best attempt basis. ++ // The records are also pretty small, so let's just go for a size of 64 to start... ++ // ++ // Content: Plugin name => nag object ++ // Why plugin name?: This doesn't store a reference to the plugin; keeps the reload ability. ++ // Why not clean on reload?: Effort. ++ private final ConcurrentMap nagRecords = new ConcurrentHashMap<>(64); + + public SysoutCatcher() { + System.setOut(new WrappedOutStream(System.out, Level.INFO, "[STDOUT] ")); + System.setErr(new WrappedOutStream(System.err, Level.SEVERE, "[STDERR] ")); + } + -+ private static final class WrappedOutStream extends PrintStream { ++ private final class WrappedOutStream extends PrintStream { + private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + private final Level level; + private final String prefix; @@ -52,6 +71,20 @@ index 0000000000000000000000000000000000000000..fd2af675d32e497fabd35f57b9e7c53e + if (SysoutCatcher.SUPPRESS_NAGS) { + return; + } ++ if (SysoutCatcher.NAG_INTERVAL > 0 || SysoutCatcher.NAG_TIMEOUT > 0) { ++ final PluginNag nagRecord = SysoutCatcher.this.nagRecords.computeIfAbsent(plugin.getName(), k -> new PluginNag()); ++ final boolean hasTimePassed = SysoutCatcher.NAG_TIMEOUT > 0 ++ && (nagRecord.lastNagTimestamp == Long.MIN_VALUE ++ || nagRecord.lastNagTimestamp + SysoutCatcher.NAG_TIMEOUT <= System.nanoTime()); ++ final boolean hasMessagesPassed = SysoutCatcher.NAG_INTERVAL > 0 ++ && (nagRecord.messagesSinceNag == Long.MIN_VALUE ++ || ++nagRecord.messagesSinceNag >= SysoutCatcher.NAG_INTERVAL); ++ if (!hasMessagesPassed && !hasTimePassed) { ++ return; ++ } ++ nagRecord.lastNagTimestamp = System.nanoTime(); ++ nagRecord.messagesSinceNag = 0; ++ } + Bukkit.getLogger().warning( + String.format("Nag author(s): '%s' of '%s' about their usage of System.out/err.print. " + + "Please use your plugin's logger instead (JavaPlugin#getLogger).", @@ -65,6 +98,11 @@ index 0000000000000000000000000000000000000000..fd2af675d32e497fabd35f57b9e7c53e + } + } + } ++ ++ private static class PluginNag { ++ private long lastNagTimestamp = Long.MIN_VALUE; ++ private long messagesSinceNag = Long.MIN_VALUE; ++ } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 9954e45c32a4b6d80fe912ed9d55cd4fc8c4e98b..6d7f16fede01c19f638e1dcdae8b07b79cd86dc0 100644