mirror of
https://github.com/Team4388/2022NoWayHome.git
synced 2026-06-09 00:38:05 -06:00
Improve stack trace logging
Shorten log signatures Add task to download recorded autos
This commit is contained in:
@@ -160,3 +160,5 @@ bin/
|
||||
|
||||
# Simulation GUI and other tools window save file
|
||||
*-window.json
|
||||
|
||||
src/main/deploy/config.json
|
||||
Vendored
+2
-8
@@ -4,13 +4,6 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Launch Main",
|
||||
"request": "launch",
|
||||
"mainClass": "frc4388.robot.Main",
|
||||
"projectName": "2022NoWayHome"
|
||||
},
|
||||
{
|
||||
"type": "wpilib",
|
||||
"name": "WPILib Desktop Debug",
|
||||
@@ -21,7 +14,8 @@
|
||||
"type": "wpilib",
|
||||
"name": "WPILib roboRIO Debug",
|
||||
"request": "launch",
|
||||
"desktop": false
|
||||
"desktop": false,
|
||||
"postDebugTask": "downloadDeployDirectory"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+14
-5
@@ -1,10 +1,19 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "downloadDeployDirectory",
|
||||
"type": "shell",
|
||||
"command": "scp -pr lvuser@roboRIO-4388-FRC.local:/home/lvuser/deploy ./deploy"
|
||||
}
|
||||
{
|
||||
"label": "downloadDeployDirectory",
|
||||
"type": "shell",
|
||||
"command": "scp -prv lvuser@roboRIO-4388-FRC.local:/home/lvuser/deploy ./src/main/",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "dedicated",
|
||||
"showReuseMessage": true,
|
||||
"clear": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -399,29 +399,46 @@ public class DriverStation {
|
||||
boolean printTrace,
|
||||
StackTraceElement[] stackTrace,
|
||||
int stackTraceFirst) {
|
||||
String locString;
|
||||
if (stackTrace.length >= stackTraceFirst + 1) {
|
||||
locString = stackTrace[stackTraceFirst].toString();
|
||||
} else {
|
||||
locString = "";
|
||||
}
|
||||
StringBuilder traceString = new StringBuilder();
|
||||
if (printTrace) {
|
||||
boolean haveLoc = false;
|
||||
for (int i = stackTraceFirst; i < stackTrace.length; i++) {
|
||||
String loc = stackTrace[i].toString();
|
||||
traceString.append("\tat ").append(loc).append('\n');
|
||||
// get first user function
|
||||
if (!haveLoc && !loc.startsWith("edu.wpi.first")) {
|
||||
locString = loc;
|
||||
haveLoc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// String locString;
|
||||
// if (stackTrace.length >= stackTraceFirst + 1) {
|
||||
// locString = stackTrace[stackTraceFirst].toString();
|
||||
// } else {
|
||||
// locString = "";
|
||||
// }
|
||||
// StringBuilder traceString = new StringBuilder();
|
||||
// if (printTrace) {
|
||||
// boolean haveLoc = false;
|
||||
// for (int i = stackTraceFirst; i < stackTrace.length; i++) {
|
||||
// String loc = stackTrace[i].toString();
|
||||
// traceString.append("\tat ").append(loc).append('\n');
|
||||
// // get first user function
|
||||
// if (!haveLoc && !loc.startsWith("edu.wpi.first")) {
|
||||
// locString = loc;
|
||||
// haveLoc = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// HAL.sendError(isError, code, false, error, locString, traceString.toString(), true);
|
||||
// for (StackTraceElement traceElement : stackTrace)
|
||||
// System.err.println("\tat " + traceElement);
|
||||
java.util.logging.Logger.getLogger(HAL.class.getName()).log(isError ? java.util.logging.Level.SEVERE : java.util.logging.Level.FINEST, "Warning at {0}: {1}", new Object[] {locString, error.split("\n")[0]});
|
||||
java.util.logging.LogRecord logRecord = new java.util.logging.LogRecord(isError ? java.util.logging.Level.SEVERE : java.util.logging.Level.FINER, error.stripTrailing());
|
||||
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 -> {
|
||||
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);
|
||||
});
|
||||
java.util.logging.Logger.getLogger(HAL.class.getSimpleName()).log(logRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user