Skip to content

Commit

Permalink
Finish up the runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Aug 5, 2024
1 parent 680ca40 commit e5623ab
Show file tree
Hide file tree
Showing 39 changed files with 1,525 additions and 155 deletions.
7 changes: 7 additions & 0 deletions WPILib.sln
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "newcommands", "src\newcomma
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epilogue", "src\epilogue\epilogue.csproj", "{B8A9AFC6-01F1-44AC-95D4-0683EF31E117}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epilogue.test", "test\epilogue.test\epilogue.test.csproj", "{A658C098-9968-4F4A-9230-C91B40FF7541}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -134,6 +136,10 @@ Global
{B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Release|Any CPU.Build.0 = Release|Any CPU
{A658C098-9968-4F4A-9230-C91B40FF7541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A658C098-9968-4F4A-9230-C91B40FF7541}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A658C098-9968-4F4A-9230-C91B40FF7541}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A658C098-9968-4F4A-9230-C91B40FF7541}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8F38C25E-641E-47FC-AC0A-0717F2159E8F} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF}
Expand All @@ -154,5 +160,6 @@ Global
{A364B855-95A2-435D-A627-A25F1215AB4E} = {1CA9AB3B-4828-4F07-8C0E-88EF7C5A9ACD}
{B09918CC-E71F-4E49-AA20-81559D3583B2} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF}
{B8A9AFC6-01F1-44AC-95D4-0683EF31E117} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF}
{A658C098-9968-4F4A-9230-C91B40FF7541} = {AD95ECD8-E708-4FB4-9B7E-A8A8EF3FCB3E}
EndGlobalSection
EndGlobal
5 changes: 3 additions & 2 deletions src/epilogue/CustomLoggingForAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Epilogue;

[AttributeUsage(AttributeTargets.Class)]
public sealed class CustomLoggerForAttribute : Attribute {
public sealed class CustomLoggerForAttribute : Attribute
{
Type[] Types { get; init; } = [];
}
}
11 changes: 7 additions & 4 deletions src/epilogue/EpilogueConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using Epilogue.Logging;
using Epilogue.Logging.Errors;
using NetworkTables;

namespace Epilogue;

public class EpilogueConfiguration {
public DataLogger DataLogger { get; set; } = new NTDataLogger(NetworkTableInstance.Default);
public class EpilogueConfiguration
{
public IDataLogger DataLogger { get; set; } = new NTDataLogger(NetworkTableInstance.Default);
public LogImportance MinimumImportance { get; set; } = LogImportance.Debug;
public ErrorHandler ErrorHandler { get; set; } = new();
public IErrorHandler ErrorHandler { get; set; } = new ErrorPrinter();
public string Root { get; set; } = "Robot";
}
}
5 changes: 3 additions & 2 deletions src/epilogue/LogImportance.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace Epilogue;

public enum LogImportance {
public enum LogImportance
{
Debug,
Info,
Critical,
}
}
5 changes: 3 additions & 2 deletions src/epilogue/LogStrategy.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Epilogue;

public enum LogStrategy {
public enum LogStrategy
{
OptIn,
OptOut,
}
}
2 changes: 1 addition & 1 deletion src/epilogue/LoggedAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ public sealed class LoggedAttribute : Attribute
public string Name { get; init; } = "";
public LogStrategy Strategy { get; init; } = LogStrategy.OptOut;
public LogImportance Importance { get; init; } = LogImportance.Debug;
}
}
50 changes: 35 additions & 15 deletions src/epilogue/Logging/ClassSpecificLogger.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,71 @@
using System.Runtime.InteropServices;
using Epilogue.Logging.Errors;
using WPIUtil.Sendable;

namespace Epilogue.Logging;

