Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 31 additions & 26 deletions src/DiIiS-NA/Core/Logging/AnsiTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class AnsiTarget : LogTarget
private readonly Table _table;
private static CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource();
private static bool _shutdown = true;

public AnsiTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTimeStamps, string timeStampFormat)
{
_shutdown = false;
Expand Down Expand Up @@ -44,7 +44,7 @@ public AnsiTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTime
{
currentConsoleSize = Console.WindowHeight * Console.WindowWidth;
}
catch {}
catch { }
if (lastCount != _table.Rows.Count || consoleSize != currentConsoleSize)
{
lastCount = _table.Rows.Count;
Expand All @@ -57,11 +57,11 @@ public AnsiTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTime
_shutdown = true;
});
}

public static void StopIfRunning(bool clear = false)
{
CancellationTokenSource.Cancel();
while(!_shutdown)
while (!_shutdown)
Thread.Sleep(100);
Thread.Sleep(1000);
if (clear)
Expand All @@ -70,7 +70,7 @@ public static void StopIfRunning(bool clear = false)
AnsiConsole.Cursor.SetPosition(0, 0);
}
}

/// <summary>
/// Logging keywords to beautify the output.
/// It's ugly, I know.
Expand All @@ -93,40 +93,37 @@ public static string Beautify(string text)
.Replace("Blizzless", $"[{blizz}]Blizz[/][{less}]less[/]", StringComparison.CurrentCultureIgnoreCase)
.Replace("Diablo III", $"[{diablo}]Diablo[/] [{d3}]III[/]", StringComparison.CurrentCultureIgnoreCase)
.Replace(@"D3\.", $"[{diablo}]D[/][{d3}]3[/]", StringComparison.CurrentCultureIgnoreCase) //D3.*

.Replace("SQL", $"[{sql}]SQL[/]")
.Replace("Discord", $"[{discord}]Discord[/]", StringComparison.CurrentCultureIgnoreCase)

.Replace("null", $"[{unkNull}]null[/]", StringComparison.CurrentCultureIgnoreCase)
.Replace($"not [{unkNull}]null[/]", $"[{notNull}]is not null[/]", StringComparison.CurrentCultureIgnoreCase)
.Replace($"is [{unkNull}]null[/]", $"[{@null}]is null[/]", StringComparison.CurrentCultureIgnoreCase);
}

private static Dictionary<string, string> _replacements = new ()

private static Dictionary<string, string> _replacements = new()
{
["["] = "[[",
["]"] = "]]",
["$[[/]]$"] = "[/]",
["$[["] = "[",
["]]$"] = "]"
};

