Class RemoteActionLog
plugins/UltiTools/security/action.log.<generation>. Generation 0 is always the
currently-active file — see init(File) for why the literal, suffix-free
action.log never exists on disk.
Replaces the audit/enforce mode ROADMAP originally asked for (D-22): there is only one policy
tier, so there is nothing to simulate, only something to record. This class is constructed
unconditionally in UltiTools.initWebSocketManagers() and is not gated by any
Capability — D-32.
Disabling this logger's parent handlers (see the static initializer below) is load-bearing.
SystemLogHandler attaches only to the root logger (Logger.getLogger("")) — the
sole attachment site is LogStreamManager.java line 95, rootLogger.addHandler(systemLogHandler).
A non-root logger with parent handlers disabled therefore cannot reach SystemLogHandler
and cannot create the feedback loop ErrorReportCollector's class javadoc warns about
("This class NEVER uses java.util.logging.Logger to prevent circular logging"). This class may
therefore safely use Logger/FileHandler where ErrorReportCollector may
not — that is a deliberate, narrower reading of the same hazard, not a violation of it.
Internal failures of the log itself (handler creation, directory creation, config load) print to
System.err, never through any Logger — the same discipline
ErrorReportCollector uses for its own internal failures, for the same reason: a failure
in the thing that logs must not try to log itself.
- Since:
- 6.3.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classOne immutable action-log entry.(package private) static final classSerializes oneRemoteActionLog.EntryperLogRecordinto a single compact JSON line — no pretty-printing — using the sameGsonBuilder().disableHtmlEscaping()construction the WebSocket managers already use.static enumAllowed or denied — the two verdicts a capability gate can reach. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final Loggerprivate FileHandlerTheFileHandlerthis specific instance attached to the shared staticACTION_LOG—nulluntil a successfulinit(File).private static final intprivate static final intprivate final com.google.gson.Gsonprivate static final Stringprivate intprivate int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidAttaches the rotatingFileHandlerat<dataFolder>/security/action.log.%g, creating thesecuritydirectory if absent.private voidLoadsultipanel.logging.action-log.max-size-bytesand.max-files, copyingErrorReportCollector.loadConfiguration()'s exact shape:UltiTools.getInstance()null-guard,instance.getConfig().getInt(path, default)per key, one try/catch whose failure branch prints toSystem.errand never to aLogger— this failure is about loading config for this very log, so it cannot log through itself.voidrecord(RemoteActionLog.Entry entry) Records one entry.voidshutdown()Removes and closes theFileHandlerthis instance attached ininit(File)(WR-01, 06-REVIEW.md).
-
Field Details
-
LOGGER_NAME
- See Also:
-
DEFAULT_MAX_SIZE_BYTES
private static final int DEFAULT_MAX_SIZE_BYTES- See Also:
-
DEFAULT_MAX_FILES
private static final int DEFAULT_MAX_FILES- See Also:
-
ACTION_LOG
-
gson
private final com.google.gson.Gson gson -
maxSizeBytes
private volatile int maxSizeBytes -
maxFiles
private volatile int maxFiles -
attachedHandler
TheFileHandlerthis specific instance attached to the shared staticACTION_LOG—nulluntil a successfulinit(File). Tracked per instance, not read back offACTION_LOGitself, soshutdown()removes only the handler this instance is responsible for (WR-01) — never a sibling instance's handler, which matters if two instances are ever briefly alive at once.
-
-
Constructor Details
-
RemoteActionLog
public RemoteActionLog()
-
-
Method Details
-
init
Attaches the rotatingFileHandlerat<dataFolder>/security/action.log.%g, creating thesecuritydirectory if absent. Loads the rotation knobs from config.yml first — seeloadConfiguration().The file on disk is never literally
action.log.FileHandleralways substitutes%gwith the current generation number when the pattern contains it, and — confirmed empirically against this JDK'sFileHandler, not merely inferred from its javadoc — it auto-appends the same suffix even if%gwere removed from the pattern, becausemax-filesdefaults to 5 (count > 1): a generation suffix is unavoidable at any rotation-enabled setting, and only an operator settingmax-filesto1(disabling rotation entirely) would remove it. Generation0is always the currently-active file that new records append to;action.log.1,action.log.2, … are older rotated generations, oldest evicted first oncemax-filesis reached. Every operator-facing reference to this file's path must sayaction.log.0(the active file), not the bare, never-existingaction.log— see UAT finding 5b.- Parameters:
dataFolder- the plugin's data folder (getDataFolder())
-
shutdown
public void shutdown()Removes and closes theFileHandlerthis instance attached ininit(File)(WR-01, 06-REVIEW.md).A no-op if
init(File)was never called or failed to attach a handler (attachedHandlerstaysnull). Flushes before closing so no buffered line is lost. Load-bearing for a Bukkit/reload:ACTION_LOGis astaticLoggershared for the life of the JVM, so without this call a secondonEnable'sinit(File)would attach a secondFileHandleron top of this one, and every subsequentrecord(Entry)would be delivered to both — duplicating every action-log line from that point on, exactly the defect this method exists to prevent. -
loadConfiguration
private void loadConfiguration()Loadsultipanel.logging.action-log.max-size-bytesand.max-files, copyingErrorReportCollector.loadConfiguration()'s exact shape:UltiTools.getInstance()null-guard,instance.getConfig().getInt(path, default)per key, one try/catch whose failure branch prints toSystem.errand never to aLogger— this failure is about loading config for this very log, so it cannot log through itself. There is deliberately noenabledkey here and noCapabilityconsulted — D-32 makes this log's existence non-negotiable for the operator, a narrow exception to the D-04 no-floor rule (which governs which commands may run, not whether the record of what ran survives). -
record
Records one entry. A no-op ifentryisnull.- Parameters:
entry- the entry to record
-