refactor(services): route logging through IPluginLogProxy

F12.2 step 5b — service cluster (~42 sites in 16 files):
MessageManager, GameFunctions/{Chat, GameFunctions, KeybindManager},
EmoteCache, PayloadHandler, AutoTellTabsService, FontManager, Commands,
Util/{WrapperUtil, AutoTranslate, MemoryUtil}, Message, Themes/ThemeRegistry,
Ipc/ExtraChat, Configuration.

The proxy interface gained Dalamud's params-overload signature
(messageTemplate + params object[]) to cover Configuration.cs:86 which
relies on Serilog-style placeholders.

Verified: zero remaining Plugin.Log.X(...) call-sites in HellionChat/,
build green, build-suite 690/690.
This commit is contained in:
2026-05-13 08:38:40 +02:00
parent 63cad62c89
commit fee2459e73
18 changed files with 78 additions and 42 deletions
+2 -2
View File
@@ -96,7 +96,7 @@ internal sealed class AutoTellTabsService : IDisposable
if (partner == null) if (partner == null)
{ {
// Diagnostics: helps detect regressions (FFXIV payload changes, new edge cases) // Diagnostics: helps detect regressions (FFXIV payload changes, new edge cases)
Plugin.Log.Warning( Plugin.LogProxy.Warning(
$"[AutoTellTabs] Could not extract tell partner. type={message.Code.Type}, " $"[AutoTellTabs] Could not extract tell partner. type={message.Code.Type}, "
+ $"senderChunks={message.Sender.Count}, contentChunks={message.Content.Count}, " + $"senderChunks={message.Sender.Count}, contentChunks={message.Content.Count}, "
+ $"senderSourcePayloads={message.SenderSource?.Payloads?.Count ?? 0}, " + $"senderSourcePayloads={message.SenderSource?.Payloads?.Count ?? 0}, "
@@ -300,7 +300,7 @@ internal sealed class AutoTellTabsService : IDisposable
catch (Exception ex) catch (Exception ex)
{ {
// Non-fatal: tab still spawns with visible error notice instead of silent history loss // Non-fatal: tab still spawns with visible error notice instead of silent history loss
Plugin.Log.Error(ex, "[AutoTellTabs] History preload failed"); Plugin.LogProxy.Error(ex, "[AutoTellTabs] History preload failed");
tab.Messages.AddPrune( tab.Messages.AddPrune(
MakeSystemMarker(HellionStrings.AutoTellTabs_HistoryLoadError), MakeSystemMarker(HellionStrings.AutoTellTabs_HistoryLoadError),
MessageManager.MessageDisplayLimit MessageManager.MessageDisplayLimit
+2 -2
View File
@@ -52,7 +52,7 @@ internal sealed class Commands : IDisposable
{ {
if (!Registered.TryGetValue(command, out var wrapper)) if (!Registered.TryGetValue(command, out var wrapper))
{ {
Plugin.Log.Warning($"Missing registration for command {command}"); Plugin.LogProxy.Warning($"Missing registration for command {command}");
return; return;
} }
@@ -62,7 +62,7 @@ internal sealed class Commands : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, $"Error while executing command {command}"); Plugin.LogProxy.Error(ex, $"Error while executing command {command}");
} }
} }
} }
+1 -1
View File
@@ -83,7 +83,7 @@ public class Configuration : IPluginConfiguration
// silently, like before. // silently, like before.
if (!Enum.IsDefined(typeof(ChatType), type) && _warnedUnknownChannels.Add(type)) if (!Enum.IsDefined(typeof(ChatType), type) && _warnedUnknownChannels.Add(type))
{ {
Plugin.Log.Warning( Plugin.LogProxy.Warning(
"PrivacyFilter: unrecognised ChatType {Type} — falling back to PrivacyPersistUnknownChannels={Persist}.", "PrivacyFilter: unrecognised ChatType {Type} — falling back to PrivacyPersistUnknownChannels={Persist}.",
type, type,
PrivacyPersistUnknownChannels PrivacyPersistUnknownChannels
+8 -5
View File
@@ -101,7 +101,10 @@ public static class EmoteCache
t => t =>
{ {
if (t.IsFaulted) if (t.IsFaulted)
Plugin.Log.Error(t.Exception!, $"EmoteCache load failed for {emoteCode}"); Plugin.LogProxy.Error(
t.Exception!,
$"EmoteCache load failed for {emoteCode}"
);
}, },
TaskScheduler.Default TaskScheduler.Default
) )
@@ -158,7 +161,7 @@ public static class EmoteCache
{ {
// Reset to Unloaded so a later trigger can retry without a plugin reload. // Reset to Unloaded so a later trigger can retry without a plugin reload.
State = LoadingState.Unloaded; State = LoadingState.Unloaded;
Plugin.Log.Error(ex, "BetterTTV cache wasn't initialized"); Plugin.LogProxy.Error(ex, "BetterTTV cache wasn't initialized");
} }
} }
@@ -214,7 +217,7 @@ public static class EmoteCache
} }
catch catch
{ {
Plugin.Log.Error("Failed to convert"); Plugin.LogProxy.Error("Failed to convert");
return null; return null;
} }
} }
@@ -304,7 +307,7 @@ public static class EmoteCache
catch (Exception ex) catch (Exception ex)
{ {
Failed = true; Failed = true;
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}"); Plugin.LogProxy.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
} }
} }
@@ -408,7 +411,7 @@ public static class EmoteCache
catch (Exception ex) catch (Exception ex)
{ {
Failed = true; Failed = true;
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}"); Plugin.LogProxy.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
} }
} }
} }
+2 -2
View File
@@ -58,7 +58,7 @@ public class FontManager
); );
if (stream is null) if (stream is null)
{ {
Plugin.Log.Warning( Plugin.LogProxy.Warning(
"Hellion font resource missing — falling back to system default font." "Hellion font resource missing — falling back to system default font."
); );
return null; return null;
@@ -237,7 +237,7 @@ public class FontManager
// Atlas-toolkit throws span IO and validation failures; routing the // Atlas-toolkit throws span IO and validation failures; routing the
// wider set through the fallback keeps a corrupt font config from // wider set through the fallback keeps a corrupt font config from
// taking down the whole atlas build. // taking down the whole atlas build.
Plugin.Log.Warning( Plugin.LogProxy.Warning(
e, e,
$"Configured {slot} font failed to load ({e.GetType().Name}), " $"Configured {slot} font failed to load ({e.GetType().Name}), "
+ "falling back to NotoSansCjkRegular" + "falling back to NotoSansCjkRegular"
+6 -6
View File
@@ -236,7 +236,7 @@ internal sealed unsafe class Chat : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in chat Activated event"); Plugin.LogProxy.Error(ex, "Error in chat Activated event");
} }
}); });
} }
@@ -266,7 +266,7 @@ internal sealed unsafe class Chat : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in chat Activated event"); Plugin.LogProxy.Error(ex, "Error in chat Activated event");
} }
return 1; // Prevent vanilla chat log from gaining focus return 1; // Prevent vanilla chat log from gaining focus
@@ -299,7 +299,7 @@ internal sealed unsafe class Chat : IDisposable
{ {
playerName = SeString.Parse(agent->TellPlayerName).TextValue; playerName = SeString.Parse(agent->TellPlayerName).TextValue;
worldId = agent->TellWorldId; worldId = agent->TellWorldId;
Plugin.Log.Debug($"Detected tell target '[redacted]'@{worldId}"); Plugin.LogProxy.Debug($"Detected tell target '[redacted]'@{worldId}");
} }
Plugin.CurrentTab.CurrentChannel = new UsedChannel Plugin.CurrentTab.CurrentChannel = new UsedChannel
@@ -358,7 +358,7 @@ internal sealed unsafe class Chat : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in chat Activated event"); Plugin.LogProxy.Error(ex, "Error in chat Activated event");
} }
} }
@@ -408,7 +408,7 @@ internal sealed unsafe class Chat : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in chat Activated event"); Plugin.LogProxy.Error(ex, "Error in chat Activated event");
} }
} }
@@ -624,7 +624,7 @@ internal sealed unsafe class Chat : IDisposable
if (contentId == 0) if (contentId == 0)
{ {
Plugin.ChatGui.PrintError(Language.Chat_SendTell_Error); Plugin.ChatGui.PrintError(Language.Chat_SendTell_Error);
Plugin.Log.Warning( Plugin.LogProxy.Warning(
"Tried to send a tell with ContentId being 0, sorry this is an internal error." "Tried to send a tell with ContentId being 0, sorry this is an internal error."
); );
return; return;
+2 -2
View File
@@ -215,7 +215,7 @@ internal unsafe class GameFunctions : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Plugin.Log.Warning(e, "Unable to open adventurer plate"); Plugin.LogProxy.Warning(e, "Unable to open adventurer plate");
return false; return false;
} }
} }
@@ -255,7 +255,7 @@ internal unsafe class GameFunctions : IDisposable
var byteCount = System.Text.Encoding.UTF8.GetByteCount(ReplacementName); var byteCount = System.Text.Encoding.UTF8.GetByteCount(ReplacementName);
if (byteCount >= PlaceholderBufferSize) if (byteCount >= PlaceholderBufferSize)
{ {
Plugin.Log.Warning( Plugin.LogProxy.Warning(
$"Replacement name too long for placeholder buffer ({byteCount} bytes >= {PlaceholderBufferSize}); falling back to original." $"Replacement name too long for placeholder buffer ({byteCount} bytes >= {PlaceholderBufferSize}); falling back to original."
); );
ReplacementName = null; ReplacementName = null;
+1 -1
View File
@@ -507,7 +507,7 @@ internal unsafe class KeybindManager : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in chat Activated event"); Plugin.LogProxy.Error(ex, "Error in chat Activated event");
} }
} }
+4 -1
View File
@@ -62,7 +62,10 @@ public sealed class ExtraChat : IDisposable
catch (Exception ex) catch (Exception ex)
{ {
// ExtraChat is optional; IPC failure is normal when the plugin isn't loaded. // ExtraChat is optional; IPC failure is normal when the plugin isn't loaded.
Plugin.Log.Verbose(ex, "ExtraChat IPC initial state query failed (peer not loaded?)"); Plugin.LogProxy.Verbose(
ex,
"ExtraChat IPC initial state query failed (peer not loaded?)"
);
} }
} }
+4 -4
View File
@@ -153,8 +153,8 @@ public partial class Message
} }
catch (ArgumentException ex) catch (ArgumentException ex)
{ {
Plugin.Log.Error(ex, "Failed to parse extra chat channel GUID"); Plugin.LogProxy.Error(ex, "Failed to parse extra chat channel GUID");
Plugin.Log.Error($"Byte Array: ${string.Join(", ", data[4..^1])}"); Plugin.LogProxy.Error($"Byte Array: ${string.Join(", ", data[4..^1])}");
return Guid.Empty; return Guid.Empty;
} }
} }
@@ -251,7 +251,7 @@ public partial class Message
AddChunkWithMessage( AddChunkWithMessage(
text.NewWithStyle(chunk.Source, chunk.Link, token.Value) text.NewWithStyle(chunk.Source, chunk.Link, token.Value)
); );
Plugin.Log.Debug( Plugin.LogProxy.Debug(
$"Invalid URL accepted by Regex but failed URI parsing: '{token.Value}'" $"Invalid URL accepted by Regex but failed URI parsing: '{token.Value}'"
); );
} }
@@ -416,7 +416,7 @@ public partial class Message
catch (Exception) catch (Exception)
{ {
AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, split)); AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, split));
Plugin.Log.Debug($"Failed to parse the text param: '{split}'"); Plugin.LogProxy.Debug($"Failed to parse the text param: '{split}'");
} }
} }
} }
+9 -7
View File
@@ -91,7 +91,7 @@ internal class MessageManager : IAsyncDisposable
await Task.Delay(100); await Task.Delay(100);
if (PendingMessageThread.IsAlive) if (PendingMessageThread.IsAlive)
Plugin.Log.Warning( Plugin.LogProxy.Warning(
"PendingMessageThread did not observe cancellation within 10s. " "PendingMessageThread did not observe cancellation within 10s. "
+ "Worker remains on background thread; next plugin reload releases it." + "Worker remains on background thread; next plugin reload releases it."
); );
@@ -137,7 +137,7 @@ internal class MessageManager : IAsyncDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error processing pending message"); Plugin.LogProxy.Error(ex, "Error processing pending message");
} }
} }
else else
@@ -182,10 +182,12 @@ internal class MessageManager : IAsyncDisposable
// Mark failed messages as deleted to prevent retry attempts // Mark failed messages as deleted to prevent retry attempts
var failedIds = messages.FailedMessageIds(); var failedIds = messages.FailedMessageIds();
Plugin.Log.Info($"Marking {failedIds.Count} messages as deleted due to parse failures"); Plugin.LogProxy.Info(
$"Marking {failedIds.Count} messages as deleted due to parse failures"
);
foreach (var msgId in messages.FailedMessageIds()) foreach (var msgId in messages.FailedMessageIds())
{ {
Plugin.Log.Debug($"Marking message '{msgId}' as deleted due to parse failure"); Plugin.LogProxy.Debug($"Marking message '{msgId}' as deleted due to parse failure");
Store.DeleteMessage(msgId); Store.DeleteMessage(msgId);
} }
} }
@@ -201,10 +203,10 @@ internal class MessageManager : IAsyncDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in FilterAllTabs"); Plugin.LogProxy.Error(ex, "Error in FilterAllTabs");
} }
Plugin.Log.Debug($"FilterAllTabs took {stopwatch.ElapsedMilliseconds}ms"); Plugin.LogProxy.Debug($"FilterAllTabs took {stopwatch.ElapsedMilliseconds}ms");
}); });
} }
@@ -259,7 +261,7 @@ internal class MessageManager : IAsyncDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error in ContentIdResolver"); Plugin.LogProxy.Error(ex, "Error in ContentIdResolver");
} }
} }
+3 -3
View File
@@ -131,7 +131,7 @@ public sealed class PayloadHandler
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error executing integration"); Plugin.LogProxy.Error(ex, "Error executing integration");
} }
} }
@@ -535,7 +535,7 @@ public sealed class PayloadHandler
) )
) )
{ {
Plugin.Log.Warning("Could not find DalamudLinkHandlers"); Plugin.LogProxy.Warning("Could not find DalamudLinkHandlers");
return; return;
} }
@@ -546,7 +546,7 @@ public sealed class PayloadHandler
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, "Error executing DalamudLinkPayload handler"); Plugin.LogProxy.Error(ex, "Error executing DalamudLinkPayload handler");
} }
} }
+1 -1
View File
@@ -118,7 +118,7 @@ public sealed class ThemeRegistry
catch (Exception ex) when (IsRecoverableFileLock(ex)) catch (Exception ex) when (IsRecoverableFileLock(ex))
{ {
// Editor mid-save: keep last known good, retry on next refresh. // Editor mid-save: keep last known good, retry on next refresh.
Plugin.Log.Debug( Plugin.LogProxy.Debug(
$"Custom theme {Path.GetFileName(path)} is locked, keeping last known good" $"Custom theme {Path.GetFileName(path)} is locked, keeping last known good"
); );
if (cached.Theme is not null) if (cached.Theme is not null)
+2 -2
View File
@@ -62,7 +62,7 @@ internal static class AutoTranslate
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
AllEntries(); AllEntries();
Plugin.Log.Debug($"Warming up auto-translate took {sw.ElapsedMilliseconds}ms"); Plugin.LogProxy.Debug($"Warming up auto-translate took {sw.ElapsedMilliseconds}ms");
}) })
{ {
IsBackground = true, IsBackground = true,
@@ -197,7 +197,7 @@ internal static class AutoTranslate
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error(ex, $"failed to translate: {lookup}"); Plugin.LogProxy.Error(ex, $"failed to translate: {lookup}");
} }
} }
+21
View File
@@ -13,28 +13,49 @@ internal sealed class DalamudPluginLogProxy : IPluginLogProxy
public void Verbose(Exception exception, string message) => _log.Verbose(exception, message); public void Verbose(Exception exception, string message) => _log.Verbose(exception, message);
public void Verbose(string messageTemplate, params object[] values) =>
_log.Verbose(messageTemplate, values);
public void Debug(string message) => _log.Debug(message); public void Debug(string message) => _log.Debug(message);
public void Debug(Exception exception, string message) => _log.Debug(exception, message); public void Debug(Exception exception, string message) => _log.Debug(exception, message);
public void Debug(string messageTemplate, params object[] values) =>
_log.Debug(messageTemplate, values);
public void Information(string message) => _log.Information(message); public void Information(string message) => _log.Information(message);
public void Information(Exception exception, string message) => public void Information(Exception exception, string message) =>
_log.Information(exception, message); _log.Information(exception, message);
public void Information(string messageTemplate, params object[] values) =>
_log.Information(messageTemplate, values);
public void Info(string message) => _log.Info(message); public void Info(string message) => _log.Info(message);
public void Info(Exception exception, string message) => _log.Info(exception, message); public void Info(Exception exception, string message) => _log.Info(exception, message);
public void Info(string messageTemplate, params object[] values) =>
_log.Info(messageTemplate, values);
public void Warning(string message) => _log.Warning(message); public void Warning(string message) => _log.Warning(message);
public void Warning(Exception exception, string message) => _log.Warning(exception, message); public void Warning(Exception exception, string message) => _log.Warning(exception, message);
public void Warning(string messageTemplate, params object[] values) =>
_log.Warning(messageTemplate, values);
public void Error(string message) => _log.Error(message); public void Error(string message) => _log.Error(message);
public void Error(Exception exception, string message) => _log.Error(exception, message); public void Error(Exception exception, string message) => _log.Error(exception, message);
public void Error(string messageTemplate, params object[] values) =>
_log.Error(messageTemplate, values);
public void Fatal(string message) => _log.Fatal(message); public void Fatal(string message) => _log.Fatal(message);
public void Fatal(Exception exception, string message) => _log.Fatal(exception, message); public void Fatal(Exception exception, string message) => _log.Fatal(exception, message);
public void Fatal(string messageTemplate, params object[] values) =>
_log.Fatal(messageTemplate, values);
} }
+7
View File
@@ -10,24 +10,31 @@ internal interface IPluginLogProxy
{ {
void Verbose(string message); void Verbose(string message);
void Verbose(Exception exception, string message); void Verbose(Exception exception, string message);
void Verbose(string messageTemplate, params object[] values);
void Debug(string message); void Debug(string message);
void Debug(Exception exception, string message); void Debug(Exception exception, string message);
void Debug(string messageTemplate, params object[] values);
void Information(string message); void Information(string message);
void Information(Exception exception, string message); void Information(Exception exception, string message);
void Information(string messageTemplate, params object[] values);
// IPluginLog exposes Info as a distinct method (short alias of // IPluginLog exposes Info as a distinct method (short alias of
// Information) — both are present so call-sites stay drop-in. // Information) — both are present so call-sites stay drop-in.
void Info(string message); void Info(string message);
void Info(Exception exception, string message); void Info(Exception exception, string message);
void Info(string messageTemplate, params object[] values);
void Warning(string message); void Warning(string message);
void Warning(Exception exception, string message); void Warning(Exception exception, string message);
void Warning(string messageTemplate, params object[] values);
void Error(string message); void Error(string message);
void Error(Exception exception, string message); void Error(Exception exception, string message);
void Error(string messageTemplate, params object[] values);
void Fatal(string message); void Fatal(string message);
void Fatal(Exception exception, string message); void Fatal(Exception exception, string message);
void Fatal(string messageTemplate, params object[] values);
} }
+1 -1
View File
@@ -42,6 +42,6 @@ public static class MemoryUtil
str.Append(' '); str.Append(' ');
} }
Plugin.Log.Information(str.ToString()); Plugin.LogProxy.Information(str.ToString());
} }
} }
+2 -2
View File
@@ -21,12 +21,12 @@ public static class WrapperUtil
{ {
try try
{ {
Plugin.Log.Debug($"Opening URI {uri} in default browser"); Plugin.LogProxy.Debug($"Opening URI {uri} in default browser");
Plugin.PlatformUtil.OpenLink(uri.ToString()); Plugin.PlatformUtil.OpenLink(uri.ToString());
} }
catch (Exception ex) catch (Exception ex)
{ {
Plugin.Log.Error($"Error opening URI: {ex}"); Plugin.LogProxy.Error($"Error opening URI: {ex}");
AddNotification(Language.Context_OpenInBrowserError, NotificationType.Error); AddNotification(Language.Context_OpenInBrowserError, NotificationType.Error);
} }
} }