mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-15 23:02:34 +02:00
* Server works if not connected to a tty. * Rich presence does not run IoC resolution at runtime anymore. * Work towards integration tests. Mostly work related to making it so the server and client can run in parallel, and allowing more control over main loop for testing. * Lots of code relating to integration tests.
96 lines
3.1 KiB
C#
96 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Robust.Shared.Log;
|
|
using Robust.Shared.Utility;
|
|
|
|
|
|
namespace Robust.Shared.Exceptions
|
|
{
|
|
internal sealed class RuntimeLog : IRuntimeLog
|
|
{
|
|
private readonly Dictionary<Type, List<LoggedException>> exceptions = new Dictionary<Type, List<LoggedException>>();
|
|
|
|
public int ExceptionCount => exceptions.Values.Sum(l => l.Count);
|
|
|
|
public void LogException(Exception exception, string catcher=null)
|
|
{
|
|
if (!exceptions.TryGetValue(exception.GetType(), out var list))
|
|
{
|
|
list = new List<LoggedException>();
|
|
exceptions[exception.GetType()] = list;
|
|
}
|
|
|
|
list.Add(new LoggedException(exception, DateTime.Now, catcher));
|
|
|
|
if (catcher != null)
|
|
{
|
|
Logger.ErrorS("runtime", "Caught exception in {0}: {1}", catcher, exception);
|
|
}
|
|
else
|
|
{
|
|
Logger.ErrorS("runtime", "Caught exception: {0}", exception);
|
|
}
|
|
}
|
|
|
|
public string Display()
|
|
{
|
|
var ret = new StringBuilder();
|
|
foreach (var (type, list) in exceptions)
|
|
{
|
|
ret.AppendLine($"{list.Count} exception {(exceptions[type].Count > 1 ? "s" : "")} {type}");
|
|
foreach (var logged in list)
|
|
{
|
|
var e = logged.Exception;
|
|
var t = logged.Time;
|
|
ret.AppendLine($"Exception in {e.TargetSite}, at {t.ToString(CultureInfo.InvariantCulture)}:");
|
|
ret.AppendLine($"Message: {e.Message}");
|
|
ret.AppendLine($"Catcher: {logged.Catcher}");
|
|
ret.AppendLine($"Stack trace: {e.StackTrace}");
|
|
if (e.Data.Count > 0)
|
|
{
|
|
ret.AppendLine("Additional data:");
|
|
foreach (var x in e.Data.Keys)
|
|
{
|
|
ret.AppendLine($"{x}: {e.Data[x]}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret.ToString();
|
|
}
|
|
|
|
private class LoggedException
|
|
{
|
|
public Exception Exception { get; }
|
|
public DateTime Time { get; }
|
|
public string Catcher { get; }
|
|
|
|
public LoggedException(Exception exception, DateTime time, string catcher)
|
|
{
|
|
Exception = exception;
|
|
Time = time;
|
|
Catcher = catcher;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The runtime log is responsible for the logging of exceptions, to prevent the game crashing entirely.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The term "runtime" dates back to BYOND, in which an exception is called a "runtime error".
|
|
/// As such, what we call exceptions is called a "runtime" in BYOND.
|
|
/// </remarks>
|
|
public interface IRuntimeLog
|
|
{
|
|
int ExceptionCount { get; }
|
|
|
|
void LogException(Exception exception, string catcher=null);
|
|
|
|
string Display();
|
|
}
|
|
}
|