Files
spark/src/client/spark_api/utils/Log.cs
T
2020-07-11 12:30:06 -04:00

164 lines
5.9 KiB
C#

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace bts {
enum Level {
NoLog,
Diag,
Info,
Warn,
Error,
Fatal,
Sys
}
enum Subsystem {
gen,
Config,
QBus,
Log,
Jetfix,
md,
Api,
Persist,
User,
OrderMan,
Assert,
Engine,
Ui,
ExSim,
Mercury,
Testing,
Latency,
DataFlow,
Plugin,
Sdk,
Http,
Spartan,
iLink3
// Please keep this list in sync with logging.h/logging.cpp
}
public readonly struct Logger {
readonly Subsystem _sys;
internal Logger(Subsystem sys) {
_sys = sys;
}
public void diag(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
Logger_log(Level.Diag, _sys, message, file, line);
}
public void info(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
Logger_log(Level.Info, _sys, message, file, line);
}
public void warn(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
Logger_log(Level.Warn, _sys, message, file, line);
}
public void error(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
Logger_log(Level.Error, _sys, message, file, line);
}
public void fatal(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
Logger_log(Level.Fatal, _sys, message, file, line);
}
[DllImport("libspark")]
static extern void Logger_log (Level level, Subsystem subsystem, string message, string file, int line);
}
public readonly struct LoggerContext {
readonly string _prefix, _suffix;
readonly Logger _logger;
public LoggerContext(Logger logger, string prefix, string suffix) {
_prefix = prefix;
_suffix = suffix;
_logger = logger;
}
public void diag(string message) => _logger.diag(_fmt(message));
public void info(string message) => _logger.info(_fmt(message));
public void warn(string message) => _logger.warn(_fmt(message));
public void error(string message) => _logger.error(_fmt(message));
public void fatal(string message) => _logger.fatal(_fmt(message));
string _fmt(string message) {
if (_prefix != null)
message = _prefix + message;
if (_suffix != null)
message += _suffix;
return message;
}
}
public static class Log {
internal static Logger Gen => new Logger(Subsystem.gen);
internal static Logger Config => new Logger(Subsystem.Config);
internal static Logger QBus => new Logger(Subsystem.QBus);
internal static Logger Md => new Logger(Subsystem.md);
internal static Logger Api => new Logger(Subsystem.Api);
internal static Logger Persist => new Logger(Subsystem.Persist);
internal static Logger User => new Logger(Subsystem.User);
internal static Logger OrderMan => new Logger(Subsystem.OrderMan);
internal static Logger Assert => new Logger(Subsystem.Assert);
internal static Logger Ui => new Logger(Subsystem.Ui);
internal static Logger Testing => new Logger(Subsystem.Testing);
internal static Logger DataFlow => new Logger(Subsystem.DataFlow);
public static Logger Sdk => new Logger(Subsystem.Sdk);
public static Logger Http => new Logger(Subsystem.Http);
internal static void log_at(this Logger logger, Level level, string message) {
switch (level) {
case Level.Diag: logger.diag(message); break;
case Level.Warn: logger.warn(message); break;
case Level.Error: logger.error(message); break;
case Level.Fatal: logger.fatal(message); break;
default: logger.info(message); break;
}
}
[Conditional("DEBUG")]
public static void assert_d(bool test, string message = "", [CallerFilePath] string file = "assert", [CallerLineNumber] int line = 0) {
assert(test, message, file, line);
}
public static void assert(bool test, string message = "", [CallerFilePath] string file = "assert", [CallerLineNumber] int line = 0) {
if (!test) {
Assert.fatal(message, file, line);
Debug.Assert(test, message);
if (Debugger.IsAttached) {
Debugger.Break();
}
system_is_crashing($"Fatal Assert: {message} at {file}:{line}", new StackTrace());
Environment.Exit(-1);
}
}
public static void notnull<T>(T o) where T : class {
assert(o != null);
}
public static void isnull<T>(T o) where T : class {
assert(o == null);
}
delegate void on_crash_callback([MarshalAs(UnmanagedType.LPStr)]string msg, [MarshalAs(UnmanagedType.LPStr)] string details);
internal static void system_is_crashing(string message, object details) {
OnSystemCrashing?.Invoke(message, details);
}
internal static event Action<string, object> OnSystemCrashing;
public static void debug_assert(this Logger logger, bool test, string message = "", [CallerFilePath] string file = "debug_assert", [CallerLineNumber] int line = 0) {
if (!test)
logger.debug_fatal(message, file, line);
}
/// Calls <see cref="Logger.fatal(string, string, int)"/> if DEBUG, otherwise <see cref="Logger.warn(string, string, int)"/>.
public static void debug_fatal(this Logger logger, string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) {
#if DEBUG
logger.fatal(message, file, line);
#else
logger.warn(message, file, line);
#endif
}
}
}