More robust file logger creation, allow "" or "none" to not have any.

This commit is contained in:
asofold 2015-01-05 22:45:24 +01:00
parent bd5794d0bd
commit 34a5b2a089

View File

@ -33,14 +33,14 @@ import fr.neatmonster.nocheatplus.logging.details.LogOptions.CallContext;
*/ */
@SetupOrder(priority = Integer.MIN_VALUE) // Just in case. @SetupOrder(priority = Integer.MIN_VALUE) // Just in case.
public class BukkitLogManager extends AbstractLogManager implements INotifyReload { public class BukkitLogManager extends AbstractLogManager implements INotifyReload {
// TODO: Make LogManager an interface <- AbstractLogManager <- BukkitLogManager (hide some / instanceof). // TODO: Make LogManager an interface <- AbstractLogManager <- BukkitLogManager (hide some / instanceof).
// TODO: ingame logging [ingame needs api to keep track of players who receive notifications.]. // TODO: ingame logging [ingame needs api to keep track of players who receive notifications.].
// TODO: Later: Custom loggers (file, other), per-player-streams (debug per player), custom ingame loggers (one or more players). // TODO: Later: Custom loggers (file, other), per-player-streams (debug per player), custom ingame loggers (one or more players).
protected final Plugin plugin; protected final Plugin plugin;
/** /**
* This will create all default loggers as well. * This will create all default loggers as well.
* @param plugin * @param plugin
@ -52,7 +52,7 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
createDefaultLoggers(config); createDefaultLoggers(config);
getLogNodeDispatcher().setMaxQueueSize(config.getInt(ConfPaths.LOGGING_MAXQUEUESIZE)); getLogNodeDispatcher().setMaxQueueSize(config.getInt(ConfPaths.LOGGING_MAXQUEUESIZE));
} }
@Override @Override
protected void registerInitLogger() { protected void registerInitLogger() {
synchronized (registryCOWLock) { synchronized (registryCOWLock) {
@ -66,19 +66,19 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
// Attach a new restrictive init logger. // Attach a new restrictive init logger.
boolean bukkitLoggerAsynchronous = ConfigManager.getConfigFile().getBoolean(ConfPaths.LOGGING_BACKEND_CONSOLE_ASYNCHRONOUS); boolean bukkitLoggerAsynchronous = ConfigManager.getConfigFile().getBoolean(ConfPaths.LOGGING_BACKEND_CONSOLE_ASYNCHRONOUS);
LoggerID initLoggerID = registerStringLogger(new ContentLogger<String>() { LoggerID initLoggerID = registerStringLogger(new ContentLogger<String>() {
@Override @Override
public void log(Level level, String content) { public void log(Level level, String content) {
try { try {
Bukkit.getLogger().log(level, content); Bukkit.getLogger().log(level, content);
} catch (Throwable t) {} } catch (Throwable t) {}
} }
}, new LogOptions(Streams.INIT.name, bukkitLoggerAsynchronous ? CallContext.ANY_THREAD_DIRECT : CallContext.PRIMARY_THREAD_ONLY)); }, new LogOptions(Streams.INIT.name, bukkitLoggerAsynchronous ? CallContext.ANY_THREAD_DIRECT : CallContext.PRIMARY_THREAD_ONLY));
attachStringLogger(initLoggerID, Streams.INIT); attachStringLogger(initLoggerID, Streams.INIT);
} }
} }
/** /**
* Create default loggers and streams. * Create default loggers and streams.
*/ */
@ -89,69 +89,102 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
Streams.SERVER_LOGGER, Streams.PLUGIN_LOGGER, Streams.SERVER_LOGGER, Streams.PLUGIN_LOGGER,
Streams.NOTIFY_INGAME, Streams.NOTIFY_INGAME,
Streams.DEFAULT_FILE, Streams.TRACE_FILE, Streams.DEFAULT_FILE, Streams.TRACE_FILE,
}) { }) {
createStringStream(streamID); createStringStream(streamID);
} }
// Variables for temporary use. // Variables for temporary use.
LoggerID tempID; LoggerID tempID;
File file;
// Configuration/defaults. // Configuration/defaults.
// TODO: More configurability. // TODO: More configurability.
// TODO: Might attempt to detect if a thread-safe logging framework is in use ("default" instead of false/true). // TODO: Might attempt to detect if a thread-safe logging framework is in use ("default" instead of false/true).
boolean bukkitLoggerAsynchronous = config.getBoolean(ConfPaths.LOGGING_BACKEND_CONSOLE_ASYNCHRONOUS); boolean bukkitLoggerAsynchronous = config.getBoolean(ConfPaths.LOGGING_BACKEND_CONSOLE_ASYNCHRONOUS);
// TODO: Do keep considering: AYNCHRONOUS_DIRECT -> ASYNCHRONOUS_TASK (not to delay async. event handling). // TODO: Do keep considering: AYNCHRONOUS_DIRECT -> ASYNCHRONOUS_TASK (not to delay async. event handling).
CallContext defaultAsynchronousContext = CallContext.ASYNCHRONOUS_DIRECT; // Plugin runtime + asynchronous. CallContext defaultAsynchronousContext = CallContext.ASYNCHRONOUS_DIRECT; // Plugin runtime + asynchronous.
// Server logger. // Server logger.
tempID = registerStringLogger(Bukkit.getLogger(), new LogOptions(Streams.SERVER_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK)); tempID = registerStringLogger(Bukkit.getLogger(), new LogOptions(Streams.SERVER_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK));
attachStringLogger(tempID, Streams.SERVER_LOGGER); attachStringLogger(tempID, Streams.SERVER_LOGGER);
// Plugin logger. // Plugin logger.
tempID = registerStringLogger(plugin.getLogger(), new LogOptions(Streams.PLUGIN_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK)); tempID = registerStringLogger(plugin.getLogger(), new LogOptions(Streams.PLUGIN_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK));
attachStringLogger(tempID, Streams.PLUGIN_LOGGER); attachStringLogger(tempID, Streams.PLUGIN_LOGGER);
// Ingame logger (assume not thread-safe at first). // Ingame logger (assume not thread-safe at first).
// TODO: Thread-safe ProtocolLib-based implementation? // TODO: Thread-safe ProtocolLib-based implementation?
tempID = registerStringLogger(new ContentLogger<String>() { tempID = registerStringLogger(new ContentLogger<String>() {
@Override @Override
public void log(Level level, String content) { public void log(Level level, String content) {
// Ignore level for now. // Ignore level for now.
NCPAPIProvider.getNoCheatPlusAPI().sendAdminNotifyMessage(content); NCPAPIProvider.getNoCheatPlusAPI().sendAdminNotifyMessage(content);
} }
}, new LogOptions(Streams.NOTIFY_INGAME.name, CallContext.PRIMARY_THREAD_DIRECT)); // TODO: Consider task. }, new LogOptions(Streams.NOTIFY_INGAME.name, CallContext.PRIMARY_THREAD_DIRECT)); // TODO: Consider task.
attachStringLogger(tempID, Streams.NOTIFY_INGAME); attachStringLogger(tempID, Streams.NOTIFY_INGAME);
// Default file logger.
file = new File(config.getString(ConfPaths.LOGGING_BACKEND_FILE_FILENAME));
if (!file.isAbsolute()) {
file = new File(plugin.getDataFolder(), file.getPath());
}
// TODO: Sanity check file+extensions and fall-back if not valid [make an auxiliary method doing all this at once]!
ContentLogger<String> defaultFileLogger = new FileLoggerAdapter(file); // TODO: Method to get-or-create these.
tempID = registerStringLogger(defaultFileLogger, new LogOptions(Streams.DEFAULT_FILE.name, defaultAsynchronousContext));
attachStringLogger(tempID, Streams.DEFAULT_FILE);
// Trace file logger.
// TODO: Create a dedicated file, if "needed".
attachStringLogger(getLoggerID(Streams.DEFAULT_FILE.name), Streams.TRACE_FILE); // Direct to default file for now.
// Abstract INIT stream (attach file logger).
// TODO: Consider configurability of skipping, depending on bukkitLoggerAsynchronous.
tempID = registerStringLogger(defaultFileLogger, new LogOptions(Streams.DEFAULT_FILE.name +".init", CallContext.ANY_THREAD_DIRECT));
attachStringLogger(tempID, Streams.INIT);
// Abstract STATUS stream (efficient version of INIT during plugin runtime). // Abstract STATUS stream (efficient version of INIT during plugin runtime).
attachStringLogger(getLoggerID(Streams.SERVER_LOGGER.name), Streams.STATUS); attachStringLogger(getLoggerID(Streams.SERVER_LOGGER.name), Streams.STATUS);
attachStringLogger(getLoggerID(Streams.DEFAULT_FILE.name), Streams.STATUS);
// Default file logger.
// String fileName = config.getString(ConfPaths.LOGGING_BACKEND_FILE_FILENAME).trim();
ContentLogger<String> defaultFileLogger = null;
if (!fileName.isEmpty() && !fileName.equalsIgnoreCase("none")) {
defaultFileLogger = newFileLogger(fileName, plugin.getDataFolder());
}
ContentLogger<String> traceFileLogger = null;
// TODO: Create a dedicated trace file, if "needed".
if (defaultFileLogger != null) {
// Do attach the default file logger.
tempID = registerStringLogger(defaultFileLogger, new LogOptions(Streams.DEFAULT_FILE.name, defaultAsynchronousContext));
attachStringLogger(tempID, Streams.DEFAULT_FILE);
// Trace file logger (if no extra file).
if (traceFileLogger == null) {
attachStringLogger(getLoggerID(Streams.DEFAULT_FILE.name), Streams.TRACE_FILE); // Direct to default file for now.
}
// Abstract INIT stream (attach file logger).
// TODO: Consider configurability of skipping, depending on bukkitLoggerAsynchronous.
tempID = registerStringLogger(defaultFileLogger, new LogOptions(Streams.DEFAULT_FILE.name +".init", CallContext.ANY_THREAD_DIRECT));
attachStringLogger(tempID, Streams.INIT);
//Abstract STATUS stream (attach file logger).
attachStringLogger(getLoggerID(Streams.DEFAULT_FILE.name), Streams.STATUS);
}
} }
/**
* Create a new file logger. Relative paths are interpreted relative to the
* given default directory (!). The used FileLoggerAdapter will interpret
* names without extensions as folders to be created, if not existent.
*
* @param fileName
* Path to the log file, or path to a folder for log files by
* date (a folder is created, if no extension is given).
* @param defaultDir
* This is used as a base, if fileName represents a relative
* path.
* @return
*/
protected ContentLogger<String> newFileLogger(String fileName, File defaultDir) {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(defaultDir, file.getPath());
}
// TODO: Sanity check file+extensions and fall-back if not valid [make an auxiliary method doing all this at once]!
try {
return new FileLoggerAdapter(file); // TODO: Method to get-or-create these (store logger by canonical abs paths).
} catch (Throwable t) {
// TODO: Complain.
}
return null;
}
@Override @Override
public void onReload() { public void onReload() {
// Hard clear and re-do loggers. Might result in loss of content. // Hard clear and re-do loggers. Might result in loss of content.
@ -159,7 +192,7 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
clear(0L, true); // Can not afford to wait. clear(0L, true); // Can not afford to wait.
createDefaultLoggers(ConfigManager.getConfigFile()); createDefaultLoggers(ConfigManager.getConfigFile());
} }
/** /**
* Necessary logging to a primary thread task (TickTask). * Necessary logging to a primary thread task (TickTask).
*/ */
@ -167,5 +200,5 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
// TODO: Schedule / hide (redundant calls mean no harm, at present). // TODO: Schedule / hide (redundant calls mean no harm, at present).
((BukkitLogNodeDispatcher) getLogNodeDispatcher()).startTasks(); ((BukkitLogNodeDispatcher) getLogNodeDispatcher()).startTasks();
} }
} }