feat(util): add IPluginLogProxy interface and production wrapper

F12.2 closes the gap that F12.1 left open: MessageStore's ctor calls
Plugin.Log.Information inside Migrate0, which prevents an isolated xUnit
construction test (Dalamud.dll cannot load in the test AppDomain).

The proxy mirrors IPluginLog's full surface (Verbose/Debug/Information/
Info/Warning/Error/Fatal — both Info and Information as Dalamud exposes
them) with both single-string and Exception+string overloads, so the
~91 existing Plugin.Log.* call-sites become a drop-in rewrite to
Plugin.LogProxy.*.

A later DI-container adoption cycle (v1.5.x) may swap this for
Microsoft.Extensions.Logging's ILogger<T>; this commit is the
intermediate decorator step.
This commit is contained in:
2026-05-13 08:11:34 +02:00
parent 3c33acf6d7
commit 8edc3c70d3
3 changed files with 79 additions and 0 deletions
+6
View File
@@ -117,6 +117,11 @@ public sealed class Plugin : IAsyncDalamudPlugin
// any service allocated in LoadAsync can read Plugin.PlatformUtil. // any service allocated in LoadAsync can read Plugin.PlatformUtil.
internal static IPlatformUtil PlatformUtil { get; private set; } = null!; internal static IPlatformUtil PlatformUtil { get; private set; } = null!;
// Log indirection over Dalamud's IPluginLog. Same rationale as PlatformUtil:
// call-sites read through LogProxy so MessageStore can be tested in
// isolation. Wired immediately after Dalamud injects Log.
internal static IPluginLogProxy LogProxy { get; private set; } = null!;
// Idempotency guard — Dalamud may fire DisposeAsync twice in a reload race. // Idempotency guard — Dalamud may fire DisposeAsync twice in a reload race.
private int _disposeStarted; private int _disposeStarted;
@@ -162,6 +167,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
// needs Util.* — services then read Plugin.PlatformUtil instead of // needs Util.* — services then read Plugin.PlatformUtil instead of
// hitting the Dalamud static surface directly. // hitting the Dalamud static surface directly.
PlatformUtil = new DalamudPlatformUtil(); PlatformUtil = new DalamudPlatformUtil();
LogProxy = new DalamudPluginLogProxy(Log);
// Schema gate: v1.4.x requires config v16. Users on older schemas // Schema gate: v1.4.x requires config v16. Users on older schemas
// must install v1.4.2 first to run the migration chain. // must install v1.4.2 first to run the migration chain.
+40
View File
@@ -0,0 +1,40 @@
using System;
using Dalamud.Plugin.Services;
namespace HellionChat.Util;
internal sealed class DalamudPluginLogProxy : IPluginLogProxy
{
private readonly IPluginLog _log;
public DalamudPluginLogProxy(IPluginLog log) => _log = log;
public void Verbose(string message) => _log.Verbose(message);
public void Verbose(Exception exception, string message) => _log.Verbose(exception, message);
public void Debug(string message) => _log.Debug(message);
public void Debug(Exception exception, string message) => _log.Debug(exception, message);
public void Information(string message) => _log.Information(message);
public void Information(Exception exception, string message) =>
_log.Information(exception, message);
public void Info(string message) => _log.Info(message);
public void Info(Exception exception, string message) => _log.Info(exception, message);
public void Warning(string message) => _log.Warning(message);
public void Warning(Exception exception, string message) => _log.Warning(exception, message);
public void Error(string message) => _log.Error(message);
public void Error(Exception exception, string message) => _log.Error(exception, message);
public void Fatal(string message) => _log.Fatal(message);
public void Fatal(Exception exception, string message) => _log.Fatal(exception, message);
}
+33
View File
@@ -0,0 +1,33 @@
using System;
namespace HellionChat.Util;
// Indirection over Dalamud's IPluginLog so MessageStore can be constructed
// in an isolated xUnit AppDomain without loading Dalamud.dll — same pattern
// as IPlatformUtil from F12.1. A later DI-container cycle (v1.5.x) may
// replace this with Microsoft.Extensions.Logging's ILogger<T>.
internal interface IPluginLogProxy
{
void Verbose(string message);
void Verbose(Exception exception, string message);
void Debug(string message);
void Debug(Exception exception, string message);
void Information(string message);
void Information(Exception exception, string message);
// 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 Warning(string message);
void Warning(Exception exception, string message);
void Error(string message);
void Error(Exception exception, string message);
void Fatal(string message);
void Fatal(Exception exception, string message);
}