Skip to content

Commit

Permalink
[wpiutil, wpilib] Add FileLogger and integrate with DLM
Browse files Browse the repository at this point in the history
  • Loading branch information
Gold856 committed Aug 17, 2024
1 parent 780b1e0 commit 5be7132
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 0 deletions.
33 changes: 33 additions & 0 deletions ntcoreffi/src/main/native/cpp/DataLogManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <fmt/format.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/DataLogBackgroundWriter.h>
#include <wpi/FileLogger.h>
#include <wpi/SafeThread.h>
#include <wpi/StringExtras.h>
#include <wpi/fs.h>
Expand Down Expand Up @@ -191,13 +192,17 @@ struct Thread final : public wpi::SafeThread {

void StartNTLog();
void StopNTLog();
void StartConsoleLog();
void StopConsoleLog();

std::string m_logDir;
bool m_filenameOverride;
wpi::log::DataLogBackgroundWriter m_log;
bool m_ntLoggerEnabled = false;
NT_DataLogger m_ntEntryLogger = 0;
NT_ConnectionDataLogger m_ntConnLogger = 0;
bool m_consoleLoggerEnabled = false;
wpi::FileLogger m_consoleLogger;
wpi::log::StringLogEntry m_messageLog;
};

Expand Down Expand Up @@ -452,6 +457,20 @@ void Thread::StopNTLog() {
}
}

void Thread::StartConsoleLog() {
if (!m_consoleLoggerEnabled) {
m_consoleLoggerEnabled = true;
m_consoleLogger = {"FRC_UserProgram.log", m_log, "output"};
}
}

void Thread::StopConsoleLog() {
if (m_consoleLoggerEnabled) {
m_consoleLoggerEnabled = false;
m_consoleLogger = {};
}
}

Instance::Instance(std::string_view dir, std::string_view filename,
double period) {
// Delete all previously existing FRC_TBD_*.wpilog files. These only exist
Expand Down Expand Up @@ -516,6 +535,16 @@ void DataLogManager::LogNetworkTables(bool enabled) {
}
}

void DataLogManager::LogConsoleOutput(bool enabled) {
if (auto thr = GetInstance().owner.GetThread()) {
if (enabled) {
thr->StartConsoleLog();
} else if (!enabled) {
thr->StopConsoleLog();
}
}
}

void DataLogManager::SignalNewDSDataOccur() {
wpi::SetSignalObject(DriverStation::gNewDataEvent);
}
Expand Down Expand Up @@ -546,6 +575,10 @@ void DLM_LogNetworkTables(int enabled) {
DataLogManager::LogNetworkTables(enabled);
}

void DLM_LogConsoleOutput(int enabled) {
DataLogManager::LogConsoleOutput(enabled);
}

