Logger refactor
This commit is contained in:
parent
ef714031dc
commit
60fae86237
|
@ -0,0 +1,11 @@
|
|||
## 20.2.0.0-alpha.1
|
||||
* `[PlutoLib#cz.tefek.pluto.io.logger]` Refactored the Logger subsystem
|
||||
* Renamed `Logger#logException` to `Logger#log` to match the rest
|
||||
of log methods and updated references to this method accordingly
|
||||
* Streamlined `StdOutSplitStream` and `StdErrSplitStream` into a more generalized
|
||||
`OutputSplitStream`
|
||||
* `Logger`'s output filenames now look cleaner with `log--YYYY-MM-DD--HH-MM-SS.txt`
|
||||
* `[Logger#setup]` can now throw `IOException`
|
||||
* `[PlutoCore]` As a result, `[PlutoApplication#run]` can now throw `Exception`
|
||||
* `[PlutoCore]` `[PlutoApplication]` now properly closes the `Logger` on exit
|
||||
* `[PlutoLib]` Various typo fixes
|
|
@ -1,5 +1,6 @@
|
|||
package cz.tefek.pluto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
@ -44,7 +45,7 @@ public abstract class PlutoApplication
|
|||
}
|
||||
}
|
||||
|
||||
public final void run(String[] args, StartupConfig config)
|
||||
public final void run(String[] args, StartupConfig config) throws Exception
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
|
@ -117,6 +118,8 @@ public abstract class PlutoApplication
|
|||
this.display.destroy();
|
||||
|
||||
DisplayBuilder.destroyGLFW();
|
||||
|
||||
Logger.close();
|
||||
}
|
||||
|
||||
public Display getDisplayInstance()
|
||||
|
|
|
@ -223,7 +223,7 @@ public class MiniTime
|
|||
* than {@link Integer#MAX_VALUE} will be permanently converted to
|
||||
* "forever".</i>
|
||||
*
|
||||
* @param input The source time span in milliseconds
|
||||
* @param future The source time span in milliseconds
|
||||
* @return The resulting MiniTime string
|
||||
*
|
||||
* @throws IllegalArgumentException on a negative time duration
|
||||
|
|
|
@ -199,7 +199,7 @@ public class StaticPlutoEventManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ package cz.tefek.pluto.io.asl.resource;
|
|||
*
|
||||
* @author 493msi
|
||||
*
|
||||
* @param R The type of the loaded <tt>Resource</tt>.
|
||||
* @param <R> The type of the loaded <tt>Resource</tt>.
|
||||
*/
|
||||
public abstract class Resource<R>
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ResourceImage extends Resource<BufferedImage>
|
|||
catch (IOException e)
|
||||
{
|
||||
Logger.log(Severity.ERROR, "Could not load BufferedImage: " + this.address.toString() + ", will load placeholder.");
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ public class ResourceImage extends Resource<BufferedImage>
|
|||
Logger.log(Severity.ERROR, "Placeholder BufferedImage not found: " + ResourceHelper.GLOBAL_ROOT + "data/assets/err/missingTex.png");
|
||||
Logger.log("This is not good! :C");
|
||||
|
||||
Logger.logException(e1);
|
||||
Logger.log(e1);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -27,7 +27,7 @@ public class TextIn
|
|||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -41,7 +41,7 @@ public class TextIn
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -55,7 +55,7 @@ public class TextIn
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,96 +1,224 @@
|
|||
package cz.tefek.pluto.io.logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import cz.tefek.pluto.io.asl.resource.ResourceHelper;
|
||||
import cz.tefek.pluto.io.asl.textio.TextOut;
|
||||
|
||||
/**
|
||||
* Logger. 'nuff said.
|
||||
* <p>
|
||||
* A simple static logger writing to both standard output and a log file.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The log file is currently hardcoded to {@link ResourceHelper#GLOBAL_ROOT}/<code>log--YYYY-MM-DD--HH-MM-SS.txt</code>
|
||||
* </p>
|
||||
*
|
||||
* @author 493msi
|
||||
*
|
||||
* @since pre-alpha
|
||||
*/
|
||||
public class Logger
|
||||
{
|
||||
static OutputStream stdout;
|
||||
static OutputStream stderr;
|
||||
private static PrintStream stdout = null;
|
||||
private static PrintStream stderr = null;
|
||||
|
||||
static FileOutputStream file_log;
|
||||
private static OutputStream fileLog = null;
|
||||
|
||||
static PrintStream stdoutStream;
|
||||
static PrintStream stderrStream;
|
||||
|
||||
public static void setup()
|
||||
/**
|
||||
* Initializes up the logger and replaces the standard output and standard error output with the logger methods.
|
||||
*
|
||||
* <p>
|
||||
* <em>
|
||||
* This method will close the logger first (if it is already open).
|
||||
* </em>
|
||||
* </p>
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static void setup() throws IOException
|
||||
{
|
||||
close();
|
||||
|
||||
stdout = new PrintStream(System.out);
|
||||
stderr = new PrintStream(System.err);
|
||||
|
||||
setupFileStream();
|
||||
// TODO: Unhardcode the log directory
|
||||
|
||||
stdoutStream = new PrintStream(new StdOutSplitStream());
|
||||
stderrStream = new PrintStream(new StdErrSplitStream());
|
||||
var logsDir = Path.of(ResourceHelper.GLOBAL_ROOT, "logs");
|
||||
|
||||
System.setOut(stdoutStream);
|
||||
System.setErr(stderrStream);
|
||||
}
|
||||
|
||||
private static void setupFileStream()
|
||||
if (!Files.isDirectory(logsDir))
|
||||
{
|
||||
try
|
||||
if (Files.exists(logsDir))
|
||||
{
|
||||
if (!new File(ResourceHelper.GLOBAL_ROOT + "logs").exists() || !new File(ResourceHelper.GLOBAL_ROOT + "logs").isDirectory())
|
||||
{
|
||||
new File(ResourceHelper.GLOBAL_ROOT + "logs").mkdirs();
|
||||
System.err.printf("[#] Failed to initialize the logger, the path `%s` is obstructed by a non-directory!%n", logsDir.toAbsolutePath().toString());
|
||||
return;
|
||||
}
|
||||
|
||||
file_log = TextOut.createFOStream(ResourceHelper.GLOBAL_ROOT + "logs/log" + System.currentTimeMillis() + ".txt");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
Files.createDirectories(logsDir);
|
||||
}
|
||||
|
||||
public static void close()
|
||||
{
|
||||
System.out.close();
|
||||
var dateTime = LocalDateTime.now();
|
||||
var logName = String.format("log--%04d-%02d-%02d--%02d-%02d-%02d.txt",
|
||||
dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(),
|
||||
dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond());
|
||||
|
||||
fileLog = Files.newOutputStream(logsDir.resolve(logName));
|
||||
|
||||
System.setOut(new PrintStream(new OutputSplitStream(stdout, false, fileLog, false)));
|
||||
System.setErr(new PrintStream(new OutputSplitStream(stderr, false, fileLog, false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the logger and its respective log file, if there is one.
|
||||
*
|
||||
* <p>
|
||||
* <em>
|
||||
* This method is a noop for an already closed logger.
|
||||
* </em>
|
||||
* </p>
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static void close() throws IOException
|
||||
{
|
||||
if (fileLog != null)
|
||||
fileLog.close();
|
||||
fileLog = null;
|
||||
|
||||
if (stdout != null)
|
||||
System.setOut(stdout);
|
||||
stdout = null;
|
||||
|
||||
if (stderr != null)
|
||||
System.setErr(stderr);
|
||||
stderr = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an object converted to a {@link String} to the stdout stream.
|
||||
*
|
||||
* <em>
|
||||
* Appends a newline.
|
||||
* </em>
|
||||
*
|
||||
* @param string The object convertible to a {@link String}
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void log(Object string)
|
||||
{
|
||||
log(Severity.NONE, string);
|
||||
System.out.println(string);
|
||||
}
|
||||
|
||||
public static synchronized void logf(String string, Object... o)
|
||||
/**
|
||||
* Logs a printf-style message to the stdout stream.
|
||||
*
|
||||
* <em>
|
||||
* No newline is appended.
|
||||
* </em>
|
||||
*
|
||||
* <em>
|
||||
* Appends a newline.
|
||||
* </em>
|
||||
*
|
||||
* @param formatSpec The format specifier {@link String}
|
||||
* @param o A list of input objects
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void logf(String formatSpec, Object... o)
|
||||
{
|
||||
System.out.printf(string, o);
|
||||
System.out.printf(formatSpec, o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an object converted to a {@link String} to the stdout stream <em>without appending a newline</em>.
|
||||
*
|
||||
* @param string The object convertible to a {@link String}
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void logNoLine(Object string)
|
||||
{
|
||||
System.out.print(string);
|
||||
}
|
||||
|
||||
public static synchronized void logException(Exception e)
|
||||
/**
|
||||
* Logs the stack trace of a {@link Throwable} to the stderr stream.
|
||||
*
|
||||
* @param e The throwable to log
|
||||
*
|
||||
* @since 20.2.0.0-alpha.1
|
||||
* */
|
||||
public static synchronized void log(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an empty message with the specified severity. That's it.
|
||||
*
|
||||
* <em>
|
||||
* A newline is automatically appended.
|
||||
* </em>
|
||||
*
|
||||
* @param s The severity of the logged message
|
||||
*
|
||||
* @since 20.2.0.0-alpha.1
|
||||
* */
|
||||
public static synchronized void log(ISeverity s)
|
||||
{
|
||||
(s.isStdErr() ? System.err : System.out).println(s.getDisplayName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an object converted to a {@link String} with the specified severity.
|
||||
*
|
||||
* <em>
|
||||
* A newline is automatically appended.
|
||||
* </em>
|
||||
*
|
||||
* @param s The severity of the logged message
|
||||
* @param string The object convertible to a {@link String}
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void log(ISeverity s, Object string)
|
||||
{
|
||||
(s.isStdErr() ? System.err : System.out).println(s.getDisplayName() + string);
|
||||
}
|
||||
|
||||
public static synchronized void logf(ISeverity s, String string, Object... o)
|
||||
/**
|
||||
* Logs a printf-style message with the specified severity.
|
||||
*
|
||||
* <em>
|
||||
* No newline is appended.
|
||||
* </em>
|
||||
*
|
||||
* @param s The severity of the logged message
|
||||
* @param formatSpec The format specifier {@link String}
|
||||
* @param o A list of input objects
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void logf(ISeverity s, String formatSpec, Object... o)
|
||||
{
|
||||
(s.isStdErr() ? System.err : System.out).printf(s.getDisplayName() + string, o);
|
||||
(s.isStdErr() ? System.err : System.out).printf(s.getDisplayName() + formatSpec, o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an object converted to a {@link String} with the specified severity <em>without appending a newline</em>.
|
||||
*
|
||||
* @param s The severity of the logged message
|
||||
* @param string The object convertable to a {@link String}
|
||||
*
|
||||
* @since pre-alpha
|
||||
* */
|
||||
public static synchronized void logNoLine(ISeverity s, Object string)
|
||||
{
|
||||
(s.isStdErr() ? System.err : System.out).print(s.getDisplayName() + string);
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package cz.tefek.pluto.io.logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Splits one {@link OutputStream} into two to allow writing to both log file
|
||||
* and console output.
|
||||
*
|
||||
* @author 493msi
|
||||
*
|
||||
*/
|
||||
class OutputSplitStream extends OutputStream
|
||||
{
|
||||
private final OutputStream outputStreamA;
|
||||
private final boolean shouldAClose;
|
||||
|
||||
private final OutputStream outputStreamB;
|
||||
private final boolean shouldBClose;
|
||||
|
||||
public OutputSplitStream(OutputStream outputStreamA, boolean shouldAClose,
|
||||
OutputStream outputStreamB, boolean shouldBClose)
|
||||
{
|
||||
this.outputStreamA = outputStreamA;
|
||||
this.shouldAClose = shouldAClose;
|
||||
|
||||
this.outputStreamB = outputStreamB;
|
||||
this.shouldBClose = shouldBClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
this.outputStreamA.write(b);
|
||||
this.outputStreamB.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException
|
||||
{
|
||||
this.outputStreamA.write(b);
|
||||
this.outputStreamB.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
this.outputStreamA.write(b, off, len);
|
||||
this.outputStreamB.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
this.outputStreamA.flush();
|
||||
this.outputStreamB.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
if (this.shouldAClose)
|
||||
outputStreamA.close();
|
||||
|
||||
if (this.shouldBClose)
|
||||
outputStreamB.close();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ package cz.tefek.pluto.io.logger;
|
|||
* A more visual way to denote what's actually happening.
|
||||
*
|
||||
* @author 493msi
|
||||
*
|
||||
* @since pre-alpha
|
||||
*/
|
||||
public enum SmartSeverity implements ISeverity
|
||||
{
|
||||
|
@ -34,8 +36,8 @@ public enum SmartSeverity implements ISeverity
|
|||
EVENT_WARNING("[!] [E] ", true),
|
||||
EVENT_ERROR("[X] [E] ", true);
|
||||
|
||||
private String displayName;
|
||||
private boolean usesStdErr;
|
||||
private final String displayName;
|
||||
private final boolean usesStdErr;
|
||||
|
||||
SmartSeverity(String name, boolean usesStdErr)
|
||||
{
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
package cz.tefek.pluto.io.logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Splits one {@link OutputStream} into two to allow writing to both log file
|
||||
* and console output.
|
||||
*
|
||||
* @author 493msi
|
||||
*
|
||||
*/
|
||||
class StdErrSplitStream extends OutputStream
|
||||
{
|
||||
public StdErrSplitStream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b);
|
||||
Logger.stderr.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b);
|
||||
Logger.stderr.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b, off, len);
|
||||
Logger.stderr.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
Logger.file_log.flush();
|
||||
Logger.stderr.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
Logger.file_log.close();
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package cz.tefek.pluto.io.logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Splits one {@link OutputStream} into two to allow writing to both log file
|
||||
* and console output.
|
||||
*
|
||||
* @author 493msi
|
||||
*
|
||||
*/
|
||||
class StdOutSplitStream extends OutputStream
|
||||
{
|
||||
public StdOutSplitStream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b);
|
||||
Logger.stdout.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b);
|
||||
Logger.stdout.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
Logger.file_log.write(b, off, len);
|
||||
Logger.stdout.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
Logger.file_log.flush();
|
||||
Logger.stdout.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
Logger.file_log.close();
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ public class ModClassLoader
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ModInstaller
|
|||
catch (IOException e)
|
||||
{
|
||||
Logger.log(SmartSeverity.MODULE_ERROR, "Unpacking of " + file + " failed!");
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
}
|
||||
|
||||
new File(ResourceHelper.GLOBAL_ROOT + "packages/" + file).delete();
|
||||
|
|
|
@ -211,7 +211,7 @@ public class ModLoaderCore
|
|||
Logger.log(SmartSeverity.MODULE_ERROR, "Problem encountered while pre-loading mods.");
|
||||
Logger.log(SmartSeverity.MODULE_ERROR, "Mod loading stopped.");
|
||||
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
cancelLoading();
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ public class ModLoaderCore
|
|||
Logger.log(SmartSeverity.MODULE_ERROR, "Problem encountered while loading mods.");
|
||||
Logger.log(SmartSeverity.MODULE_ERROR, "Mod loading stopped.");
|
||||
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
cancelLoading();
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ public class ModLoaderCore
|
|||
Logger.log(SmartSeverity.MODULE_ERROR, "Problem encountered while post-loading mods.");
|
||||
Logger.log(SmartSeverity.MODULE_ERROR, "Mod loading stopped.");
|
||||
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
cancelLoading();
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class TPL
|
|||
catch (Exception e)
|
||||
{
|
||||
Logger.log(SmartSeverity.ERROR, "[TPL] Image could not be loaded: " + file);
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
return loadImage(null);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public class TPL
|
|||
catch (Exception e)
|
||||
{
|
||||
Logger.log(SmartSeverity.ERROR, "[TPL] Image could not be loaded: " + file);
|
||||
Logger.logException(e);
|
||||
Logger.log(e);
|
||||
|
||||
remake = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue