diff --git a/src/main/java/edu/wpi/first/wpilibj/DriverStation.java b/src/main/java/edu/wpi/first/wpilibj/DriverStation.java index ed643e5..aa735b2 100644 --- a/src/main/java/edu/wpi/first/wpilibj/DriverStation.java +++ b/src/main/java/edu/wpi/first/wpilibj/DriverStation.java @@ -567,23 +567,26 @@ public class DriverStation { if (!frc4388.utility.AnsiLogging.LEVEL.equals(java.util.logging.Level.OFF)) { java.util.logging.LogRecord logRecord = new java.util.logging.LogRecord(isError ? java.util.logging.Level.SEVERE : java.util.logging.Level.FINER, error.stripTrailing()); logRecord.setLoggerName("HAL"); - if (!frc4388.utility.AnsiLogging.halLoggerHandler.isLoggable(logRecord)) return; - java.util.Optional.ofNullable(stackTrace).filter(s -> s.length >= stackTraceFirst + 1).map(s -> java.util.Arrays.copyOfRange(s, Math.min(Math.max(0, stackTraceFirst), s.length - 1), s.length - 1)).ifPresent(presentStackTrace -> { + if (stackTrace != null && stackTrace.length >= stackTraceFirst + 1) { + StackTraceElement[] presentStackTrace = java.util.Arrays.copyOfRange(stackTrace, Math.min(Math.max(0, stackTraceFirst), stackTrace.length - 1), stackTrace.length - 1); logRecord.setSourceMethodName(presentStackTrace[0].getMethodName()); - String throwableMessage; - if (presentStackTrace[0].toString().equals("edu.wpi.first.wpilibj.Tracer.lambda$printEpochs$0(Tracer.java:63)")) { - throwableMessage = "Epochs" + System.lineSeparator() + logRecord.getMessage(); - presentStackTrace = new java.lang.StackTraceElement[0]; - logRecord.setLevel(java.util.logging.Level.FINEST); - logRecord.setMessage("Execution times:"); - } else if (printTrace) { - long lineCount = logRecord.getMessage().lines().count(); - throwableMessage = (lineCount > 1 ? logRecord.getMessage().lines().findFirst().map(s -> s + " + " + lineCount + " more lines...").orElse("") : logRecord.getMessage()).stripLeading(); - } else return; - java.lang.Throwable throwable = new java.lang.Throwable(throwableMessage); - throwable.setStackTrace(presentStackTrace); - logRecord.setThrown(throwable); - }); + boolean isEpochs = !printTrace && presentStackTrace[0].toString().equals("edu.wpi.first.wpilibj.Tracer.lambda$printEpochs$0(Tracer.java:63)"); + if (printTrace || isEpochs) { + String throwableMessage; + if (isEpochs) { + throwableMessage = "Epochs" + System.lineSeparator() + logRecord.getMessage(); + presentStackTrace = new java.lang.StackTraceElement[0]; + logRecord.setLevel(java.util.logging.Level.FINEST); + logRecord.setMessage("Execution times:"); + } else { + long lineCount = logRecord.getMessage().lines().count(); + throwableMessage = (lineCount > 1 ? logRecord.getMessage().lines().findFirst().map(s -> s + " + " + (lineCount - 1) + " more lines...").orElseThrow() : logRecord.getMessage()); + } + java.lang.Throwable throwable = new java.lang.Throwable(throwableMessage); + throwable.setStackTrace(presentStackTrace); + logRecord.setThrown(throwable); + } + } if (!frc4388.utility.AnsiLogging.halLoggerHandler.isLoggable(logRecord)) return; frc4388.utility.AnsiLogging.halLoggerHandler.publish(logRecord); } diff --git a/src/main/java/frc4388/utility/AnsiLogging.java b/src/main/java/frc4388/utility/AnsiLogging.java index 3a2b9c1..f2ddda1 100644 --- a/src/main/java/frc4388/utility/AnsiLogging.java +++ b/src/main/java/frc4388/utility/AnsiLogging.java @@ -12,7 +12,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Map; import java.util.Optional; -import java.util.logging.ConsoleHandler; +import java.util.function.Consumer; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; @@ -52,13 +52,13 @@ public class AnsiLogging { // Set the console to process ANSI escape codes. ANSI_CONSOLE_STREAM.install(); // Sends standard output stream messages through a logger. - System.setOut(printStreamLogger(Logger.getGlobal(), "out", Level.INFO)); + System.setOut(printStreamLogger(false, s -> Logger.getGlobal().logp(Level.INFO, null, "out", s))); // Sends standard error output stream messages through a logger. - System.setErr(printStreamLogger(Logger.getGlobal(), "err", Level.SEVERE)); + System.setErr(printStreamLogger(false, s -> Logger.getGlobal().logp(Level.SEVERE, null, "err", s))); // This is registering a plugin that will log Durian errors to the console using a logger. DurianPlugins.register(Errors.Plugins.Log.class, e -> Logger.getLogger(e.getStackTrace()[0].getClassName().substring(e.getStackTrace()[0].getClassName().lastIndexOf('.') + 1)).log(Level.SEVERE, e, e::getLocalizedMessage)); // Store the handler for HAL to use when sending errors to DriverStation. - halLoggerHandler = new LoggingAnsiConsoleHandler(new HalOutputStream()); + halLoggerHandler = new LoggingAnsiConsoleHandler(printStreamLogger(true, s -> HAL.sendError(false, 0, false, s, "", "", true))); } catch (IOException exception) { exception.printStackTrace(AnsiConsole.sysErr()); } @@ -90,7 +90,8 @@ public class AnsiLogging { printWriter.println(); throwable.printStackTrace(printWriter); } - return stringWriter.toString(); + StringBuffer stringBuffer = stringWriter.getBuffer(); + return stringBuffer.substring(0, Math.max(0, stringBuffer.length() - 1)); } @Override @@ -98,7 +99,7 @@ public class AnsiLogging { ZonedDateTime time = ZonedDateTime.ofInstant(logRecord.getInstant(), ZONE_ID); // Get the logger name, source class name, and/or source method name. String source = Optional.ofNullable(logRecord.getLoggerName()).or(() -> Optional.ofNullable(logRecord.getSourceClassName())).map(s -> s + " ").orElse("") + Optional.ofNullable(logRecord.getSourceMethodName()).orElse(""); - String message = formatMessage(logRecord); + String message = logRecord.getMessage(); // Get the stack trace of the exception if it was thrown. String throwable = Optional.ofNullable(logRecord.getThrown()).map(LoggingAnsiFormatter::makeStackTraceString).orElse(""); // Select the appropriate format string for the log level. @@ -125,27 +126,14 @@ public class AnsiLogging { } } - private static PrintStream printStreamLogger(Logger logger, String source, Level level) { + private static PrintStream printStreamLogger(boolean strip, Consumer logger) { return new PrintStream(new ByteArrayOutputStream() { @Override public void flush() throws IOException { - String s = toString(); - if (!s.isBlank()) logger.logp(level, null, source, s); + String s = new String(buf, 0, strip ? count - 1 : count); + if (!s.isBlank()) logger.accept(s); reset(); } }, true); } - - private static class HalOutputStream extends ByteArrayOutputStream { - @Override - public synchronized void write(int b) { - if (b == '\n') flush(); - else super.write(b); - } - @Override - public void flush() { - HAL.sendError(false, 0, false, new String(buf, 0, count - 1), "", "", true); - reset(); - } - } } \ No newline at end of file