void DLM_SignalNewDSDataOccur(void) {
DataLogManager::SignalNewDSDataOccur();
}
Expand Down
12 changes: 12 additions & 0 deletions ntcoreffi/src/main/native/include/DataLogManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ class DataLogManager final {
*/
static void LogNetworkTables(bool enabled);

/**
* Enable or disable logging of the console output. Defaults to enabled.
* @param enabled true to enable, false to disable
*/
static void LogConsoleOutput(bool enabled);
/**
* Signal new DS data is available.
*/
Expand Down Expand Up @@ -152,6 +157,13 @@ const char* DLM_GetLogDir(void);
*/
void DLM_LogNetworkTables(int enabled);


/**
* Enable or disable logging of the console output. Defaults to enabled.
* @param enabled true to enable, false to disable
*/
void DLM_LogConsoleOutput(int enabled);

/**
* Signal new DS data is available.
*/
Expand Down
1 change: 1 addition & 0 deletions ntcoreffi/src/main/native/symbols.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
DLM_GetLog
DLM_GetLogDir
DLM_Log
DLM_LogConsoleOutput
DLM_LogNetworkTables
DLM_SignalNewDSDataOccur
DLM_Start
Expand Down
31 changes: 31 additions & 0 deletions wpilibc/src/main/native/cpp/DataLogManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <fmt/chrono.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/DataLog.h>
#include <wpi/FileLogger.h>
#include <wpi/DataLogBackgroundWriter.h>
#include <wpi/SafeThread.h>
#include <wpi/StringExtras.h>
Expand All @@ -37,13 +38,17 @@ struct Thread final : public wpi::SafeThread {

void StartNTLog();
void StopNTLog();
void StartConsoleLog();
void StopConsoleLog();

std::string m_logDir;
bool m_filenameOverride;
wpi::log::DataLogBackgroundWriter m_log;
bool m_ntLoggerEnabled = false;
NT_DataLogger m_ntEntryLogger = 0;
NT_ConnectionDataLogger m_ntConnLogger = 0;
bool m_consoleLoggerEnabled = false;
wpi::FileLogger m_consoleLogger;
wpi::log::StringLogEntry m_messageLog;
};

Expand Down Expand Up @@ -109,10 +114,12 @@ Thread::Thread(std::string_view dir, std::string_view filename, double period)
m_log{dir, MakeLogFilename(filename), period},
m_messageLog{m_log, "messages"} {
StartNTLog();
StartConsoleLog();
}

Thread::~Thread() {
StopNTLog();
StopConsoleLog();
}

void Thread::Main() {
Expand Down Expand Up @@ -297,6 +304,20 @@ void Thread::StopNTLog() {
}
}

void Thread::StartConsoleLog() {
if (!m_consoleLoggerEnabled) {
m_consoleLoggerEnabled = true;
m_consoleLogger = {"FRC_UserProgram.log", m_log, "output"};
}
}

void Thread::StopConsoleLog() {
if (m_consoleLoggerEnabled) {
m_consoleLoggerEnabled = false;
m_consoleLogger = {};
}
}

Instance::Instance(std::string_view dir, std::string_view filename,
double period) {
// Delete all previously existing FRC_TBD_*.wpilog files. These only exist
Expand Down Expand Up @@ -360,3 +381,13 @@ void DataLogManager::LogNetworkTables(bool enabled) {
}
}
}

void DataLogManager::LogConsoleOutput(bool enabled) {
if (auto thr = GetInstance().owner.GetThread()) {
if (enabled) {
thr->StartConsoleLog();
} else if (!enabled) {
thr->StopConsoleLog();
}
}
}
7 changes: 7 additions & 0 deletions wpilibc/src/main/native/include/frc/DataLogManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ class DataLogManager final {
* @param enabled true to enable, false to disable
*/
static void LogNetworkTables(bool enabled);


/**
* Enable or disable logging of the console output. Defaults to enabled.
* @param enabled true to enable, false to disable
*/
static void LogConsoleOutput(bool enabled);
};

} // namespace frc
33 changes: 33 additions & 0 deletions wpilibj/src/main/java/edu/wpi/first/wpilibj/DataLogManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package edu.wpi.first.wpilibj;

