Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logkitten improvements #216

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
quialst marked this conversation as resolved.
Show resolved Hide resolved
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
17 changes: 17 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
quialst marked this conversation as resolved.
Show resolved Hide resolved
<projectDescription>
<name>standard</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
55 changes: 55 additions & 0 deletions CANKitten.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.usfirst.frc4904.standard;

public class CANKitten extends Kitten {
public CANKitten(String category) {
super(category);
}

public static void logCAN(char kittenLevel, String message) {
switch(kittenLevel) {
case 'f':
LogKitten.f(message);
break;
case 'e':
LogKitten.e(message);
break;
case 'w':
LogKitten.w(message);
break;
case 'v':
LogKitten.v(message);
break;
case 'd':
LogKitten.d(message);
break;
}
}

public static void logCAN(char kittenLevel, String message, Boolean override) {
switch(kittenLevel) {
case 'f':
LogKitten.f(message, override);
break;
case 'e':
LogKitten.e(message, override);
break;
case 'w':
LogKitten.w(message, override);
break;
case 'v':
LogKitten.v(message, override);
break;
case 'd':
LogKitten.d(message, override);
break;
}
}

public static void logCANError(Exception ex) {
LogKitten.ex(ex);
}

public static void logCANError(Exception ex, Boolean override) {
LogKitten.ex(ex, override);
}
}
46 changes: 46 additions & 0 deletions Kitten.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.usfirst.frc4904.standard;

import java.io.BufferedOutputStream;
import org.usfirst.frc4904.standard.LogKitten;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Kitten {
protected final static String LOG_PATH = LogKitten.getLogPath();
public String category;
public BufferedOutputStream output;
public String generalPath;
public File pathDirectory;
public String specificPath;
public String specificAliasPath;
public File logger;
public File loggerAlias;
private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
protected volatile boolean mute;

public Kitten(String category) {
this.category = category;
this.generalPath = Kitten.LOG_PATH + this.category;
this.pathDirectory = new File(this.generalPath);
this.specificPath = this.generalPath + timestamp() + ".log";
this.logger = new File(this.specificPath);
this.specificAliasPath = this.specificPath + "recent.log";
this.loggerAlias = new File(this.specificAliasPath);
this.mute = false;
}

public boolean getMute() {
return this.getMute();
}

public void setMute(boolean mute) {
this.mute = mute;
}

public synchronized String timestamp() {
return TIMESTAMP_FORMAT.format(new Date());
}


}
166 changes: 134 additions & 32 deletions LogKitten.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.usfirst.frc4904.robot.RobotMap;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.hal.HAL;

