Class SystemLogHandler

java.lang.Object
java.util.logging.Handler
com.ultikits.ultitools.handler.SystemLogHandler

public class SystemLogHandler extends Handler
System log handler. Captures all system log records and forwards them to the UltiPanel backend.
Version:
1.0.0
Author:
UltiKits
  • Field Details

    • PUBLISHING

      private static final ThreadLocal<Boolean> PUBLISHING
      Reentrancy guard for publish(LogRecord) (Gate-2 finding, round 9). Loop-prevention in this class was, until now, done entirely by matching the RECORD's own loggerName against a small set of known class-name substrings (shouldProcessRecord(java.util.logging.LogRecord) below) -- but every diagnostic this framework logs through the SHARED plugin logger (UltiTools.getInstance().getLogger()) carries that shared logger's own name, not the calling class's, so the substring check can never catch any of them. Round 6/7 found and removed two individual instances of this (a transmitter diagnostic, then a WebSocket-send diagnostic); round 9 found a THIRD, in an exception handler that cannot simply be deleted (reporting a genuine send failure has real value). Rather than keep chasing individual call sites the review keeps finding new instances of, this ThreadLocal closes the whole class at its root: if publish is entered while ALREADY running on the SAME thread (which is exactly what happens when delivering/draining record N synchronously produces record N+1 on the same call stack -- every reachable recursion in this subsystem is same-thread, since none of the delivery/drain paths hand off to a different thread before logging), the re-entrant call is dropped instead of recursing. A single dropped self-referential diagnostic is an acceptable cost for eliminating an entire StackOverflowError defect class.
    • logTransmitter

      private final UltiPanelLogTransmitter logTransmitter
    • enabledLevels

      private Set<String> enabledLevels
    • excludedLoggers

      private Set<String> excludedLoggers
    • minimumLevel

      private Level minimumLevel
  • Constructor Details

    • SystemLogHandler

      public SystemLogHandler(UltiPanelLogTransmitter logTransmitter)
      Constructor.
      Parameters:
      logTransmitter - the log transmitter
  • Method Details

    • initializeDefaultConfiguration

      private void initializeDefaultConfiguration()
      Initializes the default configuration.
    • setEnabledLevels

      public void setEnabledLevels(Set<String> enabledLevels)
      Sets the panel-facing set of enabled log levels, and re-synchronises this handler's own java.util.logging level floor to match (syncHandlerLevelWithEnabledLevels()).
      Parameters:
      enabledLevels - the new enabled-level set
    • syncHandlerLevelWithEnabledLevels

      private void syncHandlerLevelWithEnabledLevels()
      Gate-2 finding: shouldProcessRecord(LogRecord) calls Handler.isLoggable(LogRecord) -- the base Handler's own check against Handler.getLevel() -- BEFORE this class's own enabledLevels filter ever runs. Handler.getLevel() defaults to Level.INFO (minimumLevel), which rejects JUL FINE/FINER/ FINEST records outright -- the levels mapLogLevel(Level) maps to "debug". So a panel request enabling "debug" in enabledLevels used to have no effect: no debug-shaped record could ever reach the mapping step that would have recognised it. Called after every mutation of enabledLevels (the setter above, addEnabledLevel(String), removeEnabledLevel(String), and loadConfiguration()'s own direct mutation) so the handler's own floor tracks whether "debug" is currently enabled.
    • loadConfiguration

      public void loadConfiguration()
      Loads configuration from the config file.
    • publish

      public void publish(LogRecord record)
      Specified by:
      publish in class Handler
    • shouldProcessRecord

      private boolean shouldProcessRecord(LogRecord record)
      Checks whether this log record should be processed.
    • mapLogLevel

      private String mapLogLevel(Level level)
      Maps a Java log level to the UltiPanel level vocabulary.
    • formatLogMessage

      private String formatLogMessage(LogRecord record)
      Formats a log message.
    • determineLogSource

      private String determineLogSource(LogRecord record)
      Determines the log-source identifier.
    • extractPluginName

      private String extractPluginName(String loggerName)
      Extracts a plugin name from a logger name.
    • capitalizeFirst

      private String capitalizeFirst(String str)
      Capitalizes the first letter.
    • extractModuleFromSource

      private String extractModuleFromSource(String source)
      Extract module name from the log source string (e.g., "plugin:UltiChat" -> "UltiChat").
    • inferTriggerFromStackTrace

      private TriggerContext inferTriggerFromStackTrace(Throwable throwable)
      Infer trigger context from exception stack trace.
    • addEnabledLevel

      public void addEnabledLevel(String level)
      Adds an enabled log level.
    • removeEnabledLevel

      public void removeEnabledLevel(String level)
      Removes an enabled log level.
    • addExcludedLogger

      public void addExcludedLogger(String loggerName)
      Adds an excluded logger.
    • removeExcludedLogger

      public void removeExcludedLogger(String loggerName)
      Removes an excluded logger.
    • flush

      public void flush()
      Specified by:
      flush in class Handler
    • close

      public void close() throws SecurityException
      Specified by:
      close in class Handler
      Throws:
      SecurityException
    • getConfigurationInfo

      public String getConfigurationInfo()
      Gets a configuration-info string.