import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.util.FileLogger;
import edu.wpi.first.util.WPIUtilJNI;
import edu.wpi.first.util.concurrent.Event;
import edu.wpi.first.util.datalog.DataLog;
Expand Down Expand Up @@ -52,6 +53,8 @@ public final class DataLogManager {
private static boolean m_ntLoggerEnabled = true;
private static int m_ntEntryLogger;
private static int m_ntConnLogger;
private static boolean m_consoleLoggerEnabled = true;
private static FileLogger m_consoleLogger;
private static StringLogEntry m_messageLog;

// if less than this much free space, delete log files until there is this much free space
Expand Down Expand Up @@ -121,6 +124,10 @@ public static synchronized void start(String dir, String filename, double period
if (m_ntLoggerEnabled) {
startNtLog();
}
// Log console output
if (m_consoleLoggerEnabled) {
startConsoleLog();
}
} else if (m_stopped) {
m_log.setFilename(makeLogFilename(filename));
m_log.resume();
Expand Down Expand Up @@ -205,6 +212,24 @@ public static synchronized void logNetworkTables(boolean enabled) {
}
}

/**
* Enable or disable logging of the console output. Defaults to enabled.
* @param enabled true to enable, false to disable
*/
public static synchronized void logConsoleOutput(boolean enabled) {
boolean wasEnabled = m_consoleLoggerEnabled;
m_consoleLoggerEnabled = enabled;
if (m_log == null) {
start();
return;
}
if (enabled && !wasEnabled) {
startConsoleLog();
} else if (!enabled && wasEnabled) {
stopConsoleLog();
}
}

private static String makeLogDir(String dir) {
if (!dir.isEmpty()) {
return dir;
Expand Down Expand Up @@ -266,6 +291,14 @@ private static void stopNtLog() {
NetworkTableInstance.stopConnectionDataLog(m_ntConnLogger);
}

private static void startConsoleLog() {
m_consoleLogger = new FileLogger("FRC_UserProgram.log", m_log, "console");
}

private static void stopConsoleLog() {
m_consoleLogger.close();
}

private static void logMain() {
// based on free disk space, scan for "old" FRC_*.wpilog files and remove
{
Expand Down
27 changes: 27 additions & 0 deletions wpiutil/src/main/java/edu/wpi/first/util/FileLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package edu.wpi.first.util;

import edu.wpi.first.util.datalog.DataLog;

/**
* A class version of `tail -f`, otherwise known as `tail -f` at home. Watches a file and puts the data into a data log. Only works on Linux-based platforms.
*/
public class FileLogger implements AutoCloseable {
private long m_impl;

/**
* Construct a FileLogger. When the specified file is modified, appended data will be
* appended to the specified data log.
*
* @param file The path to the file.
* @param log A data log.
* @param key The log key to append data to.
*/
public FileLogger(String file, DataLog log, String key) {
m_impl = WPIUtilJNI.createFileLogger(file, log, key);
}

@Override
public void close() {
WPIUtilJNI.freeFileLogger(m_impl);
}
}
19 changes: 19 additions & 0 deletions wpiutil/src/main/java/edu/wpi/first/util/WPIUtilJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;

import edu.wpi.first.util.datalog.DataLog;

/** WPIUtil JNI. */
public class WPIUtilJNI {
static boolean libraryLoaded = false;
Expand Down Expand Up @@ -217,6 +219,23 @@ public static native boolean waitForObjectTimeout(int handle, double timeout)
public static native int[] waitForObjectsTimeout(int[] handles, double timeout)
throws InterruptedException;

/**
* Create a native FileLogger. When the specified file is modified, appended data will be
* appended to the specified data log.
*
* @param file The path to the file.
* @param log A data log.
* @param key The log key to append data to.
*/
public static native long createFileLogger(String file, DataLog log, String key);

/**
* Free a native FileLogger. This causes the FileLogger to stop appending data to the log.
*
* @param fileTail The FileLogger handle.
*/
public static native void freeFileLogger(long fileTail);

/** Utility class. */
protected WPIUtilJNI() {}
}
34 changes: 34 additions & 0 deletions wpiutil/src/main/native/cpp/FileLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

#include "wpi/FileLogger.h"

namespace wpi {
FileLogger::FileLogger(std::string_view file,
std::function<void(std::string_view)> callback)
#ifdef __linux__
: m_fileHandle{open(file.data(), O_RDONLY)},
m_inotifyHandle{inotify_init()},
m_inotifyWatchHandle{
inotify_add_watch(m_inotifyHandle, file.data(), IN_MODIFY)},
m_thread{[=, this] {
char buf[4000];
struct inotify_event ev;
int len = 0;
while ((len = read(m_inotifyHandle, &ev, sizeof(ev))) > 0) {
int buf_len = read(m_fileHandle, buf, sizeof(buf));
callback(std::string_view{buf, buf_len});
}
}}
#endif
{}
FileLogger::~FileLogger() {
#ifdef __linux__
inotify_rm_watch(m_inotifyHandle, m_inotifyWatchHandle);
close(m_inotifyHandle);
close(m_fileHandle);
m_thread.join();
#endif
}
} // namespace wpi
Loading

0 comments on commit 5be7132

Please sign in to comment.