Logging: Update PluginLog to use Microsoft.Extensions.Logging instead

This commit is contained in:
Liza 2023-02-17 00:54:23 +01:00
parent a5456a54a0
commit 0bb7301ca1
21 changed files with 216 additions and 94 deletions

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Dalamud.Logging; using Dalamud.Logging;
using Microsoft.Extensions.Logging;
using Pal.Client.DependencyInjection.Logging;
namespace Pal.Client.Configuration namespace Pal.Client.Configuration
{ {
@ -10,6 +12,9 @@ namespace Pal.Client.Configuration
{ {
private const int DefaultEntropyLength = 16; private const int DefaultEntropyLength = 16;
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger<AccountConfigurationV7>();
[JsonConstructor] [JsonConstructor]
public AccountConfigurationV7() public AccountConfigurationV7()
{ {
@ -74,7 +79,7 @@ namespace Pal.Client.Configuration
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Verbose(e, $"Could not load account id {EncryptedId}"); _logger.LogTrace(e, "Could not load account id {Id}", EncryptedId);
return null; return null;
} }
} }

View File

@ -2,11 +2,16 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using Microsoft.Extensions.Logging;
using Pal.Client.DependencyInjection.Logging;
namespace Pal.Client.Configuration namespace Pal.Client.Configuration
{ {
internal static class ConfigurationData internal static class ConfigurationData
{ {
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger(typeof(ConfigurationData));
[Obsolete("for V1 import")] [Obsolete("for V1 import")]
internal static readonly byte[] FixedV1Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 }; internal static readonly byte[] FixedV1Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 };
@ -30,7 +35,7 @@ namespace Pal.Client.Configuration
_supportsDpapi = false; _supportsDpapi = false;
} }
PluginLog.Verbose($"DPAPI support: {_supportsDpapi}"); _logger.LogTrace("DPAPI support: {Supported}", _supportsDpapi);
} }
return _supportsDpapi.Value; return _supportsDpapi.Value;
} }

View File

