In addition to the configurable logger options, DogLog also allows you to extend the logger class to add your own custom behavior. This is a great way to simplify common logging flows your team has, and reduce duplicated code in your robot projects.
This guide will walk you through the steps to create a custom logger class that allows you to add your own custom behavior. As an example, we will add in a new log() method to help log motor values.
Add DogLog to your project if you haven't already:
Create a new file for your extended logger class:
Directorysrc
Directorymain
Directorydeploy/
- …
Directoryjava/
Directoryfrc/
Directoryrobot/
- CustomLogger.java Create this file
- Main.java
- Robot.java
- RobotContainer.java
In the newly created file, paste the following code:
src/main/java/frc/robot/CustomLogger.java package frc.robot;import com.ctre.phoenix6.hardware.TalonFX;import dev.doglog.DogLog;public class CustomLogger extends DogLog {public static void log(String key, TalonFX motor) {log(key + "/StatorCurrent", motor.getStatorCurrent().getValue());log(key + "/Position", motor.getPosition().getValue());log(key + "/Velocity", motor.getVelocity().getValue());}}Replace places where you use
DogLogwithCustomLogger.package frc.robot;import com.ctre.phoenix6.hardware.TalonFX;import dev.doglog.DogLog;public class ExampleClass {private final TalonFX motor = new TalonFX(1);public void logData() {DogLog.log("ExampleMotor/StatorCurrent", motor.getStatorCurrent().getValue());DogLog.log("ExampleMotor/Position", motor.getPosition().getValue());DogLog.log("ExampleMotor/Velocity", motor.getVelocity().getValue());CustomLogger.log("ExampleMotor", motor);}}
Timing commands
Section titled “Timing commands”If you want to track how long a command takes to run, you can extend the logger with a helper that wraps a command with a timer.
Create a
CustomLoggerclass if you don't already have one, following the steps above.Create a new file for the command wrapper:
Directorysrc
Directorymain
Directorydeploy/
- …
Directoryjava/
Directoryfrc/
Directoryrobot/
- CustomLogger.java
- TimedCommand.java Create this file
- Main.java
- Robot.java
- RobotContainer.java
Paste in the wrapper for your command framework version, then add a matching
time()method to yourCustomLogger:This wraps a Commands v3 command and logs its total execution time in seconds.
src/main/java/frc/robot/TimedCommand.java package frc.robot;import dev.doglog.DogLog;import java.util.Set;import org.wpilib.command3.Command;import org.wpilib.command3.Coroutine;import org.wpilib.command3.Mechanism;import org.wpilib.hardware.hal.HALUtil;public class TimedCommand implements Command {private final Command command;private final String key;public TimedCommand(Command command, String key) {this.command = command;this.key = key;}@Overridepublic String name() {return "Timed" + command.name();}@Overridepublic int priority() {return command.priority();}@Overridepublic Set<Mechanism> requirements() {return command.requirements();}@Overridepublic void run(Coroutine coroutine) {var startTime = HALUtil.getMonotonicTime();coroutine.await(command);var elapsed = (HALUtil.getMonotonicTime() - startTime) / 1_000_000_000.0;DogLog.log(key, elapsed);}}Then add a
time()method to yourCustomLoggerso you can wrap commands with it. The highlighted lines are what you need to add:src/main/java/frc/robot/CustomLogger.java package frc.robot;import dev.doglog.DogLog;import org.wpilib.command3.Command;public class CustomLogger extends DogLog {public static Command time(String key, Command command) {return new TimedCommand(command, key);}}This wraps a Commands v2 command and logs the duration of each phase of the command (
initialize,execute,end).src/main/java/frc/robot/TimedCommand.java package frc.robot;import dev.doglog.DogLog;import org.wpilib.command2.Command;import org.wpilib.command2.CommandScheduler;public class TimedCommand extends Command {private final Command command;private final String key;public TimedCommand(Command command, String key) {this.command = command;this.key = key;setName("Timed" + command.getName());CommandScheduler.getInstance().registerComposedCommands(command);addRequirements(command.getRequirements());}@Overridepublic void end(boolean interrupted) {var logKey = key + "/.end(" + interrupted + ")";DogLog.time(logKey);command.end(interrupted);DogLog.timeEnd(logKey);}@Overridepublic void execute() {DogLog.time(key + "/.execute()");command.execute();DogLog.timeEnd(key + "/.execute()");}@Overridepublic void initialize() {DogLog.time(key + "/.initialize()");command.initialize();DogLog.timeEnd(key + "/.initialize()");}@Overridepublic boolean isFinished() {return command.isFinished();}@Overridepublic boolean runsWhenDisabled() {return command.runsWhenDisabled();}}Then add a
time()method to yourCustomLoggerso you can wrap commands with it. The highlighted lines are what you need to add:src/main/java/frc/robot/CustomLogger.java package frc.robot;import dev.doglog.DogLog;import org.wpilib.command2.Command;public class CustomLogger extends DogLog {public static Command time(String key, Command command) {return new TimedCommand(command, key);}}Wrap your commands with the new
time()method:src/main/java/frc/robot/RobotContainer.java public Command getAutonomousCommand() {return CustomLogger.time("Autos/AutoCommand", Commands.waitTime(Units.Seconds.of(0.75)).withName("MyAutoCommand"));}