Split off logOnce to StaticLog.

This commit is contained in:
asofold 2017-04-28 21:35:00 +02:00
parent 180cf8a3c3
commit 53f534b3c6
2 changed files with 73 additions and 39 deletions

View File

@ -14,7 +14,10 @@
*/
package fr.neatmonster.nocheatplus.logging;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
@ -28,13 +31,18 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil;
*
*/
public class StaticLog {
// TODO: Remove this class, instead use an implementation of LogManager for testing.
private static boolean useLogManager = false;
private static StreamID streamID = Streams.INIT;
/** The Constant logOnce. */
// TODO: Quick and dirty - should probably use an access ordered LinkedHashSet, to expire the eldest half :p.
private static final Set<Integer> logOnce = Collections.synchronizedSet(new HashSet<Integer>());
/**
* Now needs to be set, in order to log to the INIT stream instead of the console.
* @param useLogManager
@ -42,7 +50,7 @@ public class StaticLog {
public static void setUseLogManager(boolean useLogManager) {
StaticLog.useLogManager = useLogManager;
}
public static void setStreamID(StreamID streamID) {
if (streamID == null) {
throw new NullPointerException("StreamID must not be null, use setUseLogManager(false) instead.");
@ -75,6 +83,17 @@ public class StaticLog {
}
public static void log(final Level level, final String msg) {
log(StaticLog.streamID, level, msg);
}
/**
*
* @param streamID
* May get ignored if only the console is available.
* @param level
* @param msg
*/
public static void log(final StreamID streamID, final Level level, final String msg) {
if (useLogManager) {
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().log(streamID, level, msg);
} else {
@ -83,4 +102,39 @@ public class StaticLog {
}
}
/**
* Not really once: Always log the header with an id: create a hash of to be
* logged parts and keep the hash in memory, log it with the header - only
* log the longMessage once per hash. Once the id tracking storage has
* reached a certain size, many/all are removed. The hash involves both the
* header and longMessage strings as well as their lengths. No distinction
* is made for log level. This is intended for long messages like stack
* traces.
*
* @param level
* @param message
*/
public static void logOnce(final StreamID stream, final Level level,
final String header, final String longMessage) {
// TODO: LogOnce should be in static log ?
final int ref = header.hashCode() ^ longMessage.hashCode() ^ new Integer(header.length()).hashCode()
^ new Integer(longMessage.length()).hashCode();
final String extra;
final boolean details = logOnce.add(ref);
if (details) {
// Not already contained.
extra = " -> log once id=";
} else {
extra = " See earlier in this log, search for -> log once id=";
}
log(stream, level, header + extra + ref);
if (details) {
log(stream, level, longMessage);
if (logOnce.size() > 10000) {
logOnce.clear();
log(stream, level, "Cleared log once ids, due to exceeding the maximum number of stored ids.");
}
}
}
}

View File

@ -15,10 +15,8 @@
package fr.neatmonster.nocheatplus.utilities;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -38,15 +36,25 @@ import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
// TODO: Auto-generated Javadoc
/**
* Random auxiliary gear, some might have general quality. Contents are likely to get moved to other classes.
* Random auxiliary gear, some might have general quality. Contents are likely
* to get moved to other classes. All that is in here should be set up with
* checks and not be related to early setup stages of the plugin.
*/
public class CheckUtils {
/** The Constant logOnce. */
// TODO: Quick and dirty -> other methods elsewhere.
private static final Set<Integer> logOnce = Collections.synchronizedSet(new HashSet<Integer>());
/**
* Improper API access.
*
* @param checkType
* the check type
*/
private static void improperAPIAccess(final CheckType checkType) {
// TODO: Log once + examine stack (which plugins/things are involved).
final String trace = Arrays.toString(Thread.currentThread().getStackTrace());
StaticLog.logOnce(Streams.STATUS, Level.SEVERE, "Off primary thread call to hasByPass for " + checkType, trace);
}
/**
* Kick and log.
@ -191,34 +199,6 @@ public class CheckUtils {
return NCPExemptionManager.isExempted(player, checkType, isPrimaryThread);
}
/**
* Improper api access.
*
* @param checkType
* the check type
*/
private static void improperAPIAccess(final CheckType checkType) {
// TODO: Log once + examine stack (which plugins/things are involved).
final String trace = Arrays.toString(Thread.currentThread().getStackTrace());
final int ref = trace.hashCode() ^ new Integer(trace.length()).hashCode();
final String extra;
final boolean details = logOnce.add(ref);
if (details) {
// Not already contained.
extra = " (id=" + ref + ")";
} else {
extra = " (see earlier log with id=" + ref + ")";
}
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().severe(Streams.STATUS, "Off primary thread call to hasByPass for " + checkType + extra + ".");
if (details) {
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().severe(Streams.STATUS, trace);
if (logOnce.size() > 10000) {
logOnce.clear();
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().severe(Streams.STATUS, "Cleared log-once ids, due to exceeding the maximum number of stored ids.");
}
}
}
/**
* Static relay for the check-specific convenience methods, logging with
* standard format ([check_type] [player_name] ...).