Improve stack trace logging

Shorten log signatures
Add task to download recorded autos
This commit is contained in:
nathanrsxtn
2022-02-25 01:33:32 -07:00
parent 9ccf4bcea2
commit 9d5d58f032
9 changed files with 117 additions and 93 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ public final class Main {
*/
public static void main(String... args) {
AnsiLogging.systemInstall();
DurianPlugins.register(Errors.Plugins.Log.class, e -> Logger.getLogger(e.getStackTrace()[0].getClassName()).log(Level.SEVERE, e, e::getLocalizedMessage));
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));
RobotBase.startRobot(Robot::new);
}
}
+14 -15
View File
@@ -9,7 +9,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.StreamSupport;
import java.util.stream.IntStream;
import com.diffplug.common.base.Errors;
@@ -19,7 +19,6 @@ import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import edu.wpi.first.wpilibj2.command.InstantCommand;
import edu.wpi.first.wpilibj2.command.RunCommand;
import frc4388.utility.RobotTime;
@@ -31,7 +30,7 @@ import frc4388.utility.RobotTime;
* project.
*/
public class Robot extends TimedRobot {
private static final Logger LOGGER = Logger.getLogger(Robot.class.getName());
private static final Logger LOGGER = Logger.getLogger(Robot.class.getSimpleName());
Command m_autonomousCommand;
private RobotTime m_robotTime = RobotTime.getInstance();
@@ -43,22 +42,21 @@ public class Robot extends TimedRobot {
*/
@Override
public void robotInit() {
// if (org.fusesource.jansi.Ansi.isEnabled()) {
LOGGER.log(Level.ALL, "Logging Test 1/8");
LOGGER.log(Level.SEVERE, "Logging Test 2/8");
LOGGER.log(Level.WARNING, "Logging Test 3/8");
LOGGER.log(Level.INFO, "Logging Test 4/8");
LOGGER.log(Level.CONFIG, "Logging Test 5/8");
LOGGER.log(Level.FINE, "Logging Test 6/8");
LOGGER.log(Level.FINER, "Logging Test 7/8");
LOGGER.log(Level.FINEST, "Logging Test 8/8");
// }
LOGGER.log(Level.ALL, "Logging Test 1/8");
LOGGER.log(Level.SEVERE, "Logging Test 2/8");
LOGGER.log(Level.WARNING, "Logging Test 3/8");
LOGGER.log(Level.INFO, "Logging Test 4/8");
LOGGER.log(Level.CONFIG, "Logging Test 5/8");
LOGGER.log(Level.FINE, "Logging Test 6/8");
LOGGER.log(Level.FINER, "Logging Test 7/8");
LOGGER.log(Level.FINEST, "Logging Test 8/8");
Errors.log().run(() -> { throw new Throwable("Exception Test"); });
// var path = PathPlannerUtil.Path.read(Filesystem.getDeployDirectory().toPath().resolve("pathplanner").resolve("Move Forward.path").toFile());
// LOGGER.finest(path::toString);
LOGGER.fine("robotInit()");
LOGGER.fine("Sssssssssh.");
DriverStation.silenceJoystickConnectionWarning(true);
// LOGGER.fine("Sssssssssh.");
// DriverStation.silenceJoystickConnectionWarning(true);
// Instantiate our RobotContainer. This will perform all our button bindings, and put our
// autonomous chooser on the dashboard.
m_robotContainer = new RobotContainer();
@@ -110,6 +108,7 @@ public class Robot extends TimedRobot {
SmartDashboard.putNumber("Odometry X", m_robotContainer.getOdometry().getX());
SmartDashboard.putNumber("Odometry Y", m_robotContainer.getOdometry().getY());
SmartDashboard.putNumber("Odometry Theta", m_robotContainer.getOdometry().getRotation().getDegrees());
IntStream.range(0, 9999).forEach(Math::cos);
}
/**
@@ -75,7 +75,7 @@ import frc4388.utility.controller.DeadbandedXboxController;
* commands, and button mappings) should be declared here.
*/
public class RobotContainer {
private static final Logger LOGGER = Logger.getLogger(RobotContainer.class.getName());
private static final Logger LOGGER = Logger.getLogger(RobotContainer.class.getSimpleName());
/* RobotMap */
private final RobotMap m_robotMap = new RobotMap();
@@ -237,7 +237,7 @@ public class RobotContainer {
m_robotSwerveDrive::setModuleStates, m_robotSwerveDrive),
new InstantCommand(m_robotSwerveDrive::stopModules)).withName("Run Autonomous Path");
} else {
Logger.getLogger(this.getClass().getName()).severe("No auto selected.");
LOGGER.severe("No auto selected.");
return new RunCommand(() -> {
}).withName("No Autonomous Path");
}
@@ -27,7 +27,7 @@ public class LED extends SubsystemBase {
m_LEDController = LEDController;
setPattern(LEDConstants.DEFAULT_PATTERN);
updateLED();
Logger.getLogger(LED.class.getName()).finer("In the Beginning, there was Joe.\nAnd he said, 'Let there be LEDs.'\nAnd it was good.");
Logger.getLogger(LED.class.getSimpleName()).finer("In the Beginning, there was Joe.\nAnd he said, 'Let there be LEDs.'\nAnd it was good.");
}
@Override
+44 -41
View File
@@ -9,6 +9,8 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.Optional;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
@@ -19,10 +21,6 @@ import java.util.logging.Logger;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Attribute;
import org.fusesource.jansi.Ansi.Color;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import org.fusesource.jansi.AnsiConsole;
public class AnsiLogging extends ConsoleHandler {
@@ -31,67 +29,72 @@ public class AnsiLogging extends ConsoleHandler {
// Configures java.util.logging.Logger to output additional colored information.
LogManager.getLogManager().updateConfiguration(key -> (o, n) -> {
switch (key) {
case ".level": return Level.ALL.getName();
case "handlers": return AnsiColorConsoleHandler.class.getName();
default: return n;
case ".level":
return Level.ALL.getName();
case "handlers":
return AnsiColorConsoleHandler.class.getName();
default:
return n;
}
});
// Replaces standard output streams with org.fusesource.jansi.AnsiPrintStreams.
AnsiConsole.systemInstall();
// Replaces standard output stream with java.util.logging.Logger.
System.setOut(printStreamLogger(Logger.getGlobal(), Level.ALL));
System.setOut(printStreamLogger(Logger.getGlobal(), Level.INFO));
// Replaces standard error output stream with java.util.logging.Logger.
System.setErr(printStreamLogger(Logger.getGlobal(), Level.SEVERE));
} catch (IOException exception) {
exception.printStackTrace(AnsiConsole.sysErr());
}
}
public static class AnsiColorConsoleHandler extends ConsoleHandler {
@Override
public void publish(LogRecord logRecord) {
AnsiConsole.err().print(getFormatter().format(logRecord));
AnsiConsole.err().flush();
}
@Override
public Formatter getFormatter() {
return formatter;
}
private static final Formatter formatter = new Formatter() {
private final ZoneId zoneId = ZoneId.systemDefault();
private final Map<Integer, String> levelColors = Map.of(
Level.OFF.intValue(), "",
Level.SEVERE.intValue(), makeSignatureFormatString(ansi().fgBright(Color.RED)),
Level.WARNING.intValue(), makeSignatureFormatString(ansi().fgBright(Color.YELLOW)),
Level.INFO.intValue(), makeSignatureFormatString(ansi().fg(Color.GREEN)),
Level.CONFIG.intValue(), makeSignatureFormatString(ansi().fgBright(Color.BLUE)),
Level.FINE.intValue(), makeSignatureFormatString(ansi().fg(Color.CYAN)),
Level.FINER.intValue(), makeSignatureFormatString(ansi().fg(Color.MAGENTA)),
Level.FINEST.intValue(), makeSignatureFormatString(ansi().fgBright(Color.BLACK)),
Level.ALL.intValue(), makeSignatureFormatString(ansi().fg(Color.DEFAULT))
);
private String makeSignatureFormatString(Ansi base) {
return base.bold().a(Attribute.UNDERLINE).a("[%1$tb %1$td %1$tk:%1$tM:%1$tS.%1$tL] %2$s %3$s:").boldOff().a(Attribute.UNDERLINE_OFF).a("%4$s%5$s").a(Attribute.INTENSITY_FAINT).a("%6$s").reset().a("%n").toString();
}
private String makeStackTraceString(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
printWriter.println();
throwable.printStackTrace(printWriter);
}
return stringWriter.toString();
}
@Override
public String format(LogRecord logRecord) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(logRecord.getInstant(), ZoneId.systemDefault());
String source;
if (logRecord.getSourceClassName() != null && !logRecord.getSourceClassName().startsWith(AnsiLogging.class.getName())) {
source = logRecord.getSourceClassName();
if (logRecord.getSourceMethodName() != null) {
source += " " + logRecord.getSourceMethodName();
}
} else
source = logRecord.getLoggerName();
ZonedDateTime time = ZonedDateTime.ofInstant(logRecord.getInstant(), zoneId);
String source = Optional.ofNullable(logRecord.getLoggerName()).or(() -> Optional.ofNullable(logRecord.getSourceClassName())).map(s -> s + " ").orElse("") + Optional.ofNullable(logRecord.getSourceMethodName()).orElse("");
String message = formatMessage(logRecord);
boolean multiline = message.contains("\n");
String throwable = "";
if (logRecord.getThrown() != null) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
pw.println();
logRecord.getThrown().printStackTrace(pw);
}
throwable = sw.toString();
multiline = true;
}
Ansi ansi;
if (logRecord.getLevel() == Level.SEVERE) ansi = ansi().fgBright(Color.RED);
else if (logRecord.getLevel() == Level.WARNING) ansi = ansi().fgBright(Color.YELLOW);
else if (logRecord.getLevel() == Level.INFO) ansi = ansi().fg(Color.GREEN);
else if (logRecord.getLevel() == Level.CONFIG) ansi = ansi().fgBright(Color.BLUE);
else if (logRecord.getLevel() == Level.FINE) ansi = ansi().fg(Color.CYAN);
else if (logRecord.getLevel() == Level.FINER) ansi = ansi().fg(Color.MAGENTA);
else if (logRecord.getLevel() == Level.FINEST) ansi = ansi().fgBright(Color.BLACK);
else ansi = ansi().fg(Color.DEFAULT);
String format = ansi.bold().a(Attribute.UNDERLINE).a("%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s %4$s:").boldOff().a(Attribute.UNDERLINE_OFF).a(multiline ? "%n%5$s%6$s" : " %5$s%6$s").reset().a("%n").toString();
return String.format(format, zdt, source, logRecord.getLoggerName(), logRecord.getLevel().getLocalizedName(), message, throwable);
String throwable = Optional.ofNullable(logRecord.getThrown()).map(this::makeStackTraceString).orElse("");
String format = levelColors.getOrDefault(logRecord.getLevel().intValue(), levelColors.get(Level.ALL.intValue()));
return String.format(format, time, source, logRecord.getLevel().getLocalizedName(), message.lines().count() > 1 ? System.lineSeparator() : " ", message, throwable);
}
};
}
@@ -101,7 +104,7 @@ public class AnsiLogging extends ConsoleHandler {
private final StringBuilder stringBuilder = new StringBuilder();
@Override
public final void write(int i) throws IOException {
public void write(int i) throws IOException {
if (i == '\n') {
logger.log(level, stringBuilder::toString);
stringBuilder.setLength(0);