mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-28 02:11:43 +00:00
[epilogue] Add an annotation-based logging framework for Java programs (#6584)
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.epilogue.logging;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import edu.wpi.first.epilogue.Logged;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ClassSpecificLoggerTest {
|
||||
@Logged
|
||||
record Point2d(double x, double y, int dim) {
|
||||
static class Logger extends ClassSpecificLogger<Point2d> {
|
||||
Logger() {
|
||||
super(Point2d.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update(DataLogger dataLogger, Point2d object) {
|
||||
dataLogger.log("x", object.x);
|
||||
dataLogger.log("y", object.y);
|
||||
dataLogger.log("dim", object.dim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReadPrivate() {
|
||||
var point = new Point2d(1, 4, 2);
|
||||
var logger = new Point2d.Logger();
|
||||
var dataLog = new TestLogger();
|
||||
logger.update(dataLog.getSubLogger("Point"), point);
|
||||
|
||||
assertEquals(
|
||||
List.of(
|
||||
new TestLogger.LogEntry<>("Point/x", 1.0),
|
||||
new TestLogger.LogEntry<>("Point/y", 4.0),
|
||||
new TestLogger.LogEntry<>("Point/dim", 2)),
|
||||
dataLog.getEntries());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.epilogue.logging;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LazyLoggerTest {
|
||||
@Test
|
||||
void lazyOfLazyReturnsSelf() {
|
||||
var lazy = new LazyLogger(new NullLogger());
|
||||
assertSame(lazy, lazy.lazy());
|
||||
}
|
||||
|
||||
@Test
|
||||
void lazyInt() {
|
||||
var logger = new TestLogger();
|
||||
var lazy = new LazyLogger(logger);
|
||||
|
||||
{
|
||||
// First time logging to "int" should go through
|
||||
lazy.log("int", 0);
|
||||
assertEquals(List.of(new TestLogger.LogEntry<>("int", 0)), logger.getEntries());
|
||||
}
|
||||
|
||||
{
|
||||
// Logging the current value shouldn't go through
|
||||
lazy.log("int", 0);
|
||||
assertEquals(List.of(new TestLogger.LogEntry<>("int", 0)), logger.getEntries());
|
||||
}
|
||||
|
||||
{
|
||||
// Logging a new value should go through
|
||||
lazy.log("int", 1);
|
||||
assertEquals(
|
||||
List.of(new TestLogger.LogEntry<>("int", 0), new TestLogger.LogEntry<>("int", 1)),
|
||||
logger.getEntries());
|
||||
}
|
||||
|
||||
{
|
||||
// Logging a previous value should go through
|
||||
lazy.log("int", 0);
|
||||
assertEquals(
|
||||
List.of(
|
||||
new TestLogger.LogEntry<>("int", 0),
|
||||
new TestLogger.LogEntry<>("int", 1),
|
||||
new TestLogger.LogEntry<>("int", 0)),
|
||||
logger.getEntries());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.epilogue.logging;
|
||||
|
||||
import edu.wpi.first.util.struct.Struct;
|
||||
import edu.wpi.first.util.struct.StructBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("PMD.TestClassWithoutTestCases") // This is not a test class!
|
||||
public class TestLogger implements DataLogger {
|
||||
public record LogEntry<T>(String identifier, T value) {}
|
||||
|
||||
private final Map<String, SubLogger> m_subLoggers = new HashMap<>();
|
||||
|
||||
private final List<LogEntry<?>> m_entries = new ArrayList<>();
|
||||
|
||||
public List<LogEntry<?>> getEntries() {
|
||||
return m_entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLogger getSubLogger(String path) {
|
||||
return m_subLoggers.computeIfAbsent(path, k -> new SubLogger(k, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, int value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, long value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, float value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, double value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, boolean value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, byte[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, int[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, long[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, float[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, double[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, boolean[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, String value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String identifier, String[] value) {
|
||||
m_entries.add(new LogEntry<>(identifier, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> void log(String identifier, S value, Struct<S> struct) {
|
||||
var serialized = StructBuffer.create(struct).write(value).array();
|
||||
|
||||
m_entries.add(new LogEntry<>(identifier, serialized));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> void log(String identifier, S[] value, Struct<S> struct) {
|
||||
var serialized = StructBuffer.create(struct).writeArray(value).array();
|
||||
|
||||
m_entries.add(new LogEntry<>(identifier, serialized));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user