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.
public class BukkitLogManager extends AbstractLogManager implements INotifyReload {
// 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: Later: Custom loggers (file, other), per-player-streams (debug per player), custom ingame loggers (one or more players).
protected final Plugin plugin;
/**
* This will create all default loggers as well.
* @param plugin
@ -52,7 +52,7 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
createDefaultLoggers(config);
getLogNodeDispatcher().setMaxQueueSize(config.getInt(ConfPaths.LOGGING_MAXQUEUESIZE));
}
@Override
protected void registerInitLogger() {
synchronized (registryCOWLock) {
@ -66,19 +66,19 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
// Attach a new restrictive init logger.
boolean bukkitLoggerAsynchronous = ConfigManager.getConfigFile().getBoolean(ConfPaths.LOGGING_BACKEND_CONSOLE_ASYNCHRONOUS);
LoggerID initLoggerID = registerStringLogger(new ContentLogger<String>() {
@Override
public void log(Level level, String content) {
try {
Bukkit.getLogger().log(level, content);
} catch (Throwable t) {}
}
}, new LogOptions(Streams.INIT.name, bukkitLoggerAsynchronous ? CallContext.ANY_THREAD_DIRECT : CallContext.PRIMARY_THREAD_ONLY));
attachStringLogger(initLoggerID, Streams.INIT);
}
}
/**
* Create default loggers and streams.
*/
@ -89,69 +89,102 @@ public class BukkitLogManager extends AbstractLogManager implements INotifyReloa
Streams.SERVER_LOGGER, Streams.PLUGIN_LOGGER,
Streams.NOTIFY_INGAME,
Streams.DEFAULT_FILE, Streams.TRACE_FILE,
}) {
createStringStream(streamID);
}
// Variables for temporary use.
LoggerID tempID;
File file;
// Configuration/defaults.
// TODO: More configurability.
// 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);
// TODO: Do keep considering: AYNCHRONOUS_DIRECT -> ASYNCHRONOUS_TASK (not to delay async. event handling).
CallContext defaultAsynchronousContext = CallContext.ASYNCHRONOUS_DIRECT; // Plugin runtime + asynchronous.
// Server logger.
tempID = registerStringLogger(Bukkit.getLogger(), new LogOptions(Streams.SERVER_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK));
attachStringLogger(tempID, Streams.SERVER_LOGGER);
// Plugin logger.
tempID = registerStringLogger(plugin.getLogger(), new LogOptions(Streams.PLUGIN_LOGGER.name, bukkitLoggerAsynchronous ? defaultAsynchronousContext : CallContext.PRIMARY_THREAD_TASK));
attachStringLogger(tempID, Streams.PLUGIN_LOGGER);
// Ingame logger (assume not thread-safe at first).
// TODO: Thread-safe ProtocolLib-based implementation?
tempID = registerStringLogger(new ContentLogger<String>() {
@Override
public void log(Level level, String content) {
// Ignore level for now.
NCPAPIProvider.getNoCheatPlusAPI().sendAdminNotifyMessage(content);
}
}, new LogOptions(Streams.NOTIFY_INGAME.name, CallContext.PRIMARY_THREAD_DIRECT)); // TODO: Consider task.
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).
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
public void onReload() {
// 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.
createDefaultLoggers(ConfigManager.getConfigFile());
}
/**
* 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).
((BukkitLogNodeDispatcher) getLogNodeDispatcher()).startTasks();
}
}