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)
{
// 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}, "
+ $"senderChunks={message.Sender.Count}, contentChunks={message.Content.Count}, "
+ $"senderSourcePayloads={message.SenderSource?.Payloads?.Count ?? 0}, "
@@ -300,7 +300,7 @@ internal sealed class AutoTellTabsService : IDisposable
catch (Exception ex)
{
// 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(
MakeSystemMarker(HellionStrings.AutoTellTabs_HistoryLoadError),
MessageManager.MessageDisplayLimit
+2 -2
View File
@@ -52,7 +52,7 @@ internal sealed class Commands : IDisposable
{
if (!Registered.TryGetValue(command, out var wrapper))
{
Plugin.Log.Warning($"Missing registration for command {command}");
Plugin.LogProxy.Warning($"Missing registration for command {command}");
return;
}
@@ -62,7 +62,7 @@ internal sealed class Commands : IDisposable
}
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.
if (!Enum.IsDefined(typeof(ChatType), type) && _warnedUnknownChannels.Add(type))
{
Plugin.Log.Warning(
Plugin.LogProxy.Warning(
"PrivacyFilter: unrecognised ChatType {Type} — falling back to PrivacyPersistUnknownChannels={Persist}.",
type,
PrivacyPersistUnknownChannels
+8 -5
View File
@@ -101,7 +101,10 @@ public static class EmoteCache
t =>
{
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
)
@@ -158,7 +161,7 @@ public static class EmoteCache
{
// Reset to Unloaded so a later trigger can retry without a plugin reload.
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
{
Plugin.Log.Error("Failed to convert");
Plugin.LogProxy.Error("Failed to convert");
return null;
}
}
@@ -304,7 +307,7 @@ public static class EmoteCache
catch (Exception ex)
{
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)
{
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)
{
Plugin.Log.Warning(
Plugin.LogProxy.Warning(
"Hellion font resource missing — falling back to system default font."
);
return null;
@@ -237,7 +237,7 @@ public class FontManager
// Atlas-toolkit throws span IO and validation failures; routing the
// wider set through the fallback keeps a corrupt font config from
// taking down the whole atlas build.
Plugin.Log.Warning(
Plugin.LogProxy.Warning(
e,
$"Configured {slot} font failed to load ({e.GetType().Name}), "
+ "falling back to NotoSansCjkRegular"
+6 -6
View File
@@ -236,7 +236,7 @@ internal sealed unsafe class Chat : IDisposable
}
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)
{
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
@@ -299,7 +299,7 @@ internal sealed unsafe class Chat : IDisposable
{
playerName = SeString.Parse(agent->TellPlayerName).TextValue;
worldId = agent->TellWorldId;
Plugin.Log.Debug($"Detected tell target '[redacted]'@{worldId}");
Plugin.LogProxy.Debug($"Detected tell target '[redacted]'@{worldId}");
}
Plugin.CurrentTab.CurrentChannel = new UsedChannel
@@ -358,7 +358,7 @@ internal sealed unsafe class Chat : IDisposable
}
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)
{
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)
{
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."
);
return;
+2 -2
View File
@@ -215,7 +215,7 @@ internal unsafe class GameFunctions : IDisposable
}
catch (Exception e)
{
Plugin.Log.Warning(e, "Unable to open adventurer plate");
Plugin.LogProxy.Warning(e, "Unable to open adventurer plate");
return false;
}
}
@@ -255,7 +255,7 @@ internal unsafe class GameFunctions : IDisposable
var byteCount = System.Text.Encoding.UTF8.GetByteCount(ReplacementName);
if (byteCount >= PlaceholderBufferSize)
{
Plugin.Log.Warning(
Plugin.LogProxy.Warning(
$"Replacement name too long for placeholder buffer ({byteCount} bytes >= {PlaceholderBufferSize}); falling back to original."
);
ReplacementName = null;
+1 -1
View File
@@ -507,7 +507,7 @@ internal unsafe class KeybindManager : IDisposable
}
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)
{
// 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)
{
Plugin.Log.Error(ex, "Failed to parse extra chat channel GUID");
Plugin.Log.Error($"Byte Array: ${string.Join(", ", data[4..^1])}");
Plugin.LogProxy.Error(ex, "Failed to parse extra chat channel GUID");
Plugin.LogProxy.Error($"Byte Array: ${string.Join(", ", data[4..^1])}");
return Guid.Empty;
}
}
@@ -251,7 +251,7 @@ public partial class Message
AddChunkWithMessage(
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}'"
);
}
@@ -416,7 +416,7 @@ public partial class Message
catch (Exception)
{
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);
if (PendingMessageThread.IsAlive)
Plugin.Log.Warning(
Plugin.LogProxy.Warning(
"PendingMessageThread did not observe cancellation within 10s. "
+ "Worker remains on background thread; next plugin reload releases it."
);
@@ -137,7 +137,7 @@ internal class MessageManager : IAsyncDisposable
}
catch (Exception ex)
{
Plugin.Log.Error(ex, "Error processing pending message");
Plugin.LogProxy.Error(ex, "Error processing pending message");
}
}
else
@@ -182,10 +182,12 @@ internal class MessageManager : IAsyncDisposable
// Mark failed messages as deleted to prevent retry attempts
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())
{
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);
}
}
@@ -201,10 +203,10 @@ internal class MessageManager : IAsyncDisposable
}
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)
{
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)
{
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;
}
@@ -546,7 +546,7 @@ public sealed class PayloadHandler
}
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))
{
// 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"
);
if (cached.Theme is not null)
+2 -2
View File
@@ -62,7 +62,7 @@ internal static class AutoTranslate
{
var sw = Stopwatch.StartNew();
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,
@@ -197,7 +197,7 @@ internal static class AutoTranslate
}
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(string messageTemplate, params object[] values) =>
_log.Verbose(messageTemplate, values);
public void Debug(string message) => _log.Debug(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(Exception exception, string 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(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(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(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(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(Exception exception, string message);
void Verbose(string messageTemplate, params object[] values);
void Debug(string message);
void Debug(Exception exception, string message);
void Debug(string messageTemplate, params object[] values);
void Information(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
// Information) — both are present so call-sites stay drop-in.
void Info(string message);
void Info(Exception exception, string message);
void Info(string messageTemplate, params object[] values);
void Warning(string message);
void Warning(Exception exception, string message);
void Warning(string messageTemplate, params object[] values);
void Error(string message);
void Error(Exception exception, string message);
void Error(string messageTemplate, params object[] values);
void Fatal(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(' ');
}
Plugin.Log.Information(str.ToString());
Plugin.LogProxy.Information(str.ToString());
}
}
+2 -2
View File
@@ -21,12 +21,12 @@ public static class WrapperUtil
{
try
{
Plugin.Log.Debug($"Opening URI {uri} in default browser");
Plugin.LogProxy.Debug($"Opening URI {uri} in default browser");
Plugin.PlatformUtil.OpenLink(uri.ToString());
}
catch (Exception ex)
{
Plugin.Log.Error($"Error opening URI: {ex}");
Plugin.LogProxy.Error($"Error opening URI: {ex}");
AddNotification(Language.Context_OpenInBrowserError, NotificationType.Error);
}
}