@ -8,6 +8,7 @@ using Dalamud.Logging;
using Dalamud.Plugin; using Dalamud.Plugin;
using ImGuiNET; using ImGuiNET;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Database; using Pal.Client.Database;
using NJson = Newtonsoft.Json; using NJson = Newtonsoft.Json;
@ -15,13 +16,15 @@ namespace Pal.Client.Configuration
{ {
internal sealed class ConfigurationManager internal sealed class ConfigurationManager
{ {
private readonly ILogger<ConfigurationManager> _logger;
private readonly DalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
public event EventHandler<IPalacePalConfiguration>? Saved; public event EventHandler<IPalacePalConfiguration>? Saved;
public ConfigurationManager(DalamudPluginInterface pluginInterface, IServiceProvider serviceProvider) public ConfigurationManager(ILogger<ConfigurationManager> logger, DalamudPluginInterface pluginInterface, IServiceProvider serviceProvider)
{ {
_logger = logger;
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
@ -54,12 +57,12 @@ namespace Pal.Client.Configuration
{ {
if (_pluginInterface.ConfigFile.Exists) if (_pluginInterface.ConfigFile.Exists)
{ {
PluginLog.Information("Migrating config file from v1-v6 format"); _logger.LogInformation("Migrating config file from v1-v6 format");
ConfigurationV1 configurationV1 = ConfigurationV1 configurationV1 =
NJson.JsonConvert.DeserializeObject<ConfigurationV1>( NJson.JsonConvert.DeserializeObject<ConfigurationV1>(
File.ReadAllText(_pluginInterface.ConfigFile.FullName)) ?? new ConfigurationV1(); File.ReadAllText(_pluginInterface.ConfigFile.FullName)) ?? new ConfigurationV1();
configurationV1.Migrate(_pluginInterface); configurationV1.Migrate(_pluginInterface, _serviceProvider.GetRequiredService<ILogger<ConfigurationV1>>());
configurationV1.Save(_pluginInterface); configurationV1.Save(_pluginInterface);
var v7 = MigrateToV7(configurationV1); var v7 = MigrateToV7(configurationV1);
@ -72,7 +75,7 @@ namespace Pal.Client.Configuration
foreach (var importHistory in configurationV1.ImportHistory) foreach (var importHistory in configurationV1.ImportHistory)
{ {
PluginLog.Information($"Migrating import {importHistory.Id}"); _logger.LogInformation("Migrating import {Id}", importHistory.Id);
dbContext.Imports.Add(new ImportHistory dbContext.Imports.Add(new ImportHistory
{ {
Id = importHistory.Id, Id = importHistory.Id,

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Plugin; using Dalamud.Plugin;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Configuration namespace Pal.Client.Configuration
{ {
@ -50,11 +51,11 @@ namespace Pal.Client.Configuration
public string BetaKey { get; set; } = ""; public string BetaKey { get; set; } = "";
#endregion #endregion
public void Migrate(DalamudPluginInterface pluginInterface) public void Migrate(DalamudPluginInterface pluginInterface, ILogger<ConfigurationV1> logger)
{ {
if (Version == 1) if (Version == 1)
{ {
PluginLog.Information("Updating config to version 2"); logger.LogInformation("Updating config to version 2");
if (DebugAccountId != null && Guid.TryParse(DebugAccountId, out Guid debugAccountId)) if (DebugAccountId != null && Guid.TryParse(DebugAccountId, out Guid debugAccountId))
AccountIds["http://localhost:5145"] = debugAccountId; AccountIds["http://localhost:5145"] = debugAccountId;
@ -68,7 +69,7 @@ namespace Pal.Client.Configuration
if (Version == 2) if (Version == 2)
{ {
PluginLog.Information("Updating config to version 3"); logger.LogInformation("Updating config to version 3");
Accounts = AccountIds.ToDictionary(x => x.Key, x => new AccountInfo Accounts = AccountIds.ToDictionary(x => x.Key, x => new AccountInfo
{ {

View File

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Pal.Client.Database; using Pal.Client.Database;
@ -24,12 +27,12 @@ namespace Pal.Client.DependencyInjection
dbContext.SaveChanges(); dbContext.SaveChanges();
} }
public ImportHistory? FindLast() public async Task<ImportHistory?> FindLast(CancellationToken token = default)
{ {
using var scope = _serviceProvider.CreateScope(); await using var scope = _serviceProvider.CreateAsyncScope();
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>(); await using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
return dbContext.Imports.OrderByDescending(x => x.ImportedAt).ThenBy(x => x.Id).FirstOrDefault(); return await dbContext.Imports.OrderByDescending(x => x.ImportedAt).ThenBy(x => x.Id).FirstOrDefaultAsync(cancellationToken: token);
} }
public List<ImportHistory> FindForServer(string server) public List<ImportHistory> FindForServer(string server)

View File

@ -1,27 +1,33 @@
using Dalamud.Logging; using Dalamud.Logging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
namespace Pal.Client.Net namespace Pal.Client.DependencyInjection.Logging
{ {
internal sealed class GrpcLogger : ILogger internal sealed class DalamudLogger : ILogger
{ {
private readonly string _name; private readonly string _name;
private readonly IExternalScopeProvider? _scopeProvider;
public GrpcLogger(string name) public DalamudLogger(string name, IExternalScopeProvider? scopeProvider)
{ {
_name = name; _name = name;
_scopeProvider = scopeProvider;
} }
public IDisposable BeginScope<TState>(TState state) public IDisposable BeginScope<TState>(TState state)
where TState : notnull where TState : notnull
=> NullScope.Instance; => _scopeProvider?.Push(state) ?? NullScope.Instance;
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
[MethodImpl(MethodImplOptions.NoInlining)] // PluginLog detects the plugin name as `Microsoft.Extensions.Logging` if inlined // PluginLog detects the plugin name as `Microsoft.Extensions.Logging` if inlined
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) [MethodImpl(MethodImplOptions.NoInlining)]
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception,
Func<TState, Exception?, string> formatter)
{ {
if (!IsEnabled(logLevel)) if (!IsEnabled(logLevel))
return; return;
@ -29,9 +35,23 @@ namespace Pal.Client.Net
if (formatter == null) if (formatter == null)
throw new ArgumentNullException(nameof(formatter)); throw new ArgumentNullException(nameof(formatter));
string message = $"gRPC[{_name}] {formatter(state, null)}"; StringBuilder sb = new StringBuilder();
if (string.IsNullOrEmpty(message)) _scopeProvider?.ForEachScope((scope, builder) =>
return; {
if (scope is IEnumerable<KeyValuePair<string, object>> properties)
{
foreach (KeyValuePair<string, object> pair in properties)
{
builder.Append('<').Append(pair.Key).Append('=').Append(pair.Value)
.Append("> ");
}
}
else if (scope != null)
builder.Append('<').Append(scope).Append("> ");
},
sb);
sb.Append('[').Append(_name).Append("] ").Append(formatter(state, null));
string message = sb.ToString();
#pragma warning disable CS8604 // the nullability on PluginLog methods is wrong and allows nulls for exceptions, WriteLog even declares the parameter as `Exception? exception = null` #pragma warning disable CS8604 // the nullability on PluginLog methods is wrong and allows nulls for exceptions, WriteLog even declares the parameter as `Exception? exception = null`
switch (logLevel) switch (logLevel)
@ -63,7 +83,7 @@ namespace Pal.Client.Net
#pragma warning restore CS8604 #pragma warning restore CS8604
} }
private class NullScope : IDisposable private sealed class NullScope : IDisposable
{ {
public static NullScope Instance { get; } = new(); public static NullScope Instance { get; } = new();

View File

@ -0,0 +1,31 @@
using Microsoft.Extensions.Logging;
using System;
namespace Pal.Client.DependencyInjection.Logging
{
internal sealed class DalamudLoggerProvider : ILoggerProvider, ISupportExternalScope
{
private IExternalScopeProvider? _scopeProvider;
public ILogger CreateLogger(string categoryName) => new DalamudLogger(categoryName, _scopeProvider);
/// <summary>
/// Manual logger creation, doesn't handle scopes.
/// </summary>
public ILogger CreateLogger(Type type) => CreateLogger(type.FullName ?? type.ToString());
/// <summary>
/// Manual logger creation, doesn't handle scopes.
/// </summary>
public ILogger CreateLogger<T>() => CreateLogger(typeof(T));
public void SetScopeProvider(IExternalScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
}
public void Dispose()
{
}
}
}

View File

@ -2,16 +2,17 @@
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Logging; using Dalamud.Logging;
using Dalamud.Plugin; using Dalamud.Plugin;
using Microsoft.Extensions.Logging;
using Pal.Client.Extensions; using Pal.Client.Extensions;
using Pal.Client.Properties; using Pal.Client.Properties;
namespace Pal.Client.DependencyInjection namespace Pal.Client.DependencyInjection
{ {
public class RepoVerification internal sealed class RepoVerification
{ {
public RepoVerification(DalamudPluginInterface pluginInterface, ChatGui chatGui) public RepoVerification(ILogger<RepoVerification> logger, DalamudPluginInterface pluginInterface, ChatGui chatGui)
{ {
PluginLog.Information($"Install source: {pluginInterface.SourceRepository}"); logger.LogInformation("Install source: {Repo}", pluginInterface.SourceRepository);
if (!pluginInterface.IsDev if (!pluginInterface.IsDev
&& !pluginInterface.SourceRepository.StartsWith("https://raw.githubusercontent.com/carvelli/") && !pluginInterface.SourceRepository.StartsWith("https://raw.githubusercontent.com/carvelli/")
&& !pluginInterface.SourceRepository.StartsWith("https://github.com/carvelli/")) && !pluginInterface.SourceRepository.StartsWith("https://github.com/carvelli/"))

View File

@ -16,10 +16,12 @@ using Dalamud.Plugin;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Commands; using Pal.Client.Commands;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.Database; using Pal.Client.Database;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.DependencyInjection.Logging;
using Pal.Client.Net; using Pal.Client.Net;
using Pal.Client.Properties; using Pal.Client.Properties;
using Pal.Client.Rendering; using Pal.Client.Rendering;
@ -34,6 +36,9 @@ namespace Pal.Client
// ReSharper disable once UnusedType.Global // ReSharper disable once UnusedType.Global
internal sealed class DependencyInjectionContext : IDalamudPlugin internal sealed class DependencyInjectionContext : IDalamudPlugin
{ {
public static DalamudLoggerProvider LoggerProvider { get; } = new();
private readonly ILogger _logger = LoggerProvider.CreateLogger<DependencyInjectionContext>();
private readonly string _sqliteConnectionString; private readonly string _sqliteConnectionString;
private readonly CancellationTokenSource _initCts = new(); private readonly CancellationTokenSource _initCts = new();
private ServiceProvider? _serviceProvider; private ServiceProvider? _serviceProvider;
@ -50,11 +55,16 @@ namespace Pal.Client
CommandManager commandManager, CommandManager commandManager,
DataManager dataManager) DataManager dataManager)
{ {
PluginLog.Information("Building service container"); // Temporary logger, will be overriden later
_logger.LogInformation("Building service container");
CancellationToken token = _initCts.Token; CancellationToken token = _initCts.Token;
IServiceCollection services = new ServiceCollection(); IServiceCollection services = new ServiceCollection();
services.AddLogging(builder =>
builder.AddFilter("Microsoft.EntityFrameworkCore.Database", LogLevel.Warning)
.AddFilter("Grpc", LogLevel.Debug)
.ClearProviders()
.AddProvider(LoggerProvider));
// dalamud // dalamud
services.AddSingleton<IDalamudPlugin>(this); services.AddSingleton<IDalamudPlugin>(this);
services.AddSingleton(pluginInterface); services.AddSingleton(pluginInterface);
@ -134,21 +144,24 @@ namespace Pal.Client
// //
// There's 2-3 seconds of slowdown primarily caused by the sqlite init, but that needs to happen for // There's 2-3 seconds of slowdown primarily caused by the sqlite init, but that needs to happen for
// config stuff. // config stuff.
PluginLog.Information("Service container built, triggering async init"); _logger = _serviceProvider.GetRequiredService<ILogger<DependencyInjectionContext>>();
_logger.LogInformation("Service container built, triggering async init");
Task.Run(async () => Task.Run(async () =>
{ {
using IDisposable? logScope = _logger.BeginScope("AsyncInit");
try try
{ {
PluginLog.Information("Starting async init"); _logger.LogInformation("Starting async init");
// initialize database // initialize database
await using (var scope = _serviceProvider.CreateAsyncScope()) await using (var scope = _serviceProvider.CreateAsyncScope())
{ {
PluginLog.Log("Loading database & running migrations"); _logger.LogInformation("Loading database & running migrations");
await using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>(); await using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
await dbContext.Database.MigrateAsync(); await dbContext.Database.MigrateAsync();
PluginLog.Log("Completed database migrations"); _logger.LogInformation("Completed database migrations");
} }
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
@ -169,14 +182,14 @@ namespace Pal.Client
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
_serviceProvider.GetRequiredService<Plugin>(); _serviceProvider.GetRequiredService<Plugin>();
PluginLog.Information("Async init complete"); _logger.LogInformation("Async init complete");
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, "Async load failed"); _logger.LogError(e, "Async load failed");
chatGui.PrintError($"Async loading failed: {e.GetType()}: {e.Message}"); chatGui.PrintError($"Async loading failed: {e.GetType()}: {e.Message}");
} }
}); });

View File

@ -6,12 +6,14 @@ using Dalamud.Utility.Signatures;
using System; using System;
using System.Text; using System.Text;
using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects;
using Microsoft.Extensions.Logging;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
namespace Pal.Client namespace Pal.Client
{ {
internal sealed unsafe class Hooks : IDisposable internal sealed unsafe class Hooks : IDisposable
{ {
private readonly ILogger<Hooks> _logger;
private readonly ObjectTable _objectTable; private readonly ObjectTable _objectTable;
private readonly TerritoryState _territoryState; private readonly TerritoryState _territoryState;
private readonly FrameworkService _frameworkService; private readonly FrameworkService _frameworkService;
@ -23,8 +25,9 @@ namespace Pal.Client
private Hook<ActorVfxCreateDelegate> ActorVfxCreateHook { get; init; } = null!; private Hook<ActorVfxCreateDelegate> ActorVfxCreateHook { get; init; } = null!;
#pragma warning restore CS0649 #pragma warning restore CS0649
public Hooks(ObjectTable objectTable, TerritoryState territoryState, FrameworkService frameworkService) public Hooks(ILogger<Hooks> logger, ObjectTable objectTable, TerritoryState territoryState, FrameworkService frameworkService)
{ {
_logger = logger;
_objectTable = objectTable; _objectTable = objectTable;
_territoryState = territoryState; _territoryState = territoryState;
_frameworkService = frameworkService; _frameworkService = frameworkService;
@ -86,7 +89,7 @@ namespace Pal.Client
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, "VFX Create Hook failed"); _logger.LogError(e, "VFX Create Hook failed");
} }
return ActorVfxCreateHook.Original(a1, a2, a3, a4, a5, a6, a7); return ActorVfxCreateHook.Original(a1, a2, a3, a4, a5, a6, a7);
} }

View File

@ -1,14 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
namespace Pal.Client.Net
{
internal sealed class GrpcLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName) => new GrpcLogger(categoryName);
public void Dispose()
{
}
}
}

View File

@ -1,5 +1,4 @@
using Account; using Account;
using Dalamud.Logging;
using Grpc.Core; using Grpc.Core;
using Grpc.Net.Client; using Grpc.Net.Client;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -19,9 +18,11 @@ namespace Pal.Client.Net
{ {
private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken, ILoggerFactory? loggerFactory = null, bool retry = true) private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken, ILoggerFactory? loggerFactory = null, bool retry = true)
{ {
using IDisposable? logScope = _logger.BeginScope("TryConnect");
if (_configuration.Mode != EMode.Online) if (_configuration.Mode != EMode.Online)
{ {
PluginLog.Debug("TryConnect: Not Online, not attempting to establish a connection"); _logger.LogDebug("Not Online, not attempting to establish a connection");
return (false, Localization.ConnectionError_NotOnline); return (false, Localization.ConnectionError_NotOnline);
} }
@ -29,7 +30,7 @@ namespace Pal.Client.Net
{ {
Dispose(); Dispose();
PluginLog.Information("TryConnect: Creating new gRPC channel"); _logger.LogInformation("Creating new gRPC channel");
_channel = GrpcChannel.ForAddress(RemoteUrl, new GrpcChannelOptions _channel = GrpcChannel.ForAddress(RemoteUrl, new GrpcChannelOptions
{ {
HttpHandler = new SocketsHttpHandler HttpHandler = new SocketsHttpHandler
@ -40,7 +41,7 @@ namespace Pal.Client.Net
LoggerFactory = loggerFactory, LoggerFactory = loggerFactory,
}); });
PluginLog.Information($"TryConnect: Connecting to upstream service at {RemoteUrl}"); _logger.LogInformation("Connecting to upstream service at {Url}", RemoteUrl);
await _channel.ConnectAsync(cancellationToken); await _channel.ConnectAsync(cancellationToken);
} }
@ -50,7 +51,7 @@ namespace Pal.Client.Net
IAccountConfiguration? configuredAccount = _configuration.FindAccount(RemoteUrl); IAccountConfiguration? configuredAccount = _configuration.FindAccount(RemoteUrl);
if (configuredAccount == null) if (configuredAccount == null)
{ {
PluginLog.Information($"TryConnect: No account information saved for {RemoteUrl}, creating new account"); _logger.LogInformation("No account information saved for {Url}, creating new account", RemoteUrl);
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken); var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
if (createAccountReply.Success) if (createAccountReply.Success)
{ {
@ -58,13 +59,13 @@ namespace Pal.Client.Net
throw new InvalidOperationException("invalid account id returned"); throw new InvalidOperationException("invalid account id returned");
configuredAccount = _configuration.CreateAccount(RemoteUrl, accountId); configuredAccount = _configuration.CreateAccount(RemoteUrl, accountId);
PluginLog.Information($"TryConnect: Account created with id {accountId.ToPartialId()}"); _logger.LogInformation("Account created with id {AccountId}", accountId.ToPartialId());
_configurationManager.Save(_configuration); _configurationManager.Save(_configuration);
} }
else else
{ {
PluginLog.Error($"TryConnect: Account creation failed with error {createAccountReply.Error}"); _logger.LogError("Account creation failed with error {Error}", createAccountReply.Error);
if (createAccountReply.Error == CreateAccountError.UpgradeRequired && !_warnedAboutUpgrade) if (createAccountReply.Error == CreateAccountError.UpgradeRequired && !_warnedAboutUpgrade)
{ {
_chatGui.PalError(Localization.ConnectionError_OldVersion); _chatGui.PalError(Localization.ConnectionError_OldVersion);
@ -79,17 +80,17 @@ namespace Pal.Client.Net
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (configuredAccount == null) if (configuredAccount == null)
{ {
PluginLog.Warning("TryConnect: No account to login with"); _logger.LogWarning("No account to login with");
return (false, Localization.ConnectionError_CreateAccountReturnedNoId); return (false, Localization.ConnectionError_CreateAccountReturnedNoId);
} }
if (!_loginInfo.IsValid) if (!_loginInfo.IsValid)
{ {
PluginLog.Information($"TryConnect: Logging in with account id {configuredAccount.AccountId.ToPartialId()}"); _logger.LogInformation("Logging in with account id {AccountId}", configuredAccount.AccountId.ToPartialId());
LoginReply loginReply = await accountClient.LoginAsync(new LoginRequest { AccountId = configuredAccount.AccountId.ToString() }, headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken); LoginReply loginReply = await accountClient.LoginAsync(new LoginRequest { AccountId = configuredAccount.AccountId.ToString() }, headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
if (loginReply.Success) if (loginReply.Success)
{ {
PluginLog.Information($"TryConnect: Login successful with account id: {configuredAccount.AccountId.ToPartialId()}"); _logger.LogInformation("Login successful with account id: {AccountId}", configuredAccount.AccountId.ToPartialId());
_loginInfo = new LoginInfo(loginReply.AuthToken); _loginInfo = new LoginInfo(loginReply.AuthToken);
bool save = configuredAccount.EncryptIfNeeded(); bool save = configuredAccount.EncryptIfNeeded();
@ -106,7 +107,7 @@ namespace Pal.Client.Net
} }
else else
{ {
PluginLog.Error($"TryConnect: Login failed with error {loginReply.Error}"); _logger.LogError("Login failed with error {Error}", loginReply.Error);
_loginInfo = new LoginInfo(null); _loginInfo = new LoginInfo(null);
if (loginReply.Error == LoginError.InvalidAccountId) if (loginReply.Error == LoginError.InvalidAccountId)
{ {
@ -114,7 +115,7 @@ namespace Pal.Client.Net
_configurationManager.Save(_configuration); _configurationManager.Save(_configuration);
if (retry) if (retry)
{ {
PluginLog.Information("TryConnect: Attempting connection retry without account id"); _logger.LogInformation("Attempting connection retry without account id");
return await TryConnect(cancellationToken, retry: false); return await TryConnect(cancellationToken, retry: false);
} }
else else
@ -131,7 +132,7 @@ namespace Pal.Client.Net
if (!_loginInfo.IsValid) if (!_loginInfo.IsValid)
{ {
PluginLog.Error($"TryConnect: Login state is loggedIn={_loginInfo.IsLoggedIn}, expired={_loginInfo.IsExpired}"); _logger.LogError("Login state is loggedIn={LoggedIn}, expired={Expired}", _loginInfo.IsLoggedIn, _loginInfo.IsExpired);
return (false, Localization.ConnectionError_LoginReturnedNoToken); return (false, Localization.ConnectionError_LoginReturnedNoToken);
} }
@ -147,17 +148,19 @@ namespace Pal.Client.Net
public async Task<string> VerifyConnection(CancellationToken cancellationToken = default) public async Task<string> VerifyConnection(CancellationToken cancellationToken = default)
{ {
using IDisposable? logScope = _logger.BeginScope("VerifyConnection");
_warnedAboutUpgrade = false; _warnedAboutUpgrade = false;
var connectionResult = await TryConnect(cancellationToken, loggerFactory: _grpcToPluginLogLoggerFactory); var connectionResult = await TryConnect(cancellationToken, loggerFactory: _loggerFactory);
if (!connectionResult.Success) if (!connectionResult.Success)
return string.Format(Localization.ConnectionError_CouldNotConnectToServer, connectionResult.Error); return string.Format(Localization.ConnectionError_CouldNotConnectToServer, connectionResult.Error);
PluginLog.Information("VerifyConnection: Connection established, trying to verify auth token"); _logger.LogInformation("Connection established, trying to verify auth token");
var accountClient = new AccountService.AccountServiceClient(_channel); var accountClient = new AccountService.AccountServiceClient(_channel);
await accountClient.VerifyAsync(new VerifyRequest(), headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken); await accountClient.VerifyAsync(new VerifyRequest(), headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
PluginLog.Information("VerifyConnection: Verification returned no errors."); _logger.LogInformation("Verification returned no errors.");
return Localization.ConnectionSuccessful; return Localization.ConnectionSuccessful;
} }

View File

@ -3,6 +3,7 @@ using Dalamud.Logging;
using Grpc.Core; using Grpc.Core;
using System.Net.Security; using System.Net.Security;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Net namespace Pal.Client.Net
{ {
@ -40,7 +41,7 @@ namespace Pal.Client.Net
throw new InvalidOperationException(); throw new InvalidOperationException();
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.DefaultKeySet); var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.DefaultKeySet);
PluginLog.Debug($"Using client certificate {certificate.GetCertHashString()}"); _logger.LogDebug("Using client certificate {CertificateHash}", certificate.GetCertHashString());
return new SslClientAuthenticationOptions return new SslClientAuthenticationOptions
{ {
ClientCertificates = new X509CertificateCollection() ClientCertificates = new X509CertificateCollection()
@ -49,7 +50,7 @@ namespace Pal.Client.Net
}, },
}; };
#else #else
PluginLog.Debug("Not using client certificate"); _logger.LogDebug("Not using client certificate");
return null; return null;
#endif #endif
} }

View File

@ -17,9 +17,8 @@ namespace Pal.Client.Net
private readonly string _userAgent = private readonly string _userAgent =
$"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}"; $"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}";
private readonly ILoggerFactory _grpcToPluginLogLoggerFactory = LoggerFactory.Create(builder => private readonly ILoggerFactory _loggerFactory;
builder.AddProvider(new GrpcLoggerProvider()).AddFilter("Grpc", LogLevel.Trace)); private readonly ILogger<RemoteApi> _logger;
private readonly ChatGui _chatGui; private readonly ChatGui _chatGui;
private readonly ConfigurationManager _configurationManager; private readonly ConfigurationManager _configurationManager;
private readonly IPalacePalConfiguration _configuration; private readonly IPalacePalConfiguration _configuration;
@ -28,9 +27,15 @@ namespace Pal.Client.Net
private LoginInfo _loginInfo = new(null); private LoginInfo _loginInfo = new(null);
private bool _warnedAboutUpgrade; private bool _warnedAboutUpgrade;
public RemoteApi(ChatGui chatGui, ConfigurationManager configurationManager, public RemoteApi(
ILoggerFactory loggerFactory,
ILogger<RemoteApi> logger,
ChatGui chatGui,
ConfigurationManager configurationManager,
IPalacePalConfiguration configuration) IPalacePalConfiguration configuration)
{ {
_loggerFactory = loggerFactory;
_logger = logger;
_chatGui = chatGui; _chatGui = chatGui;
_configurationManager = configurationManager; _configurationManager = configurationManager;
_configuration = configuration; _configuration = configuration;
@ -38,7 +43,7 @@ namespace Pal.Client.Net
public void Dispose() public void Dispose()
{ {
PluginLog.Debug("Disposing gRPC channel"); _logger.LogDebug("Disposing gRPC channel");
_channel?.Dispose(); _channel?.Dispose();
_channel = null; _channel = null;
} }

View File

@ -13,6 +13,7 @@ using System.Numerics;
using System.Reflection; using System.Reflection;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Microsoft.Extensions.Logging;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Extensions; using Pal.Client.Extensions;
@ -22,19 +23,24 @@ namespace Pal.Client.Rendering
{ {
private const long OnTerritoryChange = -2; private const long OnTerritoryChange = -2;
private readonly ILogger<SplatoonRenderer> _logger;
private readonly DebugState _debugState; private readonly DebugState _debugState;
private readonly ClientState _clientState; private readonly ClientState _clientState;
private readonly ChatGui _chatGui; private readonly ChatGui _chatGui;
public SplatoonRenderer(DalamudPluginInterface pluginInterface, IDalamudPlugin dalamudPlugin, public SplatoonRenderer(
ILogger<SplatoonRenderer> logger,
DalamudPluginInterface pluginInterface,
IDalamudPlugin dalamudPlugin,
DebugState debugState, DebugState debugState,
ClientState clientState, ChatGui chatGui) ClientState clientState, ChatGui chatGui)
{ {
_logger = logger;
_debugState = debugState; _debugState = debugState;
_clientState = clientState; _clientState = clientState;
_chatGui = chatGui; _chatGui = chatGui;
PluginLog.Information("Initializing splatoon..."); _logger.LogInformation("Initializing splatoon...");
ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI); ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI);
} }
@ -53,7 +59,7 @@ namespace Pal.Client.Rendering
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, $"Could not create splatoon layer {layer} with {elements.Count} elements"); _logger.LogError(e, "Could not create splatoon layer {Layer} with {Count} elements", layer, elements.Count);
_debugState.SetFromException(e); _debugState.SetFromException(e);
} }
}); });
@ -67,7 +73,7 @@ namespace Pal.Client.Rendering
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, $"Could not reset splatoon layer {layer}"); _logger.LogError(e, "Could not reset splatoon layer {Layer}", layer);
} }
} }

View File

@ -1,4 +1,6 @@
using Dalamud.Logging; using System.Reflection.Metadata;
using Dalamud.Logging;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Scheduled namespace Pal.Client.Scheduled
{ {
@ -12,18 +14,25 @@ namespace Pal.Client.Scheduled
internal abstract class Handler<T> : IHandler internal abstract class Handler<T> : IHandler
where T : IQueueOnFrameworkThread where T : IQueueOnFrameworkThread
{ {
protected readonly ILogger<Handler<T>> _logger;
protected Handler(ILogger<Handler<T>> logger)
{
_logger = logger;
}
protected abstract void Run(T queued, ref bool recreateLayout, ref bool saveMarkers); protected abstract void Run(T queued, ref bool recreateLayout, ref bool saveMarkers);
public void RunIfCompatible(IQueueOnFrameworkThread queued, ref bool recreateLayout, ref bool saveMarkers) public void RunIfCompatible(IQueueOnFrameworkThread queued, ref bool recreateLayout, ref bool saveMarkers)
{ {
if (queued is T t) if (queued is T t)
{ {
PluginLog.Information($"Handling {queued.GetType()} with handler {GetType()}"); _logger.LogInformation("Handling {QueuedType}", queued.GetType());
Run(t, ref recreateLayout, ref saveMarkers); Run(t, ref recreateLayout, ref saveMarkers);
} }
else else
{ {
PluginLog.Error($"Could not use queue handler {GetType()} with type {queued.GetType()}"); _logger.LogError("Could not use queue handler {QueuedType}", queued.GetType());
} }
} }
} }

View File

@ -1,4 +1,5 @@
using Pal.Client.Configuration; using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
namespace Pal.Client.Scheduled namespace Pal.Client.Scheduled
@ -11,8 +12,9 @@ namespace Pal.Client.Scheduled
private readonly FloorService _floorService; private readonly FloorService _floorService;
private readonly TerritoryState _territoryState; private readonly TerritoryState _territoryState;
public Handler(IPalacePalConfiguration configuration, FloorService floorService, public Handler(ILogger<Handler> logger, IPalacePalConfiguration configuration, FloorService floorService,
TerritoryState territoryState) TerritoryState territoryState)
: base(logger)
{ {
_configuration = configuration; _configuration = configuration;
_floorService = floorService; _floorService = floorService;

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Logging; using Dalamud.Logging;
using Microsoft.Extensions.Logging;
using Pal.Client.Database; using Pal.Client.Database;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Extensions; using Pal.Client.Extensions;
@ -36,10 +37,12 @@ namespace Pal.Client.Scheduled
private readonly ConfigWindow _configWindow; private readonly ConfigWindow _configWindow;
public Handler( public Handler(
ILogger<Handler> logger,
ChatGui chatGui, ChatGui chatGui,
FloorService floorService, FloorService floorService,
ImportService importService, ImportService importService,
ConfigWindow configWindow) ConfigWindow configWindow)
: base(logger)
{ {
_chatGui = chatGui; _chatGui = chatGui;
_floorService = floorService; _floorService = floorService;
@ -83,14 +86,14 @@ namespace Pal.Client.Scheduled
}); });
_configWindow.UpdateLastImport(); _configWindow.UpdateLastImport();
PluginLog.Information( _logger.LogInformation(
$"Imported {import.ExportId} for {import.ImportedTraps} traps, {import.ImportedHoardCoffers} hoard coffers"); $"Imported {import.ExportId} for {import.ImportedTraps} traps, {import.ImportedHoardCoffers} hoard coffers");
_chatGui.PalMessage(string.Format(Localization.ImportCompleteStatistics, import.ImportedTraps, _chatGui.PalMessage(string.Format(Localization.ImportCompleteStatistics, import.ImportedTraps,
import.ImportedHoardCoffers)); import.ImportedHoardCoffers));
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, "Import failed"); _logger.LogError(e, "Import failed");
_chatGui.PalError(string.Format(Localization.Error_ImportFailed, e)); _chatGui.PalError(string.Format(Localization.Error_ImportFailed, e));
} }
} }
@ -99,15 +102,15 @@ namespace Pal.Client.Scheduled
{ {
if (import.Export.ExportVersion != ExportConfig.ExportVersion) if (import.Export.ExportVersion != ExportConfig.ExportVersion)
{ {
PluginLog.Error( _logger.LogError(
$"Import: Different version in export file, {import.Export.ExportVersion} != {ExportConfig.ExportVersion}"); "Import: Different version in export file, {ExportVersion} != {ConfiguredVersion}", import.Export.ExportVersion, ExportConfig.ExportVersion);
_chatGui.PalError(Localization.Error_ImportFailed_IncompatibleVersion); _chatGui.PalError(Localization.Error_ImportFailed_IncompatibleVersion);
return false; return false;
} }
if (!Guid.TryParse(import.Export.ExportId, out Guid exportId) || exportId == Guid.Empty) if (!Guid.TryParse(import.Export.ExportId, out Guid exportId) || exportId == Guid.Empty)
{ {
PluginLog.Error($"Import: Invalid export id ({import.Export.ExportId})"); _logger.LogError("Import: Invalid export id '{Id}'", import.Export.ExportId);
_chatGui.PalError(Localization.Error_ImportFailed_InvalidFile); _chatGui.PalError(Localization.Error_ImportFailed_InvalidFile);
return false; return false;
} }
@ -117,7 +120,7 @@ namespace Pal.Client.Scheduled
if (string.IsNullOrEmpty(import.Export.ServerUrl)) if (string.IsNullOrEmpty(import.Export.ServerUrl))
{ {
// If we allow for backups as import/export, this should be removed // If we allow for backups as import/export, this should be removed
PluginLog.Error("Import: No server URL"); _logger.LogError("Import: No server URL");
_chatGui.PalError(Localization.Error_ImportFailed_InvalidFile); _chatGui.PalError(Localization.Error_ImportFailed_InvalidFile);
return false; return false;
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Extensions; using Pal.Client.Extensions;
@ -22,7 +23,13 @@ namespace Pal.Client.Scheduled
private readonly TerritoryState _territoryState; private readonly TerritoryState _territoryState;
private readonly DebugState _debugState; private readonly DebugState _debugState;
public Handler(IPalacePalConfiguration configuration, FloorService floorService, TerritoryState territoryState, DebugState debugState) public Handler(
ILogger<Handler> logger,
IPalacePalConfiguration configuration,
FloorService floorService,
TerritoryState territoryState,
DebugState debugState)
: base(logger)
{ {
_configuration = configuration; _configuration = configuration;
_floorService = floorService; _floorService = floorService;

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Windows; using Pal.Client.Windows;
@ -22,7 +23,8 @@ namespace Pal.Client.Scheduled
private readonly FloorService _floorService; private readonly FloorService _floorService;
private readonly ConfigWindow _configWindow; private readonly ConfigWindow _configWindow;
public Handler(ImportService importService, FloorService floorService, ConfigWindow configWindow) public Handler(ILogger<Handler> logger, ImportService importService, FloorService floorService, ConfigWindow configWindow)
: base(logger)
{ {
_importService = importService; _importService = importService;
_floorService = floorService; _floorService = floorService;

View File

@ -19,6 +19,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Microsoft.Extensions.Logging;
using Pal.Client.Properties; using Pal.Client.Properties;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.Database; using Pal.Client.Database;
@ -31,6 +32,7 @@ namespace Pal.Client.Windows
{ {
private const string WindowId = "###PalPalaceConfig"; private const string WindowId = "###PalPalaceConfig";
private readonly ILogger<ConfigWindow> _logger;
private readonly WindowSystem _windowSystem; private readonly WindowSystem _windowSystem;
private readonly ConfigurationManager _configurationManager; private readonly ConfigurationManager _configurationManager;
private readonly IPalacePalConfiguration _configuration; private readonly IPalacePalConfiguration _configuration;
@ -60,8 +62,10 @@ namespace Pal.Client.Windows
private ImportHistory? _lastImport; private ImportHistory? _lastImport;
private CancellationTokenSource? _testConnectionCts; private CancellationTokenSource? _testConnectionCts;
private CancellationTokenSource? _lastImportCts;
public ConfigWindow( public ConfigWindow(
ILogger<ConfigWindow> logger,
WindowSystem windowSystem, WindowSystem windowSystem,
ConfigurationManager configurationManager, ConfigurationManager configurationManager,
IPalacePalConfiguration configuration, IPalacePalConfiguration configuration,
@ -75,6 +79,7 @@ namespace Pal.Client.Windows
ImportService importService) ImportService importService)
: base(WindowId) : base(WindowId)
{ {
_logger = logger;
_windowSystem = windowSystem; _windowSystem = windowSystem;
_configurationManager = configurationManager; _configurationManager = configurationManager;
_configuration = configuration; _configuration = configuration;
@ -105,6 +110,7 @@ namespace Pal.Client.Windows
public void Dispose() public void Dispose()
{ {
_windowSystem.RemoveWindow(this); _windowSystem.RemoveWindow(this);
_lastImportCts?.Cancel();
_testConnectionCts?.Cancel(); _testConnectionCts?.Cancel();
} }
@ -454,11 +460,11 @@ namespace Pal.Client.Windows
{ {
if (cts == _testConnectionCts) if (cts == _testConnectionCts)
{ {
PluginLog.Error(e, "Could not establish remote connection"); _logger.LogError(e, "Could not establish remote connection");
_connectionText = e.ToString(); _connectionText = e.ToString();
} }
else else
PluginLog.Warning(e, _logger.LogWarning(e,
"Could not establish a remote connection, but user also clicked 'test connection' again so not updating UI"); "Could not establish a remote connection, but user also clicked 'test connection' again so not updating UI");
} }
}); });
@ -476,7 +482,14 @@ namespace Pal.Client.Windows
internal void UpdateLastImport() internal void UpdateLastImport()
{ {
_lastImport = _importService.FindLast(); _lastImportCts?.Cancel();
CancellationTokenSource cts = new CancellationTokenSource();
_lastImportCts = cts;
Task.Run(async () =>
{
_lastImport = await _importService.FindLast(cts.Token);
}, cts.Token);
} }
private void DoExport(string destinationPath) private void DoExport(string destinationPath)
@ -500,7 +513,7 @@ namespace Pal.Client.Windows
} }
catch (Exception e) catch (Exception e)
{ {
PluginLog.Error(e, "Export failed"); _logger.LogError(e, "Export failed");
_chatGui.PalError($"Export failed: {e}"); _chatGui.PalError($"Export failed: {e}");
} }
}); });