/// <summary>
/// Performs a cleanup on the target.
/// All [ becomes [[, and ] becomes ]] (for ignoring ANSI codes)
/// To use a style, use $[..]$abc$[/]$.
/// Example:
/// Logger.Warn("This is a $[red]$red$[/]$ message");
/// instead of
/// Logger.Warn("This is a [red]red[/] message");
/// Returns a markup-escaped string so Spectre.Console will never throw.
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
public static string Cleanup(string input)
{
if (string.IsNullOrEmpty(input)) return "";
return Beautify(_replacements.Aggregate(input, (current, replacement) => current.Replace(replacement.Key, replacement.Value)));

var beautified = Beautify(input);

var replaced = _replacements.Aggregate(beautified, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
return Markup.Escape(replaced);
}
public override void LogMessage(Logger.Level level, string logger, string message)
{
Expand Down Expand Up @@ -161,15 +158,23 @@ private void AddRow(Logger.Level level, string logger, string message, string ex
{
Style messageStyle = GetStyleByLevel(level);
Style exStyle = exFormat ? new Style(foreground: Color.Red3_1) : new Style(foreground: Color.Green3_1);
var colTimestamp = new Markup(DateTime.Now.ToString(TimeStampFormat), messageStyle).Centered();
var colLevel = new Markup(level.ToString(), messageStyle).RightJustified();
var colMessage = new Markup(Cleanup(message), messageStyle).Centered();
var colLogger = new Markup(logger, new Style(messageStyle.Foreground, messageStyle.Background, messageStyle.Decoration
#if DEBUG

// Экранируем содержимое, чтобы Spectre.Console не упал из‑за незакрытых скобок
var safeTime = Markup.Escape(DateTime.Now.ToString(TimeStampFormat));
var safeLevel = Markup.Escape(level.ToString());
var safeMessage = Markup.Escape(Cleanup(message) ?? "");
var safeLogger = Markup.Escape(logger ?? "");
var safeExMessage = Markup.Escape(exMessage ?? "");

var colTimestamp = new Markup(safeTime, messageStyle).Centered();
var colLevel = new Markup(safeLevel, messageStyle).RightJustified();
var colMessage = new Markup(safeMessage, messageStyle).Centered();
var colLogger = new Markup(safeLogger, new Style(messageStyle.Foreground, messageStyle.Background, messageStyle.Decoration
#if DEBUG
//, link = ...
#endif
#endif
)).LeftJustified();
var colError = new Markup(isError ? exMessage : "", exStyle).RightJustified();
var colError = new Markup(isError ? safeExMessage : "", exStyle).RightJustified();
if (IncludeTimeStamps) _table.AddRow(colTimestamp, colLevel, colMessage, colLogger, colError);
else _table.AddRow(colLevel, colMessage, colLogger, colError);
}
Expand Down
195 changes: 118 additions & 77 deletions src/DiIiS-NA/Core/Logging/ConsoleTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,82 +6,123 @@

namespace DiIiS_NA.Core.Logging
{
public class ConsoleTarget : LogTarget
{
/// <param name="minLevel">Minimum level of messages to emit</param>
/// <param name="maxLevel">Maximum level of messages to emit</param>
/// <param name="includeTimeStamps">Include timestamps in log?</param>
public ConsoleTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTimeStamps, string timeStampFormat)
{
MinimumLevel = minLevel;
MaximumLevel = maxLevel;
IncludeTimeStamps = includeTimeStamps;
TimeStampFormat = timeStampFormat;
}


/// <param name="level">Log level.</param>
/// <param name="logger">Source of the log message.</param>
/// <param name="message">Log message.</param>
public override void LogMessage(Logger.Level level, string logger, string message)
{
var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString(TimeStampFormat) + "]] " : "";
AnsiConsole.MarkupLine($"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {AnsiTarget.Cleanup(message)}[/]");
}
public class ConsoleTarget : LogTarget
{
/// <param name="minLevel">Minimum level of messages to emit</param>
/// <param name="maxLevel">Maximum level of messages to emit</param>
/// <param name="includeTimeStamps">Include timestamps in log?</param>
public ConsoleTarget(Logger.Level minLevel, Logger.Level maxLevel, bool includeTimeStamps, string timeStampFormat)
{
MinimumLevel = minLevel;
MaximumLevel = maxLevel;
IncludeTimeStamps = includeTimeStamps;
TimeStampFormat = timeStampFormat;
}

/// <param name="level">Log level.</param>
/// <param name="logger">Source of the log message.</param>
/// <param name="message">Log message.</param>
/// <param name="exception">Exception to be included with log message.</param>
public override void LogException(Logger.Level level, string logger, string message, Exception exception)
{
var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString(TimeStampFormat) + "]] " : "";

AnsiConsole.MarkupLine(
$"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {Cleanup(message)}[/] - [underline red on white][[{exception.GetType().Name}]][/][red] {Cleanup(exception.Message)}[/]");
AnsiConsole.WriteException(exception);
}


/// <summary>
/// Performs a cleanup on the target.
/// All [ becomes [[, and ] becomes ]] (for ignoring ANSI codes)
/// To use a style, use $[..]$abc$[/]$.
/// Example:
/// Logger.Warn("This is a $[red]$red$[/]$ message");
/// instead of
/// Logger.Warn("This is a [red]red[/] message");
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
string Cleanup(string x) => AnsiTarget.Beautify(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));


/// <param name="level"></param>
private static string SetColor(Logger.Level level, bool withBackground = false)
{
string postfix = withBackground ? " on grey19" : "";
switch (level)
{
case Logger.Level.PacketDump:
return $"[grey30{postfix}]";
case Logger.Level.Debug:
return $"[grey39{postfix}]";
case Logger.Level.Trace:
return $"[purple{postfix}]";
case Logger.Level.Info:
return $"[white{postfix}]";
case Logger.Level.Success:
return $"[green3_1{postfix}]";
case Logger.Level.Warn:
return $"[darkorange3_1{postfix}]";
case Logger.Level.Error:
return $"[indianred1{postfix}]";
case Logger.Level.Fatal:
return $"[red3{postfix}]";
default:
return $"[navajowhite3{postfix}]";
}
}
}
}
/// <param name="level">Log level.</param>
/// <param name="logger">Source of the log message.</param>
/// <param name="message">Log message.</param>
public override void LogMessage(Logger.Level level, string logger, string message)
{
var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString(TimeStampFormat) + "]] " : "";

try
{
AnsiConsole.MarkupLine($"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {Cleanup(message)}[/]");
}
catch (Exception ex)
{
// Фоллбек без форматирования
var safeTimeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString(TimeStampFormat) + "] " : "";
Console.WriteLine($"{safeTimeStamp}[{level}] [{logger}]: {message} - (Logging error: {ex.Message})");
}
}

/// <param name="level">Log level.</param>
/// <param name="logger">Source of the log message.</param>
/// <param name="message">Log message.</param>
/// <param name="exception">Exception to be included with log message.</param>
public override void LogException(Logger.Level level, string logger, string message, Exception exception)
{
var timeStamp = IncludeTimeStamps ? "[[" + DateTime.Now.ToString(TimeStampFormat) + "]] " : "";

try
{
AnsiConsole.MarkupLine(
$"{timeStamp}{SetColor(level, true)}[[{level.ToString(),8}]][/] {SetColor(level)}[[{Cleanup(logger),20}]]: {Cleanup(message)}[/] - [underline red on white][[{exception.GetType().Name}]][/][red] {Cleanup(exception.Message)}[/]");
AnsiConsole.WriteException(exception);
}
catch (Exception ex)
{
// fallback to Console.WriteLine to avoid logging causing crashes
var safeTimeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString(TimeStampFormat) + "] " : "";
Console.WriteLine($"{safeTimeStamp}[{level}] [{logger}]: {message} - [Exception] {exception} (Logging error: {ex.Message})");
}
}


/// <summary>
/// Performs a cleanup on the target.
/// All [ becomes [[, and ] becomes ]] (for ignoring ANSI codes)
/// To use a style, use $[..]$abc$[/]$.
/// Example:
/// Logger.Warn("This is a $[red]$red$[/]$ message");
/// instead of
/// Logger.Warn("This is a [red]red[/] message");
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
//string Cleanup(string x) => AnsiTarget.Beautify(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
string Cleanup(string x)
{
if (string.IsNullOrEmpty(x)) return "";

// Временные маркеры для защиты нашего кастомного форматирования
string protectedText = x
.Replace("$[/]$", "{{TEMP_END}}")
.Replace("$[", "{{TEMP_OPEN}}")
.Replace("]$", "{{TEMP_CLOSE}}");

// Экранируем все оставшиеся случайные скобки
string escaped = protectedText
.Replace("[", "[[")
.Replace("]", "]]");

// Восстанавливаем наше форматирование в правильную Spectre.Console разметку
string restored = escaped
.Replace("{{TEMP_OPEN}}", "[")
.Replace("{{TEMP_CLOSE}}", "]")
.Replace("{{TEMP_END}}", "[/]");

return AnsiTarget.Beautify(restored);
}

/// <param name="level"></param>
private static string SetColor(Logger.Level level, bool withBackground = false)
{
string postfix = withBackground ? " on grey19" : "";
switch (level)
{
case Logger.Level.PacketDump:
return $"[grey30{postfix}]";
case Logger.Level.Debug:
return $"[grey39{postfix}]";
case Logger.Level.Trace:
return $"[purple{postfix}]";
case Logger.Level.Info:
return $"[white{postfix}]";
case Logger.Level.Success:
return $"[green3_1{postfix}]";
case Logger.Level.Warn:
return $"[darkorange3_1{postfix}]";
case Logger.Level.Error:
return $"[indianred1{postfix}]";
case Logger.Level.Fatal:
return $"[red3{postfix}]";
default:
return $"[navajowhite3{postfix}]";
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static Actor Create(World world, ActorSno sno, TagMap tags, [CallerMember

// Otherwise → it is indeed an expected asset that does not exist → log error.
var path = Path.GetFileName(filePath);
Logger.Trace($"$[underline red on white]$Actor asset not found$[/]$, Method: $[olive]{memberName}()$[/]$ - $[underline white]{memberName}() in {path}:{lineNumber}$[/]$");
Logger.Trace($"$[underline red on white]$Actor asset not found$[/]$, Method: $[olive]${memberName}()$[/]$ - $[underline white]${memberName}() in {path}:{lineNumber}$[/]$");
return null;
}
switch (sno)
Expand Down
4 changes: 2 additions & 2 deletions src/DiIiS-NA/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ ForceMinimapVisibility = false
; AnsiLog for visualization, ConsoleLog for debugging, and PacketLog for packet analysis

[AnsiLog]
Enabled = true
Enabled = false
Target = Ansi
IncludeTimeStamps = true
MinimumLevel = MethodTrace
MaximumLevel = Fatal

[ConsoleLog]
Enabled = false
Enabled = true
Target = Console
IncludeTimeStamps = true
MinimumLevel = MethodTrace
Expand Down
2 changes: 1 addition & 1 deletion src/DiIiS-NA/database.Account.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<property name="use_proxy_validator">true</property>
<property name="command_timeout">0</property>
<property name="connection.connection_string">
Server=localhost;Database=diiis;User ID=postgres;Password=postgres
Server=localhost;Database=diiis;User ID=postgres;Password=123456
</property>
<property name="connection.release_mode">on_close</property>
<property name="adonet.batch_size">0</property>
Expand Down
2 changes: 1 addition & 1 deletion src/DiIiS-NA/database.Worlds.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<property name="use_proxy_validator">true</property>
<property name="command_timeout">0</property>
<property name="connection.connection_string">
Server=localhost;Database=worlds;User ID=postgres;Password=postgres
Server=localhost;Database=worlds;User ID=postgres;Password=123456
</property>
<property name="connection.release_mode">on_close</property>
<property name="adonet.batch_size">0</property>
Expand Down
Loading