public class LogKitten {
private static BufferedOutputStream fileOutput;
private static BufferedOutputStream globalOutput;
private static Map<Kitten, String> kittenList; // Hashmap with <Kitten, String(what subclass the corresponding kitten is)>
public final static KittenLevel LEVEL_WTF = KittenLevel.WTF;
public final static KittenLevel LEVEL_FATAL = KittenLevel.FATAL;
public final static KittenLevel LEVEL_ERROR = KittenLevel.ERROR;
Expand All @@ -26,44 +31,99 @@ public class LogKitten {
private static KittenLevel logLevel = LogKitten.DEFAULT_LOG_LEVEL;
private static KittenLevel printLevel = LogKitten.DEFAULT_PRINT_LEVEL;
private static KittenLevel dsLevel = LogKitten.DEFAULT_DS_LEVEL;
private static String GLOBAL_PATH = "/home/lvuser/logs/global/";
private static String LOG_PATH = "/home/lvuser/logs/";
private static String LOG_ALIAS_PATH = LogKitten.LOG_PATH + "recent.log";
private static String GLOBAL_ALIAS_PATH = LogKitten.GLOBAL_PATH + "recent.log";
private static volatile boolean PRINT_MUTE = false;
private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
static {
File logPathDirectory = new File(LogKitten.LOG_PATH);
kittenList = new HashMap<Kitten, String>();
kittenList.put(RobotMap.Kittens.autonKitten, "RobotModeKitten");
kittenList.put(RobotMap.Kittens.teleopKitten, "RobotModeKitten");
File globalPathDirectory = new File(LogKitten.GLOBAL_PATH);
try {
if (!logPathDirectory.isDirectory()) { // ensure that the directory /home/lvuser/logs/ exists
logPathDirectory.mkdirs(); // otherwise create all the directories of the path
if (!globalPathDirectory.isDirectory()) { // ensure that the directory /home/lvuser/logs/global/ exists
globalPathDirectory.mkdirs(); // otherwise create all the directories of the path
}
}
catch (SecurityException se) {
System.out.println("Could not create log directory");
System.out.println("Could not create global log directory");
se.printStackTrace();
}
String filePath = LogKitten.LOG_PATH + LogKitten.timestamp() + ".log"; // Set this sessions log to /home/lvuser/logs/[current time].log
File file = new File(filePath);
for(Map.Entry<Kitten, String> i : kittenList.entrySet()) {
try {
if (!i.getKey().pathDirectory.isDirectory()) {
i.getKey().pathDirectory.mkdirs();
}
}
catch (SecurityException se) {
System.out.println("Could not create " + i.getKey().category + " log directory");
se.printStackTrace();
}
}
String globalPath = LogKitten.GLOBAL_PATH + LogKitten.timestamp() + ".log"; // Set this sessions log to /home/lvuser/logs/global/[current time].log
File global = new File(globalPath);
try {
// Create new file if it doesn't exist (this should happen)
file.createNewFile(); // creates if does not exist
global.createNewFile(); // creates if does not exist
// Create FileOutputStream to actually write to the file.
LogKitten.fileOutput = new BufferedOutputStream(new FileOutputStream(file));
LogKitten.globalOutput = new BufferedOutputStream(new FileOutputStream(global));
}
catch (IOException ioe) {
System.out.println("Could not open logfile");
System.out.println("Could not open global logfile");
ioe.printStackTrace();
}
File logAlias = new File(LogKitten.LOG_ALIAS_PATH);
for(Map.Entry<Kitten, String> i : kittenList.entrySet()) {
try {
i.getKey().logger.createNewFile();
i.getKey().output = new BufferedOutputStream(new FileOutputStream(i.getKey().logger));
}
catch (IOException ioe) {
System.out.println("Could not open " + i.getKey().category + " log directory");
ioe.printStackTrace();
}
}
File globalAlias = new File(LogKitten.GLOBAL_ALIAS_PATH);
try {
if (logAlias.exists()) {
logAlias.delete();
if(globalAlias.exists()) {
globalAlias.delete();
}
Files.createSymbolicLink(logAlias.toPath(), file.toPath());
Files.createSymbolicLink(globalAlias.toPath(), global.toPath());
}
catch (IOException ioe) {
System.out.println("Could not alias logfile");
System.out.println("Could not alias global logfile");
ioe.printStackTrace();
}
for(Map.Entry<Kitten, String> i : kittenList.entrySet()) {
try {
if(i.getKey().loggerAlias.exists()) {
i.getKey().loggerAlias.delete();
}
Files.createSymbolicLink(i.getKey().loggerAlias.toPath(), i.getKey().logger.toPath());
}
catch (IOException ioe) {
System.out.println("Could not alias " + i.getKey().category + " logfile");
}
}
}//static ends

/**
* Gets the mode of the robot
*
* @return a string with either auton or teleop
*/
private static String getRobotMode(){
String robotMode = null;
if(DriverStation.getInstance().isAutonomous()) {
quialst marked this conversation as resolved.
Show resolved Hide resolved
robotMode = "AUTONOMOUS";
}else if(!DriverStation.getInstance().isAutonomous()) {
robotMode = "TELEOPERATED";
}
return robotMode;
}

public static String getLogPath() {
return LOG_PATH;
}

/**
Expand Down Expand Up @@ -119,15 +179,15 @@ public static void setDefaultDSLevel(KittenLevel DEFAULT_DS_LEVEL) {
}

/**
* Set the logfile path for all LogKitten instances
* Set the globalfile path for all LogKitten instances
*
* @param LOG_PATH
* logfile path as a string
* @param GLOBAL_PATH
* globalfile path as a string
*/
public static void setLogPath(String LOG_PATH) {
LogKitten.LOG_PATH = LOG_PATH;
public static void setGlobalPath(String GLOBAL_PATH) {
LogKitten.GLOBAL_PATH = GLOBAL_PATH;
}

/**
* Mutes all messages except those overriding
* (useful for debugging)
Expand All @@ -137,7 +197,7 @@ public static void setLogPath(String LOG_PATH) {
public static void setPrintMute(boolean mute) {
LogKitten.PRINT_MUTE = mute;
}

/**
* Like DriverStation.reportError, but without stack trace nor printing to System.err
* (updated for 2017 WPILib release)
Expand All @@ -152,34 +212,76 @@ private static void reportErrorToDriverStation(String details, String errorMessa
public static synchronized void logMessage(Object message, KittenLevel level, boolean override) {
message = message.toString(); // Not strictly needed, but good practice
if (LogKitten.logLevel.compareTo(level) >= 0) {
String content = LogKitten.timestamp() + " " + level.getName() + ": " + LogKitten.getLoggerMethodCallerMethodName()
String content = getRobotMode() + " " + LogKitten.timestamp() + " " + level.getName() + ": " + LogKitten.getLoggerMethodCallerMethodName()
+ ": " + message + " \n";
try {
if (LogKitten.fileOutput != null) {
LogKitten.fileOutput.write(content.getBytes());
if (LogKitten.globalOutput != null) {
LogKitten.globalOutput.write(content.getBytes());
} else {
System.out.println("Error logging: logfile not open");
System.out.println("Error logging: global logfile not open");
}
}
catch (IOException ioe) {
System.out.println("Error logging " + level.getName() + " message");
ioe.printStackTrace();
}
}
for(Map.Entry<Kitten, String> i : kittenList.entrySet()) {
String content = getRobotMode() + " " + LogKitten.timestamp() + " " + level.getName() + ": " + LogKitten.getLoggerMethodCallerMethodName()
+ ": " + message + " \n";
switch(i.getValue()) {
case "RobotModeKitten":
if(getRobotMode() == ((RobotModeKitten)i.getKey()).getMode()) {
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of duplicate code between "RobotModeKitten" and "CANKitten" cases. The code:

	try {
 		if(i.getKey().output != null) {
 			i.getKey().output.write(content.getBytes());
 		} else {
 			System.out.println("Error logging: " + i.getKey().category + " logfile not open");
		}
 	}
 	catch(IOException ioe) {
 		System.out.println("Error logging " + level.getName() + " message");
 		ioe.printStackTrace();
 	}

Could probably be reduced to a private method, or maybe a better flow could be worked out here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it might be better instead to move the logMessage method to the Kitten class itself, and have LogKitten extend Kitten or something of that sort. Looking at a screen is making me nauseous right now but I can take a closer look tomorrow hopefully.

if(i.getKey().output != null) {
i.getKey().output.write(content.getBytes());
} else {
System.out.println("Error logging: " + i.getKey().category + " logfile not open");
}
}
catch(IOException ioe) {
System.out.println("Error logging " + level.getName() + " message");
ioe.printStackTrace();
}
}
break;
case "CANKitten":
for(int j = 0; j < Thread.currentThread().getStackTrace().length; j++) {
if(Thread.currentThread().getStackTrace()[j].getClassName().contains("CANKitten")) {
try {
if(i.getKey().output != null) {
i.getKey().output.write(content.getBytes());
} else {
System.out.println("Error logging: " + i.getKey().category + " logfile not open");
}
}
catch(IOException ioe) {
System.out.println("Error logging " + level.getName() + " message");
ioe.printStackTrace();
}
}
}
break;
case "Kitten":
break;
default:
break;
}
}
if (!LogKitten.PRINT_MUTE || override) {
String printContent = level.getName() + ": " + LogKitten.getLoggerMethodCallerClassName() + "#"
String printContent = level.getName() + ": " + LogKitten.getRobotMode() + " " + LogKitten.getLoggerMethodCallerClassName() + "#"
+ LogKitten.getLoggerMethodCallerMethodName() + ": " + message + " \n";
if (LogKitten.printLevel.compareTo(level) >= 0) {
System.out.println(printContent);
}
if (LogKitten.dsLevel.compareTo(level) >= 0) {
LogKitten.reportErrorToDriverStation(
LogKitten.getLoggerMethodCallerClassName() + "#" + LogKitten.getLoggerMethodCallerMethodName(),
LogKitten.getRobotMode() + " " + LogKitten.getLoggerMethodCallerClassName() + "#" + LogKitten.getLoggerMethodCallerMethodName(),
level.getName() + ": " + message, level);
}
}
}

/**
* What a Terrible Failure: Report a condition that should never happen, allowing override
*
Expand Down Expand Up @@ -348,8 +450,8 @@ public static void ex(Exception ex) {
*/
public static synchronized void clean() {
try {
if (LogKitten.fileOutput != null) {
LogKitten.fileOutput.close();
if (LogKitten.globalOutput != null) {
LogKitten.globalOutput.close();
}
}
catch (IOException ioe) {
Expand Down
14 changes: 14 additions & 0 deletions RobotModeKitten.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.usfirst.frc4904.standard;

public class RobotModeKitten extends Kitten {
protected String mode;

public RobotModeKitten(String category, String mode) {
super(category);
this.mode = mode;
}

public String getMode() {
return this.mode;
}
}