public abstract class ClassSpecificLogger {
public abstract class ClassSpecificLogger
{
private readonly Dictionary<ISendable, ISendableBuilder> m_sendables = [];

protected ClassSpecificLogger(Type loggedType) {
protected ClassSpecificLogger(Type loggedType)
{
LoggedType = loggedType;
}

public bool Disabled { get; private set; }

public void Disable() {
public void Disable()
{
Disabled = true;
}

public void Reenable() {
public void Reenable()
{
Disabled = false;
}

public Type LoggedType { get; }

protected virtual void LogSendable(DataLogger dataLogger, ISendable? sendable) {
if (sendable == null) {
protected virtual void LogSendable(IDataLogger dataLogger, ISendable? sendable)
{
if (sendable is null)
{
return;
}

var builder = m_sendables.
}
ref ISendableBuilder? builder = ref CollectionsMarshal.GetValueRefOrAddDefault(m_sendables, sendable, out var _);
if (builder is null)
{
builder = new LogBackedSenabledBuilder(dataLogger);
sendable.InitSendable(builder);
}
builder.Update();
}
}

public abstract class ClassSpecificLogger<T> : ClassSpecificLogger {
public abstract class ClassSpecificLogger<T> : ClassSpecificLogger
{
protected ClassSpecificLogger() : base(typeof(T))
{
}

protected abstract void Update(DataLogger dataLogger, T obj);
protected abstract void Update(IDataLogger dataLogger, T obj);

public void TryUpdate(DataLogger dataLogger, T obj, ErrorHandler errorHandler) {
if (Disabled) {
public void TryUpdate(IDataLogger dataLogger, T obj, IErrorHandler errorHandler)
{
if (Disabled)
{
return;
}

try {
try
{
Update(dataLogger, obj);
} catch (Exception e) {
errorHandler(e, this);
}
catch (Exception e)
{
errorHandler.Handle(e, this);
}
}
}
9 changes: 0 additions & 9 deletions src/epilogue/Logging/DataLogger.cs

This file was deleted.

12 changes: 12 additions & 0 deletions src/epilogue/Logging/Errors/CrashOnError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

namespace Epilogue.Logging.Errors;

public class CrashOnError : IErrorHandler
{
public void Handle(Exception exception, ClassSpecificLogger logger)
{
#pragma warning disable CA2201 // Do not raise reserved exception types
throw new Exception($"[EPILOGUE] An error occured while logging an instance of {logger.LoggedType.Name}", exception);
#pragma warning restore CA2201 // Do not raise reserved exception types
}
}
10 changes: 10 additions & 0 deletions src/epilogue/Logging/Errors/ErrorPrinter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

namespace Epilogue.Logging.Errors;

public class ErrorPrinter : IErrorHandler
{
public void Handle(Exception exception, ClassSpecificLogger logger)
{
Console.Error.WriteLine($"[EPILOGUE] An error occured while logging an instance of {logger.LoggedType.Name}: {exception.Message}");
}
}
5 changes: 3 additions & 2 deletions src/epilogue/Logging/Errors/IErrorHandler.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
namespace Epilogue.Logging.Errors;

public interface IErrorHandler {
public interface IErrorHandler
{
void Handle(Exception exception, ClassSpecificLogger logger);

public static IErrorHandler CrashOnError() => new CrashOnError();

public static IErrorHandler PrintErrorMessages() => new ErrorPrint();
public static IErrorHandler PrintErrorMessages() => new ErrorPrinter();

public static LoggerDisabler Disabling(int maximumPermissableErrors) => LoggerDisabler.ForLimit(maximumPermissableErrors);
}
29 changes: 25 additions & 4 deletions src/epilogue/Logging/Errors/LoggerDisabler.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@

using System.Runtime.InteropServices;

namespace Epilogue.Logging.Errors;

public class LoggerDisabler : IErrorHandler {
public class LoggerDisabler : IErrorHandler
{
private readonly int m_threshold;
private readonly Dictionary<ClassSpecificLogger, int> m_errorCounts = [];

public LoggerDisabler(int threshold) {
public LoggerDisabler(int threshold)
{
m_threshold = threshold;
}

public static LoggerDisabler ForLimit(int threshold) => new LoggerDisabler(threshold);
public static LoggerDisabler ForLimit(int threshold) => new(threshold);

public void Handle(Exception exception, ClassSpecificLogger logger)
{
throw new NotImplementedException();
int errorCount = ++CollectionsMarshal.GetValueRefOrAddDefault(m_errorCounts, logger, out var _);

if (errorCount > m_threshold)
{
logger.Disable();
Console.Error.WriteLine($"[EPILOGUE] Too many errors detected in {logger.GetType().Name} (maximum allowed: {m_threshold}). The most recent error follows:");
Console.Error.WriteLine(exception.Message);
Console.Error.WriteLine(exception.StackTrace);
}
}

public void Reset()
{
foreach (var logger in m_errorCounts)
{
logger.Key.Reenable();
}
m_errorCounts.Clear();
}
}
128 changes: 128 additions & 0 deletions src/epilogue/Logging/FileLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System.Runtime.InteropServices;
using WPIUtil.Logging;
using WPIUtil.Serialization.Struct;
using static WPIUtil.WpiGuard;

namespace Epilogue.Logging;

public class FileLogger : IDataLogger
{
private readonly DataLog m_dataLog;
private readonly Dictionary<string, DataLogEntry> m_entries = [];
private readonly Dictionary<string, SubLogger> m_subLoggers = [];

public FileLogger(DataLog dataLog)
{
m_dataLog = RequireNotNull(dataLog);
}

public IDataLogger Lazy => new LazyLogger(this);
public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers);

private E GetEntry<E>(string identifier, Func<DataLog, string, E> ctor) where E : DataLogEntry
{
ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(m_entries, identifier, out var _);
entry ??= ctor(m_dataLog, identifier);
return (E)entry;
}

public void Log(string identifier, bool value)
{
GetEntry(identifier, static (a, b) => new BooleanLogEntry(a, b)).Append(value);
}

public void Log(string identifier, int value)
{
GetEntry(identifier, static (a, b) => new IntegerLogEntry(a, b)).Append(value);
}

public void Log(string identifier, long value)
{
GetEntry(identifier, static (a, b) => new IntegerLogEntry(a, b)).Append(value);
}

public void Log(string identifier, float value)
{
GetEntry(identifier, static (a, b) => new FloatLogEntry(a, b)).Append(value);
}

public void Log(string identifier, double value)
{
GetEntry(identifier, static (a, b) => new DoubleLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<byte> value)
{
GetEntry(identifier, static (a, b) => new RawLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<bool> value)
{
GetEntry(identifier, static (a, b) => new BooleanArrayLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<int> value)
{
long[] widended = new long[value.Length];
for (int i = 0; i < value.Length; i++)
{
widended[i] = value[i];
}
GetEntry(identifier, static (a, b) => new IntegerArrayLogEntry(a, b)).Append(widended);
}

public void Log(string identifier, ReadOnlySpan<long> value)
{
GetEntry(identifier, static (a, b) => new IntegerArrayLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<float> value)
{
GetEntry(identifier, static (a, b) => new FloatArrayLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<double> value)
{
GetEntry(identifier, static (a, b) => new DoubleArrayLogEntry(a, b)).Append(value);
}

public void Log(string identifier, string value)
{
GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<char> value)
{
GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value);
}

public void Log(string identifier, ReadOnlySpan<string> value)
{
GetEntry(identifier, static (a, b) => new StringArrayLogEntry(a, b)).Append(value);
}

public void Log<T>(string identifier, in T value) where T : IStructSerializable<T>
{
GetEntry(identifier, static (a, b) => new StructLogEntry<T>(a, b)).Append(value);
}

public void Log<T>(string identifier, T[] value) where T : IStructSerializable<T>
{
GetEntry(identifier, static (a, b) => new StructArrayLogEntry<T>(a, b)).Append(value);
}

public void Log<T>(string identifier, Span<T> value) where T : IStructSerializable<T>
{
GetEntry(identifier, static (a, b) => new StructArrayLogEntry<T>(a, b)).Append(value);
}

public void Log<T>(string identifier, ReadOnlySpan<T> value) where T : IStructSerializable<T>
{
GetEntry(identifier, static (a, b) => new StructArrayLogEntry<T>(a, b)).Append(value);
}

public void Log<T>(string identifier, T value) where T : Enum
{
GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value.ToString());
}
}
Loading

0 comments on commit e5623ab

Please sign in to comment.