164 lines
5.9 KiB
C#
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
|
|
}
|
|
}
|
|
}
|