diff --git a/GitVersion.yml b/GitVersion.yml index 18133f36..7744a7fe 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,5 +1,5 @@ assembly-versioning-scheme: MajorMinorPatchTag -next-version: 2.5.0 +next-version: 2.6.0 branches: master: is-release-branch: true diff --git a/identifier.sqlite b/identifier.sqlite new file mode 100644 index 00000000..e69de29b diff --git a/src/Lanceur.Core/Lanceur.Core.csproj b/src/Lanceur.Core/Lanceur.Core.csproj index cb199c82..70e06a90 100644 --- a/src/Lanceur.Core/Lanceur.Core.csproj +++ b/src/Lanceur.Core/Lanceur.Core.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Lanceur.Core/LuaScripting/Script.cs b/src/Lanceur.Core/LuaScripting/Script.cs index 28809949..64883753 100644 --- a/src/Lanceur.Core/LuaScripting/Script.cs +++ b/src/Lanceur.Core/LuaScripting/Script.cs @@ -39,12 +39,16 @@ public class Script public ScriptContext Context { get; init; } - public ScriptResult EmptyResult => new ScriptResult + #endregion Properties + + #region Methods + + public ScriptResult CloneWithoutContext() => new() { Code = Code, Context = ScriptContext.Empty }; - #endregion Properties + #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur.Core/LuaScripting/ScriptContext.cs b/src/Lanceur.Core/LuaScripting/ScriptContext.cs index e8fdb1d0..b2bb6f8d 100644 --- a/src/Lanceur.Core/LuaScripting/ScriptContext.cs +++ b/src/Lanceur.Core/LuaScripting/ScriptContext.cs @@ -5,8 +5,8 @@ public class ScriptContext #region Properties public static ScriptContext Empty => new(); - public string FileName { get; set; } - public string Parameters { get; set; } + public string FileName { get; init; } + public string Parameters { get; init; } #endregion Properties } diff --git a/src/Lanceur.Core/LuaScripting/ScriptResult.cs b/src/Lanceur.Core/LuaScripting/ScriptResult.cs index e55ebd6d..763793d2 100644 --- a/src/Lanceur.Core/LuaScripting/ScriptResult.cs +++ b/src/Lanceur.Core/LuaScripting/ScriptResult.cs @@ -5,12 +5,17 @@ public class ScriptResult : Script #region Properties public string Error { get; init; } + + #endregion Properties + + #region Methods + public override string ToString() { return $"File Name : {Context.FileName}" + $"\nParameters : {Context.Parameters}"; } - #endregion Properties + #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur.Core/Managers/IFavIconManager.cs b/src/Lanceur.Core/Managers/IFavIconManager.cs index f23ac499..2532dc3c 100644 --- a/src/Lanceur.Core/Managers/IFavIconManager.cs +++ b/src/Lanceur.Core/Managers/IFavIconManager.cs @@ -1,6 +1,4 @@ -using Lanceur.Core.Models; - -namespace Lanceur.Core.Managers +namespace Lanceur.Core.Managers { public interface IFavIconManager { diff --git a/src/Lanceur.Core/Models/AliasQueryResult.cs b/src/Lanceur.Core/Models/AliasQueryResult.cs index 2c365477..d6932786 100644 --- a/src/Lanceur.Core/Models/AliasQueryResult.cs +++ b/src/Lanceur.Core/Models/AliasQueryResult.cs @@ -59,16 +59,15 @@ public override bool IsElevated public bool IsHidden { get; set; } - public string Notes { get; set; } - - public RunAs RunAs { get; set; } = RunAs.CurrentUser; - /// /// Gets or sets a Lua script that will be executed /// when user launch an alias /// public string LuaScript { get; set; } + public string Notes { get; set; } + + public RunAs RunAs { get; set; } = RunAs.CurrentUser; public StartMode StartMode { get; set; } = StartMode.Default; /// @@ -90,8 +89,8 @@ public string Synonyms /// New synonyms added when updated /// public string SynonymsToAdd => (from n in Synonyms.SplitCsv() - where !SynonymsWhenLoaded.SplitCsv().Contains(n) - select n).ToArray().JoinCsv(); + where !SynonymsWhenLoaded.SplitCsv().Contains(n) + select n).ToArray().JoinCsv(); /// /// Synonyms present when the entity was loaded diff --git a/src/Lanceur.Core/Models/AliasQueryResultMixin.cs b/src/Lanceur.Core/Models/AliasQueryResultMixin.cs index e3c08384..6f20935b 100644 --- a/src/Lanceur.Core/Models/AliasQueryResultMixin.cs +++ b/src/Lanceur.Core/Models/AliasQueryResultMixin.cs @@ -6,6 +6,14 @@ public static class AliasQueryResultMixin { #region Methods + /// + /// Indicates whether this alias is a packaged application (i.e: UWP) + /// + /// The alias ti check + /// True if this is a packaged application; otherwise False + public static bool IsPackagedApplication(this AliasQueryResult alias) + => alias.FileName.ToLower().StartsWith("package:"); + /// /// Set first names defined in the synonyms as the name of the alias /// @@ -17,13 +25,5 @@ public static void SetName(this AliasQueryResult alias) .FirstOrDefault(); } - /// - /// Indicates whether this alias is a packaged application (i.e: UWP) - /// - /// The alias ti check - /// True if this is a packaged application; otherwise False - public static bool IsPackagedApplication(this AliasQueryResult alias) - => alias.FileName.ToLower().StartsWith("package:"); - #endregion Methods } \ No newline at end of file diff --git a/src/Lanceur.Core/Models/DisplayQueryResult.cs b/src/Lanceur.Core/Models/DisplayQueryResult.cs index 71c0ee3f..1557f083 100644 --- a/src/Lanceur.Core/Models/DisplayQueryResult.cs +++ b/src/Lanceur.Core/Models/DisplayQueryResult.cs @@ -21,6 +21,9 @@ public DisplayQueryResult(string name, string description = null, string iconKin #region Properties + public static IEnumerable NoResultFound + => SingleFromResult("No result found", iconKind: "AlertCircleOutline"); + public override string Description => _description; public override bool IsResult => false; @@ -37,9 +40,6 @@ public static IEnumerable SingleFromResult(string text, string subt }; } - public static IEnumerable NoResultFound - => SingleFromResult("No result found", iconKind: "AlertCircleOutline"); - #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur.Core/Models/PluginExecutableQueryResult.cs b/src/Lanceur.Core/Models/PluginExecutableQueryResult.cs index 9bf7cbec..e5923dc7 100644 --- a/src/Lanceur.Core/Models/PluginExecutableQueryResult.cs +++ b/src/Lanceur.Core/Models/PluginExecutableQueryResult.cs @@ -1,7 +1,7 @@ using Lanceur.Core.Plugins; using Lanceur.Core.Plugins.Models; -using Lanceur.Core.Services; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; namespace Lanceur.Core.Models { @@ -9,16 +9,16 @@ public sealed class PluginExecutableQueryResult : SelfExecutableQueryResult { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IPlugin _plugin; #endregion Fields #region Constructors - public PluginExecutableQueryResult(IPlugin plugin, IAppLoggerFactory logFactory) + public PluginExecutableQueryResult(IPlugin plugin, ILoggerFactory loggerFactory) { - _log = logFactory.GetLogger(); + _logger = loggerFactory.CreateLogger(); _plugin = plugin; Name = plugin.Name; Icon = plugin.Icon; @@ -49,7 +49,7 @@ public override async Task> ExecuteAsync(Cmdline cmdlin { if (cmdline == null || cmdline.Name.IsNullOrWhiteSpace()) { - _log.Info($"Cannot execute plugin '{Name}': the cmdline is empty."); + _logger.LogInformation("Cannot execute plugin {Name}: the cmdline is empty", Name); return NoResult; } diff --git a/src/Lanceur.Core/Models/QueryResultMixin.cs b/src/Lanceur.Core/Models/QueryResultMixin.cs index 2e6b7e37..53ae3814 100644 --- a/src/Lanceur.Core/Models/QueryResultMixin.cs +++ b/src/Lanceur.Core/Models/QueryResultMixin.cs @@ -12,7 +12,7 @@ public static class QueryResultMixin public static string GetMacroName(this AliasQueryResult @this) { if (@this is null) return string.Empty; - + var regex = new Regex("@(.*)@"); var result = regex.IsMatch(@this.FileName ?? string.Empty) ? regex.Match(@this.FileName ?? string.Empty).Groups[1].Value diff --git a/src/Lanceur.Core/Models/SessionExecutableQueryResult.cs b/src/Lanceur.Core/Models/SessionExecutableQueryResult.cs index c928f006..56d6a0c4 100644 --- a/src/Lanceur.Core/Models/SessionExecutableQueryResult.cs +++ b/src/Lanceur.Core/Models/SessionExecutableQueryResult.cs @@ -1,5 +1,5 @@ using Lanceur.Core.Repositories; -using Lanceur.Core.Services; +using Microsoft.Extensions.Logging; namespace Lanceur.Core.Models { @@ -7,7 +7,7 @@ public class SessionExecutableQueryResult : SelfExecutableQueryResult { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IDbRepository _service; #endregion Fields @@ -17,10 +17,10 @@ public class SessionExecutableQueryResult : SelfExecutableQueryResult public SessionExecutableQueryResult( string name, string description, - IAppLoggerFactory logFactory, + ILogger logger, IDbRepository service) : base(name, description) { - _log = logFactory.GetLogger(); + _logger = logger; _service = service; } @@ -30,7 +30,7 @@ public SessionExecutableQueryResult( public override Task> ExecuteAsync(Cmdline cmdline = null) { - _log.Trace($"Change to session '{Name}' with id {Id}"); + _logger.LogInformation("Change to session {Name} with id {Id}", Name, Id); _service.SetDefaultSession(Id); return NoResultAsync; } diff --git a/src/Lanceur.Core/Repositories/IDbRepository.cs b/src/Lanceur.Core/Repositories/IDbRepository.cs index 8eff4bbd..5f73181b 100644 --- a/src/Lanceur.Core/Repositories/IDbRepository.cs +++ b/src/Lanceur.Core/Repositories/IDbRepository.cs @@ -14,14 +14,6 @@ public interface IDbRepository { #region Methods - /// - /// Returns all the names that exists in the database AND in the specified list of - /// - /// The names to find in the database - /// The id of the session. If not specified, will take default session - /// - public ExistingNameResponse SelectNames(string[] names, long? idSession = null); - /// /// Get all the aliases /// @@ -147,6 +139,14 @@ public interface IDbRepository /// Resulting aliases IEnumerable SearchAliasWithAdditionalParameters(string criteria, long? idSession = null); + /// + /// Returns all the names that exists in the database AND in the specified list of + /// + /// The names to find in the database + /// The id of the session. If not specified, will take default session + /// + public ExistingNameResponse SelectNames(string[] names, long? idSession = null); + void SetDefaultSession(long idSession); /// diff --git a/src/Lanceur.Core/Requests/ExecutionRequest.cs b/src/Lanceur.Core/Requests/ExecutionRequest.cs index c5d7a7fd..403ea7ef 100644 --- a/src/Lanceur.Core/Requests/ExecutionRequest.cs +++ b/src/Lanceur.Core/Requests/ExecutionRequest.cs @@ -11,6 +11,5 @@ public class ExecutionRequest public QueryResult QueryResult { get; init; } #endregion Properties - } } \ No newline at end of file diff --git a/src/Lanceur.Core/Services/IAppLogger.cs b/src/Lanceur.Core/Services/IAppLogger.cs deleted file mode 100644 index 46699871..00000000 --- a/src/Lanceur.Core/Services/IAppLogger.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Lanceur.Core.Services -{ - public interface IAppLogger - { - #region Methods - - void Debug(string message); - - void Debug(Exception ex); - - void Error(string message, Exception ex = null); - - void Fatal(string message, Exception ex = null); - - void Info(string message); - - void Trace(string message); - - void Warning(string message, Exception ex = null); - - void Warning(Exception ex); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur.Core/Services/IAppLoggerFactory.cs b/src/Lanceur.Core/Services/IAppLoggerFactory.cs deleted file mode 100644 index 8f2cfb24..00000000 --- a/src/Lanceur.Core/Services/IAppLoggerFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Lanceur.Core.Services -{ - public interface IAppLoggerFactory - { - #region Methods - - IAppLogger GetLogger(); - - IAppLogger GetLogger(Type sourceType); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur.Core/Services/TraceLogger.cs b/src/Lanceur.Core/Services/TraceLogger.cs deleted file mode 100644 index baa2153b..00000000 --- a/src/Lanceur.Core/Services/TraceLogger.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Diagnostics; -using _Trace = System.Diagnostics.Trace; - -namespace Lanceur.Core.Services -{ - /// - /// The use of this logger is NOT recommended. It's there - /// as a fallback if dev forgot to configure a logger. - /// This LogService is a very basic and NOT optimised logger. - /// It uses and also - /// reflection to log the name of the calling method. - /// - public class TraceLogger : IAppLogger - { - #region Methods - - private static string GetCallerName() - { - var stackTrace = new StackTrace(); - var method = stackTrace.GetFrame(1).GetMethod(); - return method.Name; - } - - private static void Write(string message, Exception ex = null) - { - var name = GetCallerName(); - - _Trace.WriteLine($"[{name}] {message}{Environment.NewLine}{(ex is not null ? ex : string.Empty)}"); - } - - private static void Write(Exception ex) - { - var name = GetCallerName(); - - _Trace.WriteLine($"[{name}] {ex}"); - } - - public void Debug(string message) => Write(message); - - public void Debug(Exception ex) => Write(ex); - - public void Error(string message, Exception ex = null) => Write(message); - - public void Fatal(string message, Exception ex = null) => Write(message); - - public void Info(string message) => Write(message); - - public void Trace(string message) => Write(message); - - public void Warning(string message, Exception ex = null) => Write(message); - - public void Warning(Exception ex) => Write(ex); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs index b2f6a578..a317fad0 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs @@ -1,9 +1,10 @@ using Dapper; using Lanceur.Core.Models; -using Lanceur.Core.Services; -using Lanceur.Infra.SQLite.Entities; +using Lanceur.Infra.Logging; +using Lanceur.Infra.Sqlite.Entities; using Lanceur.Infra.SQLite.Helpers; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using System.Data.SQLite; namespace Lanceur.Infra.SQLite.DbActions @@ -27,33 +28,22 @@ update alias where id = @id;"; private readonly IDbConnectionManager _db; - private readonly IAppLogger _log; + private readonly ILogger _logger; #endregion Fields #region Constructors - public AliasDbAction(IDbConnectionManager db, IAppLoggerFactory logFactory) + public AliasDbAction(IDbConnectionManager db, ILoggerFactory logFactory) { _db = db; - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); } #endregion Constructors #region Methods - private static void CreateAdditionalParameters(long idAlias, IEnumerable parameters, SQLiteTransactionBase tx) - { - // Remove existing additional alias parameters - const string sql1 = "delete from alias_argument where id_alias = @idAlias"; - tx.Connection.Execute(sql1, new { idAlias }); - - // Create alias additional parameters - const string sql2 = "insert into alias_argument (id_alias, argument, name) values(@idAlias, @parameter, @name);"; - tx.Connection.Execute(sql2, parameters.ToEntity(idAlias)); - } - private static void UpdateName(AliasQueryResult alias, SQLiteTransactionBase tx) { //Remove all names @@ -76,7 +66,7 @@ delete from alias var cnt = _db.ExecuteMany(sql, ids); var idd = string.Join(", ", ids); - _log.Info($"Removed {cnt} row(s) from alias. Id: {idd}"); + _logger.LogInformation("Removed {Count} row(s) from alias. Id: {Idd}", cnt, idd); } private void ClearAliasArgument(params long[] ids) @@ -87,7 +77,7 @@ delete from alias_argument var cnt = _db.ExecuteMany(sql, ids); var idd = string.Join(", ", ids); - _log.Info($"Removed {cnt} row(s) from 'alias_argument'. Id: {idd}"); + _logger.LogInformation("Removed {Count} row(s) from alias_argument. Id: {IdAliases}", cnt, idd); } private void ClearAliasName(params long[] ids) @@ -98,7 +88,7 @@ delete from alias_name var cnt = _db.ExecuteMany(sql, ids); var idd = string.Join(", ", ids); - _log.Info($"Removed {cnt} row(s) from 'alias_name'. Id: {idd}"); + _logger.LogInformation("Removed {RemovedCount} row(s) from alias_name. Id: {IdAliases}", cnt, idd); } private void ClearAliasUsage(params long[] ids) @@ -109,9 +99,20 @@ delete from alias_usage var cnt = _db.ExecuteMany(sql, ids); var idd = string.Join(", ", ids); - _log.Info($"Removed {cnt} row(s) from 'alias_usage'. Id: {idd}"); + _logger.LogInformation("Removed {Count} row(s) from alias_usage. Id: {IdAliases}", cnt, idd); } + private void CreateAdditionalParameters(long idAlias, IEnumerable parameters, SQLiteTransactionBase tx) + { + const string sql1 = "delete from alias_argument where id_alias = @idAlias"; + const string sql2 = "insert into alias_argument (id_alias, argument, name) values(@idAlias, @parameter, @name);"; + + // Remove existing additional alias parameters + tx.Connection.Execute(sql1, new { idAlias }); + + // Create alias additional parameters + tx.Connection.Execute(sql2, parameters.ToEntity(idAlias)); + } private void CreateAdditionalParameters(AliasQueryResult alias, SQLiteTransaction tx) => CreateAdditionalParameters(alias.Id, alias.AdditionalParameters, tx); @@ -169,6 +170,7 @@ insert into alias ( @isHidden ); select last_insert_rowid() from alias limit 1;"; + var param = new { Arguments = alias.Parameters, @@ -186,6 +188,8 @@ insert into alias ( var csv = alias.Synonyms.SplitCsv(); var additionalParameters = alias.AdditionalParameters; + + using var _ = _logger.BeginSingleScope("SqlCreateAlias", sqlAlias); var id = _db.WithinTransaction(tx => { var id = tx.Connection.ExecuteScalar(sqlAlias, param); @@ -365,6 +369,7 @@ an.name in @names public long Update(AliasQueryResult alias) => _db.WithinTransaction(tx => { + using var _ = _logger.BeginSingleScope("Sql", UpdateAliasSql); tx.Connection.Execute(UpdateAliasSql, new { alias.Parameters, diff --git a/src/Lanceur.Infra.SQLite/DbActions/AliasSearchDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/AliasSearchDbAction.cs index cb4c7b0a..085f5bc0 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/AliasSearchDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/AliasSearchDbAction.cs @@ -1,6 +1,8 @@ using Dapper; using Lanceur.Core.Models; using Lanceur.Core.Services; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite.DbActions; @@ -9,17 +11,17 @@ public class AliasSearchDbAction #region Fields private readonly IDbConnectionManager _db; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly MacroDbAction _macroManager; #endregion Fields #region Constructors - public AliasSearchDbAction(IDbConnectionManager db, IAppLoggerFactory logFactory, IConvertionService converter) + public AliasSearchDbAction(IDbConnectionManager db, ILoggerFactory logFactory, IConvertionService converter) { _db = db; - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); _macroManager = new(db, logFactory, converter); } diff --git a/src/Lanceur.Infra.SQLite/DbActions/GetAllAliasDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/GetAllAliasDbAction.cs index 8d9d4080..243756ef 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/GetAllAliasDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/GetAllAliasDbAction.cs @@ -1,6 +1,7 @@ using Dapper; using Lanceur.Core.Models; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite.DbActions; @@ -9,16 +10,16 @@ public class GetAllAliasDbAction #region Fields private readonly IDbConnectionManager _db; - private readonly IAppLogger _log; + private readonly ILogger _logger; #endregion Fields #region Constructors - public GetAllAliasDbAction(IDbConnectionManager db, IAppLoggerFactory logFactory) + public GetAllAliasDbAction(IDbConnectionManager db, ILoggerFactory logFactory) { _db = db; - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); } #endregion Constructors diff --git a/src/Lanceur.Infra.SQLite/DbActions/MacroDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/MacroDbAction.cs index 13443783..d07e8a69 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/MacroDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/MacroDbAction.cs @@ -1,5 +1,7 @@ using Lanceur.Core.Models; using Lanceur.Core.Services; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite.DbActions { @@ -9,16 +11,18 @@ internal class MacroDbAction private readonly IConvertionService _converter; private readonly IDbConnectionManager _db; - private readonly IAppLoggerFactory _log; + private readonly ILogger _logger; + private readonly ILoggerFactory _loggerFactory; #endregion Fields #region Constructors - public MacroDbAction(IDbConnectionManager db, IAppLoggerFactory log, IConvertionService converter) + public MacroDbAction(IDbConnectionManager db, ILoggerFactory loggerFactory, IConvertionService converter) { _db = db; - _log = log; + _loggerFactory = loggerFactory; + _logger = loggerFactory.CreateLogger(); _converter = converter; } @@ -35,18 +39,24 @@ public MacroDbAction(IDbConnectionManager db, IAppLoggerFactory log, IConvertion /// The hydrated or private AliasQueryResult Hydrate(AliasQueryResult item) { + _logger.BeginSingleScope("AliasToHydrate", item); if (!item.IsComposite()) { return item; } - var action = new AliasDbAction(_db, _log); + var action = new AliasDbAction(_db, _loggerFactory); var subAliases = new List(); - int delay = 0; + var delay = 0; foreach (var name in item?.Parameters?.Split("@") ?? Array.Empty()) { if (name == string.Empty) { delay++; } else { var alias = action.GetExact(name); + if (alias is null) + { + _logger.LogWarning("Impossible to create composite alias {AliasName}. Check all the items of the composite exists in the database", name); + continue; + } alias.Delay = delay; subAliases.Add(alias); @@ -66,7 +76,7 @@ private AliasQueryResult Hydrate(AliasQueryResult item) /// The collection with all element that are upgradable /// to composite, upgraded /// - public IEnumerable UpgradeToComposite(IEnumerable collection) + public IEnumerable UpgradeToComposite(IEnumerable collection) => collection.Select(Hydrate).ToList(); #endregion Methods diff --git a/src/Lanceur.Infra.SQLite/DbActions/SetUsageDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/SetUsageDbAction.cs index 5d50827c..5cfc4fa9 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/SetUsageDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/SetUsageDbAction.cs @@ -1,6 +1,7 @@ using Dapper; using Lanceur.Core.Models; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite.DbActions { @@ -10,18 +11,18 @@ public class SetUsageDbAction private readonly AliasDbAction _aliasDbAction; private readonly IDbConnectionManager _db; - private readonly IAppLogger _log; + private readonly ILogger _logger; #endregion Fields #region Constructors - public SetUsageDbAction(IDbConnectionManager db, IAppLoggerFactory logFactory) + public SetUsageDbAction(IDbConnectionManager db, ILoggerFactory logFactory) { _db = db; - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); - _aliasDbAction = new AliasDbAction(db, logFactory); + _aliasDbAction = new(db, logFactory); } #endregion Constructors diff --git a/src/Lanceur.Infra.SQLite/Entities/AdditionalParameterMixin.cs b/src/Lanceur.Infra.SQLite/Entities/AdditionalParameterMixin.cs index 5b6d78a7..3eaf78d4 100644 --- a/src/Lanceur.Infra.SQLite/Entities/AdditionalParameterMixin.cs +++ b/src/Lanceur.Infra.SQLite/Entities/AdditionalParameterMixin.cs @@ -1,6 +1,7 @@ using Lanceur.Core.Models; +using Lanceur.Infra.SQLite.Entities; -namespace Lanceur.Infra.SQLite.Entities; +namespace Lanceur.Infra.Sqlite.Entities; public static class AdditionalParameterMixin { diff --git a/src/Lanceur.Infra.SQLite/SQLiteDataDoctorRepository.cs b/src/Lanceur.Infra.SQLite/SQLiteDataDoctorRepository.cs index 5e9a12ce..9ccf134a 100644 --- a/src/Lanceur.Infra.SQLite/SQLiteDataDoctorRepository.cs +++ b/src/Lanceur.Infra.SQLite/SQLiteDataDoctorRepository.cs @@ -1,8 +1,8 @@ using Dapper; using Lanceur.Core.Models; using Lanceur.Core.Repositories; -using Lanceur.Core.Services; using Lanceur.Infra.SQLite.DbActions; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite; @@ -18,7 +18,7 @@ public class SQLiteDataDoctorRepository : SQLiteRepositoryBase, IDataDoctorRepos public SQLiteDataDoctorRepository( IDbConnectionManager manager, - IAppLoggerFactory logFactory) : base(manager) => _dbAction = new(DB, logFactory); + ILoggerFactory logFactory) : base(manager) => _dbAction = new(DB, logFactory); #endregion Constructors diff --git a/src/Lanceur.Infra.SQLite/SQLiteMultiConnectionManager.cs b/src/Lanceur.Infra.SQLite/SQLiteMultiConnectionManager.cs index 48f06a32..f4558147 100644 --- a/src/Lanceur.Infra.SQLite/SQLiteMultiConnectionManager.cs +++ b/src/Lanceur.Infra.SQLite/SQLiteMultiConnectionManager.cs @@ -7,11 +7,26 @@ public sealed class SQLiteMultiConnectionManager : IDbConnectionManager { #region Fields + private static readonly object Locker = new(); private readonly string _connectionString; private SQLiteConnection _currentConnection; - private static readonly object Locker = new (); - private SQLiteConnection GetConnection(bool renewConnection = true) + #endregion Fields + + #region Constructors + + public SQLiteMultiConnectionManager(SQLiteConnection connection) + { + _connectionString = + connection?.ConnectionString + ?? throw new ArgumentNullException(nameof(connection), "Cannot create a connection scope with an empty connection (NULL)."); + } + + #endregion Constructors + + #region Methods + + private SQLiteConnection GetConnection(bool renewConnection = true) { lock (Locker) { @@ -28,20 +43,6 @@ private SQLiteConnection GetConnection(bool renewConnection = true) return _currentConnection; } } - #endregion Fields - - #region Constructors - - public SQLiteMultiConnectionManager(SQLiteConnection connection) - { - _connectionString = - connection?.ConnectionString - ?? throw new ArgumentNullException(nameof(connection), "Cannot create a connection scope with an empty connection (NULL)."); - } - - #endregion Constructors - - #region Methods public static implicit operator SQLiteConnection(SQLiteMultiConnectionManager manager) => manager.GetConnection(renewConnection: false); @@ -63,7 +64,7 @@ public TReturn WithinTransaction(Func actio { using var conn = GetConnection(); if (conn.State != ConnectionState.Open) conn.Open(); - + using var tx = conn.BeginTransaction(IsolationLevel.ReadCommitted); try { diff --git a/src/Lanceur.Infra.SQLite/SQLiteUpdater.cs b/src/Lanceur.Infra.SQLite/SQLiteUpdater.cs index 10995f81..f2604804 100644 --- a/src/Lanceur.Infra.SQLite/SQLiteUpdater.cs +++ b/src/Lanceur.Infra.SQLite/SQLiteUpdater.cs @@ -1,6 +1,7 @@ using Lanceur.Core.Managers; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.SQLite { @@ -8,7 +9,7 @@ public class SQLiteUpdater { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IDataStoreUpdateManager _updater; private readonly IDataStoreVersionManager _versionManager; @@ -18,12 +19,12 @@ public class SQLiteUpdater public SQLiteUpdater( IDataStoreVersionManager versionManager, - IAppLoggerFactory logService, + ILoggerFactory logService, IDataStoreUpdateManager updater ) { _versionManager = versionManager; - _log = logService.GetLogger(); + _logger = logService.GetLogger(); _updater = updater; } @@ -43,7 +44,7 @@ public void Update(string cString) if (!File.Exists(dbPath)) { CreateDirectory(dbPath); - _log.Warning($"Creating a new database in '{dbPath}'"); + _logger.LogWarning("Creating a new database in {DbPath}", dbPath); _updater.UpdateFromScratch(); _updater.SetLatestVersion(); } @@ -54,11 +55,11 @@ public void Update(string cString) if (_versionManager.IsUpToDate(latestVer) == false) { - _log.Warning($"Database V.{currentVer} is out of date. Updating to V.{latestVer}"); + _logger.LogWarning("Database V.{CurrentVer} is out of date. Updating to V.{LatestVer}", currentVer, latestVer); _updater.UpdateFrom(currentVer); _updater.SetLatestVersion(); } - else { _log.Info($"Database V.{currentVer} is up to date. Latest script version is V.{latestVer}"); } + else { _logger.LogInformation("Database V.{CurrentVer} is up to date. Latest script version is V.{LatestVer}", currentVer, latestVer); } } } diff --git a/src/Lanceur.Infra.SQLite/SQLiteAppConfigRepository.cs b/src/Lanceur.Infra.SQLite/SqliteAppConfigRepository.cs similarity index 100% rename from src/Lanceur.Infra.SQLite/SQLiteAppConfigRepository.cs rename to src/Lanceur.Infra.SQLite/SqliteAppConfigRepository.cs diff --git a/src/Lanceur.Infra.SQLite/SQLiteRepository.cs b/src/Lanceur.Infra.SQLite/SqliteRepository.cs similarity index 93% rename from src/Lanceur.Infra.SQLite/SQLiteRepository.cs rename to src/Lanceur.Infra.SQLite/SqliteRepository.cs index 3216393d..6c8f5621 100644 --- a/src/Lanceur.Infra.SQLite/SQLiteRepository.cs +++ b/src/Lanceur.Infra.SQLite/SqliteRepository.cs @@ -2,8 +2,10 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.Infra.SQLite.DbActions; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using System.Text.RegularExpressions; namespace Lanceur.Infra.SQLite; @@ -16,7 +18,7 @@ public class SQLiteRepository : SQLiteRepositoryBase, IDbRepository private readonly AliasSearchDbAction _aliasSearchDbAction; private readonly IConvertionService _converter; private readonly GetAllAliasDbAction _getAllAliasDbAction; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly SetUsageDbAction _setUsageDbAction; #endregion Fields @@ -25,13 +27,13 @@ public class SQLiteRepository : SQLiteRepositoryBase, IDbRepository public SQLiteRepository( IDbConnectionManager manager, - IAppLoggerFactory logFactory, + ILoggerFactory logFactory, IConvertionService converter) : base(manager) { ArgumentNullException.ThrowIfNull(logFactory); ArgumentNullException.ThrowIfNull(converter); - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); _converter = converter; _aliasDbAction = new(manager, logFactory); _getAllAliasDbAction = new(manager, logFactory); @@ -43,13 +45,6 @@ public SQLiteRepository( #region Methods - /// - public ExistingNameResponse SelectNames(string[] names, long? idSession = null) - { - idSession ??= GetDefaultSessionId(); - return _aliasDbAction.SelectNames(names, idSession.Value); - } - /// /// Returns all the alias of the specified session from the repository. /// If no session is specified, it returns all the alias. @@ -265,14 +260,14 @@ public IEnumerable RefreshUsage(IEnumerable result) => public void Remove(IEnumerable doubloons) { var selectableAliasQueryResults = doubloons as SelectableAliasQueryResult[] ?? doubloons.ToArray(); - _log.Info($"Removing {selectableAliasQueryResults.Length} alias(es)"); + _logger.LogInformation("Removing {Length} alias(es)", selectableAliasQueryResults.Length); _aliasDbAction.Remove(selectableAliasQueryResults); } /// public void Remove(Session session) { - _log.Info($"Removes session with name '{session.Name}'"); + _logger.LogInformation("Removes session with name {Name}. Session: {@Session}", session.Name, session); var action = new SessionDbAction(DB); action.Remove(session); } @@ -295,17 +290,18 @@ public void SaveOrUpdate(ref AliasQueryResult alias, long? idSession = null) ArgumentNullException.ThrowIfNull(alias.Synonyms, nameof(alias.Synonyms)); ArgumentNullException.ThrowIfNull(alias.Id, nameof(alias.Id)); + using var _ = _logger.BeginSingleScope("UpdatedAlias", alias); idSession ??= GetDefaultSessionId(); switch (alias.Id) { case 0 when !_aliasDbAction.SelectNames(alias, idSession.Value): _aliasDbAction.Create(ref alias, idSession.Value); - _log.Info($"Created new alias. (Id: {alias.Id})"); + _logger.LogInformation("Created new alias {AliasName}", alias.Name); break; case > 0: - _log.Info($"Updating alias. (Id: {alias.Id})"); + _logger.LogInformation("Updating alias {AliasName}", alias.Name); _aliasDbAction.Update(alias); break; } @@ -327,6 +323,13 @@ public IEnumerable SearchAliasWithAdditionalParameters(string return _aliasSearchDbAction.SearchAliasWithAdditionalParameters(criteria, idSession.Value); } + /// + public ExistingNameResponse SelectNames(string[] names, long? idSession = null) + { + idSession ??= GetDefaultSessionId(); + return _aliasDbAction.SelectNames(names, idSession.Value); + } + public void SetDefaultSession(long idSession) { var sql = @" @@ -342,13 +345,13 @@ public void SetUsage(QueryResult alias) { if (alias is null) { - _log.Info("Impossible to set usage: alias is null.;"); + _logger.LogInformation("Impossible to set usage: alias is null"); return; } if (alias.Name.IsNullOrEmpty()) { - _log.Info("Impossible to set usage: alias name is empty."); + _logger.LogInformation("Impossible to set usage: alias name is empty. Alias: {@Alias}", alias); return; } diff --git a/src/Lanceur.Infra.SQLite/SQLiteSingleConnectionManager.cs b/src/Lanceur.Infra.SQLite/SqliteSingleConnectionManager.cs similarity index 100% rename from src/Lanceur.Infra.SQLite/SQLiteSingleConnectionManager.cs rename to src/Lanceur.Infra.SQLite/SqliteSingleConnectionManager.cs diff --git a/src/Lanceur.Infra.Win32/Images/ThumbnailMixin.cs b/src/Lanceur.Infra.Win32/Images/ThumbnailMixin.cs index e518e9d1..2ab84a8a 100644 --- a/src/Lanceur.Infra.Win32/Images/ThumbnailMixin.cs +++ b/src/Lanceur.Infra.Win32/Images/ThumbnailMixin.cs @@ -24,7 +24,7 @@ public static class ThumbnailMixin public static void CopyToImageRepository(this ImageSource imageSource, string fileName) { var destination = fileName.ToAbsolutePath(); - + lock (Locker) { if (File.Exists(destination)) return; @@ -48,7 +48,7 @@ public static void CopyToImageRepository(this ImageSource imageSource, string fi public static void CopyToImageRepository(this string imageSource, string fileName) { var destination = fileName.ToAbsolutePath(); - + lock (Locker) { if (File.Exists(destination)) return; diff --git a/src/Lanceur.Infra.Win32/PackagedApp/PackageMixin.cs b/src/Lanceur.Infra.Win32/PackagedApp/PackageMixin.cs index 94c0bec0..987d668d 100644 --- a/src/Lanceur.Infra.Win32/PackagedApp/PackageMixin.cs +++ b/src/Lanceur.Infra.Win32/PackagedApp/PackageMixin.cs @@ -8,26 +8,13 @@ public static class PackageMixin #region Fields private static readonly ConcurrentDictionary CacheAppUser = new(); - + private static readonly ConcurrentDictionary CacheIsAppUser = new(); #endregion Fields #region Methods - public static bool IsAppUserModelId(this Package entry, string fileName) - { - var key = $"{fileName}-{entry.Id.FullName}"; - if (CacheIsAppUser.TryGetValue(key, out var value)) return value; - - var result = entry.GetAppListEntries() - .Where(e => !string.IsNullOrEmpty(e.AppUserModelId)) - .Select(e => e.AppUserModelId) - .FirstOrDefault(e => !string.IsNullOrEmpty(e) && e == fileName); - CacheIsAppUser[key] = result is not null; - - return CacheIsAppUser[key]; - } public static string GetAppUserModelId(this Package entry) { var key = entry.Id.FullName; @@ -43,5 +30,19 @@ public static string GetAppUserModelId(this Package entry) return CacheAppUser[key]; } + public static bool IsAppUserModelId(this Package entry, string fileName) + { + var key = $"{fileName}-{entry.Id.FullName}"; + if (CacheIsAppUser.TryGetValue(key, out var value)) return value; + + var result = entry.GetAppListEntries() + .Where(e => !string.IsNullOrEmpty(e.AppUserModelId)) + .Select(e => e.AppUserModelId) + .FirstOrDefault(e => !string.IsNullOrEmpty(e) && e == fileName); + CacheIsAppUser[key] = result is not null; + + return CacheIsAppUser[key]; + } + #endregion Methods } \ No newline at end of file diff --git a/src/Lanceur.Infra.Win32/PackagedApp/PackagedAppSearchService.cs b/src/Lanceur.Infra.Win32/PackagedApp/PackagedAppSearchService.cs index 7d4a2897..8de2b20f 100644 --- a/src/Lanceur.Infra.Win32/PackagedApp/PackagedAppSearchService.cs +++ b/src/Lanceur.Infra.Win32/PackagedApp/PackagedAppSearchService.cs @@ -12,18 +12,18 @@ public class PackagedAppSearchService : AbstractPackagedAppSearchService, IPacka fileName = fileName.Replace("package:", ""); var installedDir = Path.GetDirectoryName(fileName); - return GetUserPackages().AsParallel() + return GetUserPackages().AsParallel() .Where(p => p is { IsFramework: false, IsDevelopmentMode: false } && ( - p.InstalledLocation.Path == installedDir + p.InstalledLocation.Path == installedDir || p.IsAppUserModelId(fileName))) .Select(p => new Core.Models.PackagedApp { - AppUserModelId = p.GetAppUserModelId(), + AppUserModelId = p.GetAppUserModelId(), InstalledLocation = p.InstalledLocation.Path, - Logo = p.Logo, - Description = p.Description, - DisplayName = p.DisplayName + Logo = p.Logo, + Description = p.Description, + DisplayName = p.DisplayName }) .Where(e => !string.IsNullOrEmpty(e.AppUserModelId)) .ToArray(); diff --git a/src/Lanceur.Infra.Win32/Restart/AppRestart.cs b/src/Lanceur.Infra.Win32/Restart/AppRestart.cs index cbf74fdc..09ba12f6 100644 --- a/src/Lanceur.Infra.Win32/Restart/AppRestart.cs +++ b/src/Lanceur.Infra.Win32/Restart/AppRestart.cs @@ -1,6 +1,6 @@ -using System.Reflection; +using Lanceur.SharedKernel.Utils; +using System.Reflection; using System.Windows; -using Lanceur.SharedKernel.Utils; namespace Lanceur.Infra.Win32.Restart { diff --git a/src/Lanceur.Infra.Win32/Thumbnails/ImageRepositoryMixin.cs b/src/Lanceur.Infra.Win32/Thumbnails/ImageRepositoryMixin.cs index 5567be2e..7a7ceff5 100644 --- a/src/Lanceur.Infra.Win32/Thumbnails/ImageRepositoryMixin.cs +++ b/src/Lanceur.Infra.Win32/Thumbnails/ImageRepositoryMixin.cs @@ -12,20 +12,21 @@ internal static class ImageRepositoryMixin #region Methods + public static string GetKeyForFavIcon(this string address) + { + ArgumentNullException.ThrowIfNull(address); + return Uri.TryCreate(address, new UriCreationOptions(), out _) + ? $"{AppPaths.FaviconPrefix}{new Uri(address).Host}" + : string.Empty; + } + public static bool IsUrl(this string address) { var result = Uri.TryCreate(address, new UriCreationOptions(), out var uri) && SupportedSchemes.Contains(uri.Scheme); return result; - - } - public static string GetKeyForFavIcon(this string address) - { - ArgumentNullException.ThrowIfNull(address); - return Uri.TryCreate(address, new UriCreationOptions(), out _) - ? $"{AppPaths.FaviconPrefix}{new Uri(address).Host}" - : string.Empty; } + #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailLoader.cs b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailLoader.cs index 48ee5afa..9d2fb2eb 100644 --- a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailLoader.cs +++ b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailLoader.cs @@ -1,7 +1,8 @@ -using System.IO; -using System.Windows.Media; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using Splat; +using System.IO; +using System.Windows.Media; namespace Lanceur.Infra.Win32.Thumbnails { @@ -10,7 +11,8 @@ internal static class ThumbnailLoader #region Fields private const int ThumbnailSize = 64; - private static readonly IAppLoggerFactory AppLogFactory = Locator.Current.GetService()!; + private static readonly Microsoft.Extensions.Logging.ILogger _logger; + private static readonly ILoggerFactory AppLogFactory = Locator.Current.GetService()!; private static readonly Dictionary Cache = new(); private static readonly string[] ImageExtensions = @@ -26,6 +28,16 @@ internal static class ThumbnailLoader #endregion Fields + #region Constructors + + static ThumbnailLoader() + { + var factory = Locator.Current.GetService(); + _logger = factory.GetLogger(typeof(ThumbnailLoader)); + } + + #endregion Constructors + #region Enums private enum ImageType @@ -51,6 +63,7 @@ private static ImageSource GetThumbnail(string path, ThumbnailOptions options) options ); } + public static ImageSource? GetThumbnail(string path) { ImageSource? image = null; @@ -88,7 +101,7 @@ private static ImageSource GetThumbnail(string path, ThumbnailOptions options) } catch (Exception ex) { - AppLogFactory!.GetLogger(typeof(ThumbnailLoader)).Warning($"Failed to extract thumbnail for {path}", ex); + _logger.LogWarning(ex, "Failed to extract thumbnail for {Path}", path); } //Return the value event if null; diff --git a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailManager.cs b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailManager.cs index 60ff0fda..773c64ed 100644 --- a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailManager.cs +++ b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailManager.cs @@ -1,9 +1,10 @@ -using Lanceur.Core.Managers; +using Lanceur.Core.Decorators; +using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Repositories; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.SharedKernel.Utils; -using Lanceur.Core.Decorators; +using Microsoft.Extensions.Logging; namespace Lanceur.Infra.Win32.Thumbnails { @@ -12,7 +13,7 @@ public class ThumbnailManager : IThumbnailManager #region Fields private readonly IDbRepository _dbRepository; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IThumbnailRefresher _thumbnailRefresher; #endregion Fields @@ -20,13 +21,13 @@ public class ThumbnailManager : IThumbnailManager #region Constructors public ThumbnailManager( - IAppLoggerFactory loggerFactory, + ILoggerFactory loggerFactory, IDbRepository dbRepository, IThumbnailRefresher thumbnailRefresher) { _dbRepository = dbRepository; _thumbnailRefresher = thumbnailRefresher; - _log = loggerFactory.GetLogger(); + _logger = loggerFactory.GetLogger(); } #endregion Constructors @@ -46,7 +47,7 @@ public async Task RefreshThumbnailsAsync(IEnumerable results) var queries = EntityDecorator.FromEnumerable(results) .ToArray(); - using var m = TimePiece.Measure(this, m => _log.Info(m)); + using var m = TimePiece.Measure(this, (msg, @params) => _logger.LogTrace(msg, @params)); try { await Task.Run(() => Parallel.ForEach(queries, _thumbnailRefresher.RefreshCurrentThumbnail)); @@ -62,7 +63,7 @@ public async Task RefreshThumbnailsAsync(IEnumerable results) } catch (Exception ex) { - _log.Warning($"An error occured during the refresh of the icons. ('{ex.Message}')", ex); + _logger.LogWarning(ex, "An error occured during the refresh of the icons"); } } diff --git a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailRefresher.cs b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailRefresher.cs index e2b40535..0b93f898 100644 --- a/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailRefresher.cs +++ b/src/Lanceur.Infra.Win32/Thumbnails/ThumbnailRefresher.cs @@ -1,10 +1,12 @@ -using System.IO; using Lanceur.Core.Decorators; using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.Infra.Win32.Images; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; +using System.IO; namespace Lanceur.Infra.Win32.Thumbnails; @@ -14,18 +16,18 @@ public class ThumbnailRefresher : IThumbnailRefresher private const string WebIcon = "Web"; private readonly IFavIconManager _favIconManager; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IPackagedAppSearchService _searchService; #endregion Fields #region Constructors - public ThumbnailRefresher(IAppLoggerFactory loggerFactory, IPackagedAppSearchService searchService, IFavIconManager favIconManager) + public ThumbnailRefresher(ILoggerFactory loggerFactory, IPackagedAppSearchService searchService, IFavIconManager favIconManager) { - _searchService = searchService; + _searchService = searchService; _favIconManager = favIconManager; - _log = loggerFactory.GetLogger(); + _logger = loggerFactory.GetLogger(); } #endregion Constructors @@ -38,7 +40,8 @@ public void RefreshCurrentThumbnail(EntityDecorator query) if (alias.FileName.IsNullOrEmpty()) return; if (File.Exists(alias.Thumbnail) || alias.Icon == WebIcon) { - _log.Trace($"A thumbnail already exists for '{alias.Name}'. Thumbnail: '{alias.Thumbnail ?? WebIcon}'"); + var thumbnail = alias.Thumbnail ?? WebIcon; + _logger.LogTrace("A thumbnail already exists for {Name}. Thumbnail: {Thumbnail}", alias.Name, thumbnail); return; } if (alias.IsPackagedApplication()) @@ -52,7 +55,7 @@ public void RefreshCurrentThumbnail(EntityDecorator query) } alias.Thumbnail.CopyToImageRepository(alias.FileName); - _log.Trace($"Retrieved thumbnail for packaged app '{alias.Name}'. Thumbnail: '{alias.Thumbnail}'"); + _logger.LogTrace("Retrieved thumbnail for packaged application {Name}. Thumbnail: {Thumbnail}", alias.Name, alias.Thumbnail); return; } @@ -63,7 +66,7 @@ public void RefreshCurrentThumbnail(EntityDecorator query) imageSource.CopyToImageRepository(file.Name); alias.Thumbnail = file.Name.ToAbsolutePath(); query.Soil(); - _log.Trace($"Retrieved thumbnail for win32 application'{alias.Name}'. Thumbnail: '{alias.Thumbnail}'"); + _logger.LogTrace("Retrieved thumbnail for win32 application {Name}. Thumbnail: {Thumbnail}", alias.Name, alias.Thumbnail); return; } @@ -80,11 +83,11 @@ public void RefreshCurrentThumbnail(EntityDecorator query) return; } - alias.Icon = WebIcon; + alias.Icon = WebIcon; alias.Thumbnail = favicon; _ = _favIconManager.RetrieveFaviconAsync(alias.FileName); // Fire & forget favicon retrieving - _log.Trace($"Retrieved favicon for alias '{alias.Name}'. Favicon '{alias.FileName}'"); + _logger.LogTrace("Retrieved favicon for alias {Name}. Favicon {FileName}", alias.Name, alias.FileName); } #endregion Methods diff --git a/src/Lanceur.Infra.Win32/Thumbnails/WindowsThumbnailProvider.cs b/src/Lanceur.Infra.Win32/Thumbnails/WindowsThumbnailProvider.cs index 0eb43b72..5c08e18d 100644 --- a/src/Lanceur.Infra.Win32/Thumbnails/WindowsThumbnailProvider.cs +++ b/src/Lanceur.Infra.Win32/Thumbnails/WindowsThumbnailProvider.cs @@ -150,8 +150,8 @@ public static BitmapSource GetThumbnail(string fileName, int width, int height, try { return Imaging.CreateBitmapSourceFromHBitmap( - hBitmap, - IntPtr.Zero, + hBitmap, + IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() ); diff --git a/src/Lanceur.Infra.Win32/Utils/Coordinate.cs b/src/Lanceur.Infra.Win32/Utils/Coordinate.cs index f42cb792..079b603a 100644 --- a/src/Lanceur.Infra.Win32/Utils/Coordinate.cs +++ b/src/Lanceur.Infra.Win32/Utils/Coordinate.cs @@ -1,6 +1,4 @@ -using System.Windows.Navigation; - -namespace Lanceur.Infra.Win32.Utils +namespace Lanceur.Infra.Win32.Utils { public class Coordinate { diff --git a/src/Lanceur.Infra/Constants/AppPaths.cs b/src/Lanceur.Infra/Constants/AppPaths.cs index a389ef31..d3b5ebb4 100644 --- a/src/Lanceur.Infra/Constants/AppPaths.cs +++ b/src/Lanceur.Infra/Constants/AppPaths.cs @@ -4,10 +4,19 @@ namespace Lanceur.Infra.Constants; public static class AppPaths { - public static string Settings => @"%appdata%\probel\lanceur2\settings.json".ExpandPath(); + #region Fields + + public const string FaviconPrefix = "favicon_"; + + #endregion Fields + + #region Properties + + public static string DefaultDbPath => @"%appdata%\probel\lanceur2\data.sqlite".ExpandPath(); + public static string ImageRepository => @"%appdata%\probel\lanceur2\thumbnails".ExpandPath(); + public static string LogFilePath => @"%appdata%\probel\lanceur2\logs\probel-lanceur..clef".ExpandPath(); public static string PluginUninstallLogs => @"%appdata%\probel\lanceur2\.plugin-uninstall".ExpandPath(); - public static string DefaultDbPath => @"%appdata%\probel\lanceur2\data.sqlite".ExpandPath(); - public static string ImageRepository => @"%appdata%\probel\lanceur2\thumbnails".ExpandPath(); - - public const string FaviconPrefix = "favicon_"; + public static string Settings => @"%appdata%\probel\lanceur2\settings.json".ExpandPath(); + + #endregion Properties } \ No newline at end of file diff --git a/src/Lanceur.Infra/Lanceur.Infra.csproj b/src/Lanceur.Infra/Lanceur.Infra.csproj index 798ab5a0..f8a7935e 100644 --- a/src/Lanceur.Infra/Lanceur.Infra.csproj +++ b/src/Lanceur.Infra/Lanceur.Infra.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Lanceur.Infra/Logging/LogScope.cs b/src/Lanceur.Infra/Logging/LogScope.cs new file mode 100644 index 00000000..774b61d5 --- /dev/null +++ b/src/Lanceur.Infra/Logging/LogScope.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Logging; + +namespace Lanceur.Infra.Logging; + +public class LogScope +{ + #region Fields + + private readonly ILogger _logger; + private readonly Dictionary _scope = new(); + + #endregion Fields + + #region Constructors + + public LogScope(ILogger logger) + { + _logger = logger; + } + + #endregion Constructors + + #region Methods + + public LogScope Add(string key, object value) + { + _scope.Add(key, value); + return this; + } + + public LogScope AddDestructured(string key, object value) + { + if (!key.StartsWith('@')) { key = $"@{key}"; } + return Add(key, value); + } + + public IDisposable BeginScope() => _logger.BeginScope(_scope); + + #endregion Methods +} \ No newline at end of file diff --git a/src/Lanceur.Infra/Logging/LoggerFactoryMixin.cs b/src/Lanceur.Infra/Logging/LoggerFactoryMixin.cs new file mode 100644 index 00000000..819ad7ab --- /dev/null +++ b/src/Lanceur.Infra/Logging/LoggerFactoryMixin.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Logging; +using Splat; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Lanceur.Infra.Logging; + +public static class LoggerFactoryMixin +{ + #region Methods + + public static ILogger GetLogger(this ILoggerFactory loggerFactory, Type type) + { + var factory = loggerFactory ?? Locator.Current.GetService(); + return factory?.CreateLogger(type) ?? new TraceLogger(); + } + + public static ILogger GetLogger(this ILoggerFactory loggerFactory) + { + var factory = loggerFactory ?? Locator.Current.GetService(); + return factory?.CreateLogger() ?? new TraceLogger(); + } + + #endregion Methods +} \ No newline at end of file diff --git a/src/Lanceur.Infra/Logging/LoggerMixin.cs b/src/Lanceur.Infra/Logging/LoggerMixin.cs new file mode 100644 index 00000000..95eb2809 --- /dev/null +++ b/src/Lanceur.Infra/Logging/LoggerMixin.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Logging; + +namespace Lanceur.Infra.Logging; + +public static class LoggerMixin +{ + #region Methods + + public static IDisposable BeginSingleScope(this ILogger logger, string key, object value) + { + if (!key.StartsWith('@')) { key = $"@{key}"; } + return new LogScope(logger).Add(key, value).BeginScope(); + } + + public static void LogActivate(this ILogger logger) + { + logger.LogTrace("Activating view {View}", typeof(TView)); + } + + #endregion Methods +} \ No newline at end of file diff --git a/src/Lanceur.Infra/Logging/TraceLogger.cs b/src/Lanceur.Infra/Logging/TraceLogger.cs new file mode 100644 index 00000000..eb431ab6 --- /dev/null +++ b/src/Lanceur.Infra/Logging/TraceLogger.cs @@ -0,0 +1,60 @@ +using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; +using System.Diagnostics; + +namespace Lanceur.Infra.Logging +{ + /// + /// The use of this logger is NOT recommended. It's there + /// as a fallback if dev forgot to configure a logger. + /// This LogService is a very basic and NOT optimised logger. + /// It uses and also + /// reflection to log the name of the calling method. + /// + public class TraceLogger : ILogger + { + #region Methods + + private static string GetCallerName() + { + var stackTrace = new StackTrace(); + var method = stackTrace!.GetFrame(1)!.GetMethod(); + return method!.Name; + } + + private static void Write(Exception ex, string message, params object[] parameterValues) + { + var name = GetCallerName(); + + Trace.WriteLine($"[{name}] {message.Format(parameterValues)}{Environment.NewLine}{(ex is not null ? ex : string.Empty)}"); + } + + public IDisposable BeginScope(TState state) where TState : notnull => new TraceLoggerScope(state); + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + var parameters = new object[] { logLevel, eventId, state }; + var message = formatter(state, exception); + Write(exception, message, parameters); + } + + #endregion Methods + } + + /// + /// The use of this logger is NOT recommended. It's there + /// as a fallback if dev forgot to configure a logger. + /// This LogService is a very basic and NOT optimised logger. + /// It uses and also + /// reflection to log the name of the calling method. + /// + /// + /// This is an implementation to allow getting logger with the + /// generics + /// + public class TraceLogger : TraceLogger, ILogger + { + } +} \ No newline at end of file diff --git a/src/Lanceur.Infra/Logging/TraceLoggerScope.cs b/src/Lanceur.Infra/Logging/TraceLoggerScope.cs new file mode 100644 index 00000000..f8fb8fb9 --- /dev/null +++ b/src/Lanceur.Infra/Logging/TraceLoggerScope.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; +using System.Diagnostics; + +namespace Lanceur.Infra.Logging; + +public class TraceLoggerScope : IDisposable +{ + #region Fields + + private readonly object _state; + + #endregion Fields + + #region Constructors + + public TraceLoggerScope(object state) + { + _state = state; + } + + #endregion Constructors + + #region Methods + + public void Dispose() + { + var json = JsonConvert.SerializeObject(_state, Formatting.Indented); + Trace.WriteLine($"Display scope:\r\n{json}"); + } + + #endregion Methods +} \ No newline at end of file diff --git a/src/Lanceur.Infra/LuaScripting/LuaManager.cs b/src/Lanceur.Infra/LuaScripting/LuaManager.cs index f04ca0fb..fd5bbcbc 100644 --- a/src/Lanceur.Infra/LuaScripting/LuaManager.cs +++ b/src/Lanceur.Infra/LuaScripting/LuaManager.cs @@ -14,18 +14,18 @@ public static ScriptResult ExecuteScript(Script script) try { lua.State.Encoding = Encoding.UTF8; - lua["context"] = script.Context; + lua["context"] = script.Context; var result = lua.DoString(script.Code); - if (!result.Any()) { return script.EmptyResult; } - if (result[0] is not ScriptContext output) return script.EmptyResult; + if (!result.Any()) { return script.CloneWithoutContext(); } + if (result[0] is not ScriptContext output) return script.CloneWithoutContext(); return new() { Code = script.Code, Context = new() { - FileName = output.FileName, + FileName = output.FileName, Parameters = output.Parameters }, }; @@ -34,7 +34,7 @@ public static ScriptResult ExecuteScript(Script script) { return new() { - Code = script.Code, + Code = script.Code, Error = e.Message, }; } diff --git a/src/Lanceur.Infra/Managers/ExecutionManager.cs b/src/Lanceur.Infra/Managers/ExecutionManager.cs index 916d41e7..3d57443b 100644 --- a/src/Lanceur.Infra/Managers/ExecutionManager.cs +++ b/src/Lanceur.Infra/Managers/ExecutionManager.cs @@ -3,10 +3,11 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Requests; -using Lanceur.Core.Services; using Lanceur.Core.Utils; +using Lanceur.Infra.Logging; using Lanceur.Infra.LuaScripting; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using System.Diagnostics; namespace Lanceur.Infra.Managers @@ -17,7 +18,7 @@ public class ExecutionManager : IExecutionManager private readonly ICmdlineManager _cmdlineManager; private readonly IDbRepository _dataService; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IWildcardManager _wildcardManager; #endregion Fields @@ -25,13 +26,13 @@ public class ExecutionManager : IExecutionManager #region Constructors public ExecutionManager( - IAppLoggerFactory logFactory, + ILoggerFactory logFactory, IWildcardManager wildcardManager, IDbRepository dataService, ICmdlineManager cmdlineManager ) { - _log = logFactory.GetLogger(); + _logger = logFactory.GetLogger(); _wildcardManager = wildcardManager; _dataService = dataService; _cmdlineManager = cmdlineManager; @@ -41,41 +42,45 @@ ICmdlineManager cmdlineManager #region Methods - private static void ExecuteLuaScript(ref AliasQueryResult query) - { - var result = LuaManager.ExecuteScript(new() - { - Code = query.LuaScript, - Context = new() - { - FileName = query.FileName, - Parameters = query.Parameters - } - - }); - if(result?.Context?.FileName is not null) query.FileName = result.Context.FileName; - if(result?.Context?.Parameters is not null) query.Parameters = result.Context.Parameters; - } - private async Task> ExecuteAliasAsync(AliasQueryResult query) { try { if (query.Delay > 0) { - _log.Trace($"Delay of {query.Delay} second(s) before executing the alias"); + _logger.LogDebug("Delay of {Delay} second(s) before executing the alias", query.Delay); await Task.Delay(query.Delay * 1000); } if (query.IsUwp()) { - _log.Trace("Executing UWP application..."); return ExecuteUwp(query); } - _log.Trace("Executing process..."); return ExecuteProcess(query); } - catch (Exception ex) { throw new ApplicationException($"Cannot execute alias '{(query?.Name ?? "NULL")}'. Check the path of the executable or the URL.", ex); } + catch (Exception ex) { throw new ApplicationException($"Cannot execute alias '{query?.Name ?? "NULL"}'. Check the path of the executable or the URL.", ex); } + } + + private void ExecuteLuaScript(ref AliasQueryResult query) + { + using var _ = _logger.BeginSingleScope("Query", query); + + var result = LuaManager.ExecuteScript(new() + { + Code = query.LuaScript, + Context = new() + { + FileName = query.FileName, + Parameters = query.Parameters + } + }); + using var __ = _logger.BeginSingleScope("ScriptResult", result); + if (!result.Error.IsNullOrEmpty()) _logger.LogWarning("The Lua script is on error"); + + if (result?.Context?.FileName is not null) query.FileName = result.Context.FileName; + if (result?.Context?.Parameters is not null) query.Parameters = result.Context.Parameters; + + _logger.LogInformation("Lua script executed on {AlisName}", query.Name); } private IEnumerable ExecuteProcess(AliasQueryResult query) @@ -85,7 +90,7 @@ private IEnumerable ExecuteProcess(AliasQueryResult query) query.Parameters = _wildcardManager.ReplaceOrReplacementOnNull(query.Parameters, query.Query.Parameters); ExecuteLuaScript(ref query); - _log.Debug($"Executing '{query.FileName}' with args '{query.Parameters}'"); + _logger.LogInformation("Executing {FileName} with args {Parameters}", query.FileName, query.Parameters); var psi = new ProcessStartInfo { FileName = _wildcardManager.Replace(query.FileName, query.Parameters), @@ -99,7 +104,7 @@ private IEnumerable ExecuteProcess(AliasQueryResult query) if (query.IsElevated || query.RunAs == SharedKernel.Constants.RunAs.Admin) { psi.Verb = "runas"; - _log.Info($"Runs '{query.FileName}' as ADMIN"); + _logger.LogInformation("Run {FileName} as ADMIN", query.FileName); } using var _ = Process.Start(psi); @@ -118,17 +123,17 @@ private IEnumerable ExecuteUwp(AliasQueryResult query) //https://stackoverflow.com/a/23199505/389529 psi.UseShellExecute = true; psi.Verb = "runas"; - _log.Info($"Runs '{query.FileName}' as ADMIN"); + _logger.LogInformation("Run {FileName} as {Elevated}", query.FileName, "ADMIN"); } else { - psi.FileName = $"explorer.exe"; + psi.FileName = "explorer.exe"; psi.Arguments = file; psi.UseShellExecute = false; - _log.Info($"Runs '{query.FileName}'"); + _logger.LogInformation("Run {FileName} as {Elevated}", query.FileName, "regular user"); } - _log.Debug($"Executing packaged application'{file}'"); + _logger.LogInformation("Run packaged application {File}", file); Process.Start(psi); return QueryResult.NoResult; @@ -138,20 +143,22 @@ public async Task ExecuteAsync(ExecutionRequest request) { if (request is null) { - _log.Trace("The execution request is null."); + _logger.LogInformation("The execution request is null"); return new() { Results = DisplayQueryResult.SingleFromResult("This alias does not exist"), HasResult = true, }; } + + var name = request.QueryResult?.Name ?? ""; if (request.QueryResult is not IExecutable) { - _log.Trace($"Alias '{request.QueryResult?.Name ?? ""}', is not executable. Return '{nameof(ExecutionResponse.NoResult)}'."); + const string noResult = nameof(ExecutionResponse.NoResult); + _logger.LogInformation("Alias {Name}, is not executable. Return {NoResult}", name, noResult); return ExecutionResponse.NoResult; } - _log.Info($"Executing alias '{request.QueryResult.Name}'"); _dataService.SetUsage(request.QueryResult); switch (request.QueryResult) { @@ -162,6 +169,7 @@ await ExecuteAliasAsync(alias) ); case ISelfExecutable exec: + _logger.LogInformation("Executing self executable {Name}", name); exec.IsElevated = request.ExecuteWithPrivilege; return ExecutionResponse.FromResults( await exec.ExecuteAsync(_cmdlineManager.BuildFromText(request.Query)) diff --git a/src/Lanceur.Infra/Managers/FavIconManager.cs b/src/Lanceur.Infra/Managers/FavIconManager.cs index cbaf9ee1..3ed09fb6 100644 --- a/src/Lanceur.Infra/Managers/FavIconManager.cs +++ b/src/Lanceur.Infra/Managers/FavIconManager.cs @@ -1,9 +1,10 @@ using Lanceur.Core.Managers; using Lanceur.Core.Services; using Lanceur.Infra.Constants; +using Lanceur.SharedKernel.Utils; using Lanceur.SharedKernel.Web; +using Microsoft.Extensions.Logging; using System.Text.RegularExpressions; -using Lanceur.SharedKernel.Utils; namespace Lanceur.Infra.Managers { @@ -18,20 +19,20 @@ public class FavIconManager : IFavIconManager private static readonly Regex IsMacro = new("@.*@"); private readonly IFavIconDownloader _favIconDownloader; - private readonly IAppLogger _log; + private readonly ILogger _logger; #endregion Fields #region Constructors - public FavIconManager(IPackagedAppSearchService searchService, IFavIconDownloader favIconDownloader, IAppLoggerFactory appLoggerFactory) + public FavIconManager(IPackagedAppSearchService searchService, IFavIconDownloader favIconDownloader, ILoggerFactory appLoggerFactory) { ArgumentNullException.ThrowIfNull(searchService); ArgumentNullException.ThrowIfNull(favIconDownloader); ArgumentNullException.ThrowIfNull(appLoggerFactory); _favIconDownloader = favIconDownloader; - _log = appLoggerFactory.GetLogger(); + _logger = appLoggerFactory.CreateLogger(); } #endregion Constructors @@ -45,7 +46,7 @@ public async Task RetrieveFaviconAsync(string fileName) if (!Uri.TryCreate(fileName, UriKind.Absolute, out var uri)) return; if (!await _favIconDownloader.CheckExistsAsync(new($"{uri.Scheme}://{uri.Host}"))) return; - using var m = TimePiece.Measure(this, m => _log.Trace(m)); + using var m = TimePiece.Measure(this, (msg, @params) => _logger.LogTrace(msg, @params)); var output = Path.Combine(AppPaths.ImageRepository, $"{AppPaths.FaviconPrefix}{uri.Host}.png"); await _favIconDownloader.SaveToFileAsync(uri, output); } diff --git a/src/Lanceur.Infra/Managers/MacroManager.cs b/src/Lanceur.Infra/Managers/MacroManager.cs index a9500686..3bd6ede5 100644 --- a/src/Lanceur.Infra/Managers/MacroManager.cs +++ b/src/Lanceur.Infra/Managers/MacroManager.cs @@ -1,7 +1,7 @@ using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Repositories; -using Lanceur.Core.Services; +using Microsoft.Extensions.Logging; using System.Reflection; namespace Lanceur.Infra.Managers @@ -10,7 +10,7 @@ public class MacroManager : MacroManagerCache, IMacroManager { #region Constructors - public MacroManager(Assembly asm, IAppLoggerFactory logFactory = null, IDbRepository repository = null) : base(asm, logFactory, repository) + public MacroManager(Assembly asm, ILoggerFactory logFactory = null, IDbRepository repository = null) : base(asm, logFactory, repository) { } @@ -47,7 +47,9 @@ public QueryResult Handle(QueryResult item) if (!MacroInstances.ContainsKey(alias.GetMacroName())) { /* Well, this is a misconfigured macro, log it and forget it */ - Log.Warning($"User has misconfigured a Macro with name '{alias.FileName}'. Fix the name of the macro or remove the alias from the database."); + Logger.LogWarning( + "User has misconfigured a Macro with name {FileName}. Fix the name of the macro or remove the alias from the database", + alias.FileName); return null; } @@ -55,10 +57,9 @@ public QueryResult Handle(QueryResult item) if (instance is not MacroQueryResult i) throw new NotSupportedException($"Cannot cast '{instance.GetType()}' into '{typeof(MacroQueryResult)}'"); var macro = i.Clone(); - macro.Name = alias.Name; + macro.Name = alias.Name; macro.Parameters = alias.Parameters; return macro; - } #endregion Methods diff --git a/src/Lanceur.Infra/Managers/MacroManagerCache.cs b/src/Lanceur.Infra/Managers/MacroManagerCache.cs index d7cbe531..c380db7b 100644 --- a/src/Lanceur.Infra/Managers/MacroManagerCache.cs +++ b/src/Lanceur.Infra/Managers/MacroManagerCache.cs @@ -1,8 +1,8 @@ using Lanceur.Core; using Lanceur.Core.Models; using Lanceur.Core.Repositories; -using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using Splat; using System.ComponentModel; using System.Reflection; @@ -13,18 +13,18 @@ public abstract class MacroManagerCache { #region Fields - private Dictionary _macroInstances; private readonly Assembly _asm; private readonly IDbRepository _dataService; + private Dictionary _macroInstances; #endregion Fields #region Constructors - internal MacroManagerCache(Assembly asm, IAppLoggerFactory logFactory, IDbRepository repository) + internal MacroManagerCache(Assembly asm, ILoggerFactory logFactory, IDbRepository repository) { _asm = asm; - Log = Locator.Current.GetLogger(logFactory); + Logger = logFactory.GetLogger(); _dataService = repository ?? Locator.Current.GetService(); } @@ -32,7 +32,7 @@ internal MacroManagerCache(Assembly asm, IAppLoggerFactory logFactory, IDbReposi #region Properties - protected IAppLogger Log { get; } + protected ILogger Logger { get; } protected Dictionary MacroInstances { @@ -69,7 +69,7 @@ where t.GetCustomAttributes().Any() _dataService.HydrateMacro(alias); macroInstances.Add(name, alias); - Log.Trace($"Found macro '{name}'"); + Logger.LogDebug("Found macro {Name}", name); } _macroInstances = macroInstances; } diff --git a/src/Lanceur.Infra/Plugins/PluginButler.cs b/src/Lanceur.Infra/Plugins/PluginButler.cs index 2c789290..669a65f6 100644 --- a/src/Lanceur.Infra/Plugins/PluginButler.cs +++ b/src/Lanceur.Infra/Plugins/PluginButler.cs @@ -1,6 +1,7 @@ using Lanceur.Core.Plugins; -using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System.IO.Compression; using System.IO.FileOps.Core; @@ -24,7 +25,7 @@ public sealed class PluginButler : IPluginInstaller, IPluginUninstaller /// private static readonly Dictionary MutableUninstallationCandidates = new(); - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly IPluginValidationRule _pluginValidationRule; #endregion Fields @@ -32,14 +33,14 @@ public sealed class PluginButler : IPluginInstaller, IPluginUninstaller #region Constructors public PluginButler( - IAppLoggerFactory appLoggerFactory, + ILoggerFactory appLoggerFactory, IPluginValidationRule pluginValidationRule) { ArgumentNullException.ThrowIfNull(appLoggerFactory, nameof(appLoggerFactory)); ArgumentNullException.ThrowIfNull(pluginValidationRule, nameof(pluginValidationRule)); _pluginValidationRule = pluginValidationRule; - _log = appLoggerFactory.GetLogger(); + _logger = appLoggerFactory.GetLogger(); } #endregion Constructors @@ -101,7 +102,7 @@ public async Task SubscribeForInstallAsync(string pack if (config == null) { - _log.Warning($"No plugin manifest in package '{packagePath}'"); + _logger.LogWarning("No plugin manifest in package {PackagePath}", packagePath); return null; } @@ -117,7 +118,7 @@ public async Task SubscribeForInstallAsync(string pack var validation = _pluginValidationRule.Check(manifest); if (!validation.IsValid) { - _log.Warning(validation.Message); + _logger.LogWarning("Validation failed: {ValidationMsg}", validation.Message); return PluginInstallationResult.Error(validation.Message); } @@ -169,7 +170,7 @@ public async Task SubscribeForUninstallAsync(IPluginManifest manifest) if (dir is null) throw new DirectoryNotFoundException($"Cannot find plugin directory for plugin '{manifest.Name}'."); - _log.Info($"Add '{dir}' to directory to remove."); + _logger.LogInformation("Add {Directory} to directory to remove", dir); AddCandidate(manifest); os.AddOperation(OperationFactory.RemoveDirectory(Locations.GetAbsolutePath(dir))) diff --git a/src/Lanceur.Infra/Plugins/PluginManager.cs b/src/Lanceur.Infra/Plugins/PluginManager.cs index 0c7e81d0..7ffadee1 100644 --- a/src/Lanceur.Infra/Plugins/PluginManager.cs +++ b/src/Lanceur.Infra/Plugins/PluginManager.cs @@ -1,6 +1,6 @@ using Lanceur.Core.Plugins; -using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using Splat; using System.Reflection; @@ -10,16 +10,15 @@ public class PluginManager : IPluginManager { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; #endregion Fields #region Constructors - public PluginManager(IAppLoggerFactory logFactory = null) + public PluginManager(ILoggerFactory logFactory = null) { - var l = Locator.Current; - _log = l.GetLogger(logFactory); + _logger = logFactory.GetLogger(); } #endregion Constructors @@ -49,9 +48,12 @@ public IEnumerable CreatePlugin(string path) if (!plugins.Any()) return plugins; var availableTypes = string.Join(",", assembly.GetTypes().Select(t => t.FullName)); - _log.Warning( - $"Can't find any type which implements {nameof(IPlugin)} in {assembly} from {assembly.Location}.\n" + - $"Available types: {availableTypes}"); + _logger.LogWarning( + "Can't find any type which implements {IPlugin} in {Assembly} from {Location}. Available types: {AvailableTypes}", + nameof(IPlugin), + assembly, + assembly.Location, + availableTypes); return plugins; } diff --git a/src/Lanceur.Infra/Services/SearchService.cs b/src/Lanceur.Infra/Services/SearchService.cs index 53bdb91f..2bbba77f 100644 --- a/src/Lanceur.Infra/Services/SearchService.cs +++ b/src/Lanceur.Infra/Services/SearchService.cs @@ -44,8 +44,8 @@ private IEnumerable SetupAndSort(QueryResult[] input) .ThenBy(e => e.Name) .ToArray(); - return input?.Any() ?? false - ? orderedResults + return input?.Any() ?? false + ? orderedResults : DisplayQueryResult.NoResultFound; } @@ -65,20 +65,19 @@ public IEnumerable Search(Cmdline query) .SelectMany(store => store.Search(query)) .ToArray(); - // Remember the query foreach (var result in results) { result.Query = query; } // If there's an exact match, promote it to the top // of the list. var orderedResults = SetupAndSort(results).ToList(); - var match = (from r in orderedResults + var match = (from r in orderedResults where r.Name == query.Name select r).FirstOrDefault(); if (match is not null) { orderedResults.Move(match, 0); } - - return !orderedResults.Any() - ? DisplayQueryResult.SingleFromResult("No result found", iconKind: "AlertCircleOutline") + + return !orderedResults.Any() + ? DisplayQueryResult.SingleFromResult("No result found", iconKind: "AlertCircleOutline") : orderedResults; } diff --git a/src/Lanceur.Infra/Stores/PluginStore.cs b/src/Lanceur.Infra/Stores/PluginStore.cs index fb455142..d993facf 100644 --- a/src/Lanceur.Infra/Stores/PluginStore.cs +++ b/src/Lanceur.Infra/Stores/PluginStore.cs @@ -3,8 +3,9 @@ using Lanceur.Core.Repositories; using Lanceur.Core.Services; using Lanceur.Core.Stores; +using Lanceur.Infra.Logging; using Lanceur.Infra.Plugins; -using Lanceur.Infra.Utils; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Splat; using System.Reflection; @@ -20,8 +21,8 @@ public class PluginStore : ISearchService, IPluginManifestRepository private readonly Version _appVersion; private readonly IPluginStoreContext _context; private readonly IDbRepository _dbRepository; - private readonly IAppLogger _log; - private readonly IAppLoggerFactory _logFactory; + private readonly ILogger _logger; + private readonly ILoggerFactory _loggerFactory; private readonly IPluginManager _pluginManager; #endregion Fields @@ -30,19 +31,19 @@ public class PluginStore : ISearchService, IPluginManifestRepository private PluginStore( IPluginStoreContext context = null, - IAppLoggerFactory logFactory = null, IPluginManager pluginManager = null, - IDbRepository dbRepository = null + IDbRepository dbRepository = null, + ILoggerFactory loggerFactory = null ) { var l = Locator.Current; + + _loggerFactory = loggerFactory ?? l.GetService(); + _logger = LoggerFactoryMixin.GetLogger(_loggerFactory); + _dbRepository = dbRepository ?? l.GetService(); _pluginManager = pluginManager ?? l.GetService(); _context = context ?? l.GetService(); - - _logFactory = logFactory ?? l.GetService(); - _log = l.GetLogger(_logFactory); - _appVersion = Assembly.GetExecutingAssembly().GetName().Version; } @@ -62,7 +63,7 @@ private void LoadPlugins() _plugins = configs .Where(manifest => _appVersion >= manifest.AppMinVersion) .SelectMany(manifest => _pluginManager.CreatePlugin(manifest.Dll)) - .Select(x => new PluginExecutableQueryResult(x, _logFactory)) + .Select(x => new PluginExecutableQueryResult(x, _loggerFactory)) .ToList(); } @@ -90,7 +91,7 @@ public IEnumerable Search(Cmdline query) var found = (from plugin in _plugins where plugin?.Name?.ToLower().StartsWith(query.Name.ToLower()) ?? false select plugin).ToArray(); - _log.Trace($"Found {found.Length} plugin(s)"); + _logger.LogDebug("Found {Length} plugin(s)", found.Length); //Set count and name foreach (var item in found) diff --git a/src/Lanceur.Infra/Utils/LocatorMixin.cs b/src/Lanceur.Infra/Utils/LocatorMixin.cs deleted file mode 100644 index eda443c1..00000000 --- a/src/Lanceur.Infra/Utils/LocatorMixin.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Lanceur.Core.Services; -using Splat; - -namespace Lanceur.Infra.Utils -{ - public static class LocatorMixin - { - #region Methods - - public static IAppLogger GetLogger(this IReadonlyDependencyResolver locator, IAppLoggerFactory factory = null) - { - return factory?.GetLogger() - ?? locator?.GetService()?.GetLogger() - ?? new TraceLogger(); - } - - public static IAppLogger GetLogger(this IReadonlyDependencyResolver locator, Type category, IAppLoggerFactory factory = null) - { - return factory?.GetLogger(category) - ?? locator?.GetService()?.GetLogger(category) - ?? new TraceLogger(); - } - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs b/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs index 24a2f9aa..17e03505 100644 --- a/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs +++ b/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs @@ -13,7 +13,7 @@ public static class CloningMixin /// The type of the object to clone /// A new instance of the object with the same state public static T CloneObject(this T obj) - where T: new() + where T : new() { var bytes = JsonSerializer.SerializeToUtf8Bytes(obj); return JsonSerializer.Deserialize(bytes); diff --git a/src/Lanceur.SharedKernel/Mixins/PathMixin.cs b/src/Lanceur.SharedKernel/Mixins/PathMixin.cs index 372174d9..f1dc84cf 100644 --- a/src/Lanceur.SharedKernel/Mixins/PathMixin.cs +++ b/src/Lanceur.SharedKernel/Mixins/PathMixin.cs @@ -4,10 +4,10 @@ public static class PathMixin { #region Methods - public static string GetDirectoryName(this string path) => Path.GetDirectoryName(path); - public static string ExpandPath(this string path) => Environment.ExpandEnvironmentVariables(path); + public static string GetDirectoryName(this string path) => Path.GetDirectoryName(path); + #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur.SharedKernel/Mixins/StringMixin.cs b/src/Lanceur.SharedKernel/Mixins/StringMixin.cs index 82861be2..d51bf75d 100644 --- a/src/Lanceur.SharedKernel/Mixins/StringMixin.cs +++ b/src/Lanceur.SharedKernel/Mixins/StringMixin.cs @@ -7,19 +7,19 @@ public static class StringMixin { #region Methods - public static bool CastToBool(this string @this, bool @default = default) => bool.TryParse(@this, out bool result) ? result : @default; + private static bool CastToBool(this string @this, bool @default = default) => bool.TryParse(@this, out bool result) ? result : @default; - public static bool CastToBool(this object @this, bool @default = default) => $"{@this}".CastToBool(@default); - - public static double CastToDouble(this object @this, double @default = default, IFormatProvider provider = null) => $"{@this}".CastToDouble(@default, provider); - - public static double CastToDouble(this string @this, double @default = default, IFormatProvider provider = null) + private static double CastToDouble(this string @this, double @default = default, IFormatProvider provider = null) { provider ??= new CultureInfo("en-US"); return double.TryParse(@this, NumberStyles.AllowDecimalPoint, provider, out double result) ? result : @default; } - public static int CastToInt(this string @this, int @default = default) => int.TryParse(@this, out int result) ? result : @default; + private static int CastToInt(this string @this, int @default = default) => int.TryParse(@this, out int result) ? result : @default; + + public static bool CastToBool(this object @this, bool @default = default) => $"{@this}".CastToBool(@default); + + public static double CastToDouble(this object @this, double @default = default, IFormatProvider provider = null) => $"{@this}".CastToDouble(@default, provider); public static int CastToInt(this object @this, int @default = default) => $"{@this}".CastToInt(@default); @@ -54,6 +54,13 @@ public static string JoinCsv(this string[] strings) return string.Join(", ", strings); } + public static string Left(this string @string, int length) + { + return @string.Length <= length + ? @string + : @string[..length]; + } + public static string[] SplitCsv(this string str) { if (str is null) { return Array.Empty(); } diff --git a/src/Lanceur.SharedKernel/Utils/Measurement.cs b/src/Lanceur.SharedKernel/Utils/Measurement.cs index d92f8e7d..6f418a40 100644 --- a/src/Lanceur.SharedKernel/Utils/Measurement.cs +++ b/src/Lanceur.SharedKernel/Utils/Measurement.cs @@ -7,7 +7,7 @@ public sealed class Measurement : IDisposable #region Fields private readonly string _callerMemberName; - private readonly Action _log; + private readonly Action _log; private readonly Type _source; private readonly Stopwatch _stopwatch; @@ -15,12 +15,12 @@ public sealed class Measurement : IDisposable #region Constructors - internal Measurement(Type source, string callerMemberName, Action log) + internal Measurement(Type source, string callerMemberName, Action log) { - _source = source; + _source = source; _callerMemberName = callerMemberName; - _log = log; - _stopwatch = new(); + _log = log; + _stopwatch = new(); _stopwatch.Start(); } @@ -30,9 +30,11 @@ internal Measurement(Type source, string callerMemberName, Action log) public void Dispose() { + var elapsed = _stopwatch.ElapsedMilliseconds; _stopwatch.Stop(); - var message = $"'{_source.FullName}.{_callerMemberName}' executed in {_stopwatch.ElapsedMilliseconds} milliseconds."; - _log(message); + var message = "{SourceFullName}.{CallerMemberName} executed in {ElapsedMilliseconds} milliseconds"; + var parameters = new object[] { _source.FullName, _callerMemberName, elapsed }; + _log(message, parameters); } #endregion Methods diff --git a/src/Lanceur.SharedKernel/Utils/TimePiece.cs b/src/Lanceur.SharedKernel/Utils/TimePiece.cs index a24ac972..53d11936 100644 --- a/src/Lanceur.SharedKernel/Utils/TimePiece.cs +++ b/src/Lanceur.SharedKernel/Utils/TimePiece.cs @@ -6,9 +6,9 @@ public static class TimePiece { #region Methods - public static Measurement Measure(object source, - Action log, - [CallerMemberName] string callerMemberName = "") + public static Measurement Measure(object source, + Action log, + [CallerMemberName] string callerMemberName = "") => new(source.GetType(), callerMemberName, log); #endregion Methods diff --git a/src/Lanceur.SharedKernel/Web/IFavIconDownloader.cs b/src/Lanceur.SharedKernel/Web/IFavIconDownloader.cs index cfb94162..0840f230 100644 --- a/src/Lanceur.SharedKernel/Web/IFavIconDownloader.cs +++ b/src/Lanceur.SharedKernel/Web/IFavIconDownloader.cs @@ -8,6 +8,13 @@ public interface IFavIconDownloader { #region Methods + /// + /// Check whether the website exists + /// + /// The URL to check + /// True if the website exists; otherwise False + Task CheckExistsAsync(Uri url); + /// /// Download the favicon and save it to a file. If there's no /// favicon, nothing is saved @@ -17,13 +24,6 @@ public interface IFavIconDownloader /// True if favicon was found at the specified address; otherwise False Task SaveToFileAsync(Uri url, string path); - /// - /// Check whether the website exists - /// - /// The URL to check - /// True if the website exists; otherwise False - Task CheckExistsAsync(Uri url); - #endregion Methods } } \ No newline at end of file diff --git a/src/Lanceur/App.xaml b/src/Lanceur/App.xaml index 026a35ae..b898e627 100644 --- a/src/Lanceur/App.xaml +++ b/src/Lanceur/App.xaml @@ -2,9 +2,9 @@ x:Class="Lanceur.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:local="clr-namespace:Lanceur" xmlns:theming="clr-namespace:Lanceur.Xaml" - xmlns:ui="http://schemas.modernwpf.com/2019" StartupUri="Views/MainView.xaml"> diff --git a/src/Lanceur/App.xaml.cs b/src/Lanceur/App.xaml.cs index f2172bd3..a8fa90b7 100644 --- a/src/Lanceur/App.xaml.cs +++ b/src/Lanceur/App.xaml.cs @@ -4,21 +4,22 @@ using Lanceur.Infra.Plugins; using Lanceur.SharedKernel.Mixins; using Lanceur.SharedKernel.Utils; +using Lanceur.Utils; using Lanceur.Xaml; +using Microsoft.Extensions.Logging; using Microsoft.Toolkit.Uwp.Notifications; using Splat; using System; using System.IO; using System.Windows; using System.Windows.Threading; -using Lanceur.Ui; namespace Lanceur; /// /// Interaction logic for App.xaml /// -public partial class App : Application +public partial class App { #region Fields @@ -38,7 +39,7 @@ public App() #region Methods - private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { var notify = Locator.Current.GetService(); notify.Error(e.Exception.Message, e.Exception); @@ -52,7 +53,7 @@ protected override void OnExit(ExitEventArgs e) protected override async void OnStartup(StartupEventArgs e) { - var log = Locator.Current.GetService().GetLogger(); + var log = StaticLoggerFactory.GetLogger(); _notifyIcon ??= new(); ThemeManager.Current.SetTheme(); @@ -70,7 +71,7 @@ protected override async void OnStartup(StartupEventArgs e) var errors = await installer.SubscribeForInstallAsync(); if (!errors.IsNullOrEmpty()) { - log.Error($"Error occured when installing plugins on startup: {errors}"); + log.LogError("Error occured when installing plugins on startup: {Errors}", errors); } } diff --git a/src/Lanceur/AssemblyInfo.cs b/src/Lanceur/AssemblyInfo.cs index 7fc2e629..bc264051 100644 --- a/src/Lanceur/AssemblyInfo.cs +++ b/src/Lanceur/AssemblyInfo.cs @@ -9,5 +9,4 @@ //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) )] - -[assembly:InternalsVisibleTo("Lanceur.Tests")] \ No newline at end of file +[assembly: InternalsVisibleTo("Lanceur.Tests")] \ No newline at end of file diff --git a/src/Lanceur/Bootstrapper.cs b/src/Lanceur/Bootstrapper.cs index c291e84b..5cb60abb 100644 --- a/src/Lanceur/Bootstrapper.cs +++ b/src/Lanceur/Bootstrapper.cs @@ -8,7 +8,9 @@ using Lanceur.Core.Services; using Lanceur.Core.Stores; using Lanceur.Core.Utils; +using Lanceur.Infra.Constants; using Lanceur.Infra.Formatters; +using Lanceur.Infra.Logging; using Lanceur.Infra.Managers; using Lanceur.Infra.Plugins; using Lanceur.Infra.Repositories; @@ -16,30 +18,37 @@ using Lanceur.Infra.SQLite; using Lanceur.Infra.Stores; using Lanceur.Infra.Wildcards; +using Lanceur.Infra.Win32.PackagedApp; +using Lanceur.Infra.Win32.Restart; +using Lanceur.Infra.Win32.Thumbnails; using Lanceur.Models; using Lanceur.Schedulers; using Lanceur.Scripts; +using Lanceur.SharedKernel.Web; using Lanceur.Ui; using Lanceur.Utils; using Lanceur.Utils.ConnectionStrings; using Lanceur.Utils.PackagedApps; using Lanceur.Views; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using ReactiveUI; +using Serilog; +using Serilog.Events; +using Serilog.Formatting.Compact; using Splat; +using Splat.Serilog; using System; using System.Data.SQLite; using System.Linq; using System.Reflection; -using Lanceur.Infra.Win32; -using Lanceur.Infra.Win32.PackagedApp; -using Lanceur.Infra.Win32.Restart; -using Lanceur.Infra.Win32.Thumbnails; -using Lanceur.SharedKernel.Web; namespace Lanceur; public class Bootstrapper { + private static ServiceProvider _serviceCollection; + #region Methods private static T Get() => Locator.Current.GetService(); @@ -57,18 +66,29 @@ private static IConfigurationProvider GetAutoMapperCfg() cfg.CreateMap() .ConstructUsing(x => - new(x.Name, x.Notes, Get(), + new(x.Name, x.Notes, Get().GetLogger(), Get())) .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)); }); } + private static void RegisterLoggers() + { + var config = new LoggerConfiguration().MinimumLevel.Verbose() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File(new CompactJsonFormatter(), + AppPaths.LogFilePath, + rollingInterval: RollingInterval.Day) + .WriteTo.Console(); + _serviceCollection = new ServiceCollection().AddLogging(b => b.AddSerilog(config.CreateLogger())) + .BuildServiceProvider(); + } + private static void RegisterServices() { var l = Locator.CurrentMutable; - Locator.CurrentMutable.RegisterConstant(new ReactiveUILogger() { Level = LogLevel.Debug }, typeof(ILogger)); - l.RegisterLazySingleton(() => new Mapper(GetAutoMapperCfg())); l.RegisterLazySingleton(() => new UserNotification()); l.RegisterLazySingleton(() => new RoutingState()); @@ -87,32 +107,36 @@ private static void RegisterServices() Get())); l.Register(() => new RxAppSchedulerProvider()); - l.Register(() => new NLoggerFactory()); + + // Logging + Locator.CurrentMutable.UseSerilogFullLogger(); + l.Register(() => _serviceCollection?.GetService() ?? new DefaultLoggerFactory()); + l.Register(() => new StoreLoader()); l.Register(() => new SearchService(Get())); l.Register(() => new CmdlineManager()); - l.Register(() => new ExecutionManager(Get(), + l.Register(() => new ExecutionManager(Get(), Get(), Get(), Get())); l.Register(() => new SQLiteRepository(Get(), - Get(), + Get(), Get())); l.Register(() => new SQLiteDataDoctorRepository(Get(), - Get())); + Get())); l.Register(() => new ReplacementComposite(Get())); l.Register(() => new CodingSebCalculatorService()); l.Register(() => new AutoMapperConverter(Get())); l.Register(() => new WindowsClipboardService()); l.RegisterLazySingleton(() => new MacroManager(Assembly.GetExecutingAssembly())); - l.Register(() => new PluginManager(Get())); - l.Register(()=> new ThumbnailRefresher(Get(), Get(), Get())); - l.Register(() => new ThumbnailManager(Get(), Get(), Get())); + l.Register(() => new PluginManager(Get())); + l.Register(() => new ThumbnailRefresher(Get(), Get(), Get())); + l.Register(() => new ThumbnailManager(Get(), Get(), Get())); l.Register(() => new PackagedAppManager()); l.Register(() => new PackagedAppSearchService()); - l.Register(()=> new FavIconDownloader()); - l.Register(() => new FavIconManager(Get(), Get(), Get())); + l.Register(() => new FavIconDownloader()); + l.Register(() => new FavIconManager(Get(), Get(), Get())); // Formatters l.Register(() => new DefaultStringFormatter()); @@ -120,11 +144,11 @@ private static void RegisterServices() // Plugins l.Register(() => new PluginStore()); l.Register(() => new PluginButler( - Get(), + Get(), Get>())); l.Register(() => new PluginButler( - Get(), + Get(), Get>())); l.Register(() => new PluginWebManifestLoader()); @@ -137,7 +161,7 @@ private static void RegisterServices() // SQLite l.Register(() => new SQLiteUpdater(Get(), - Get(), + Get(), Get())); l.Register(() => new SQLiteConnection(Get().ToString())); @@ -164,7 +188,7 @@ private static void RegisterViewModels() l.RegisterLazySingleton(() => new ToastNotification()); // ViewModels - var vmTypeCollection = (from type in Assembly.GetAssembly(typeof(MainViewModel)).GetTypes() + var vmTypeCollection = (from type in Assembly.GetAssembly(typeof(MainViewModel))!.GetTypes() where type.Name.EndsWith("ViewModel") select type).ToList(); @@ -175,7 +199,7 @@ where type.Name.EndsWith("ViewModel") if (ctorCollection.Length == 0) { - log.Info($"Add ViewModel '{vmType.FullName}' into IOC. Ctor has no ctor."); + log.Info("Add ViewModel {FullName} into IOC. Ctor has no ctor.", vmType.FullName); l.RegisterLazySingleton(() => Activator.CreateInstance(vmType)); continue; } @@ -183,7 +207,7 @@ where type.Name.EndsWith("ViewModel") var ctor = vmType.GetConstructors()[0]; var pCount = ctor.GetParameters().Length; - log.Info($"Add ViewModel '{vmType.FullName}' into IOC. Ctor has {pCount} parameter(s)."); + log.Info("Add ViewModel {FullName} into IOC. Ctor has {pCount} parameter(s).", vmType.FullName, pCount); l.RegisterLazySingleton(() => ctor.Invoke(new object[pCount]), vmType); } } @@ -197,6 +221,7 @@ private static void RegisterViews() internal static void Initialise() { + RegisterLoggers(); RegisterViews(); RegisterServices(); RegisterViewModels(); @@ -205,7 +230,7 @@ internal static void Initialise() var stg = l.GetService(); var sqlite = l.GetService(); - AppLogFactory.Get().Trace($"Settings DB path: '{stg.ToString()}'"); + StaticLoggerFactory.GetLogger().LogInformation("Settings DB path: {Settings}", stg); sqlite.Update(stg.ToString()); } diff --git a/src/Lanceur/Controls/ProcessFinderButton.xaml.cs b/src/Lanceur/Controls/ProcessFinderButton.xaml.cs index 95994009..a618a96a 100644 --- a/src/Lanceur/Controls/ProcessFinderButton.xaml.cs +++ b/src/Lanceur/Controls/ProcessFinderButton.xaml.cs @@ -1,5 +1,6 @@ using Lanceur.Core.Utils; using Lanceur.Utils; +using Microsoft.Extensions.Logging; using System; using System.IO; using System.Windows; @@ -131,7 +132,7 @@ protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) ReleaseMouseCapture(); Cursor = null; } - catch (Exception ex) { AppLogFactory.Get().Error(ex.Message, ex); } + catch (Exception ex) { StaticLoggerFactory.GetLogger().LogError(ex, "An error occured when trying to retrieve the path of the executable with the mouse"); } } protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) diff --git a/src/Lanceur/Converters/QueryDescriptionConverter.cs b/src/Lanceur/Converters/QueryDescriptionConverter.cs index 2349ffa6..082af520 100644 --- a/src/Lanceur/Converters/QueryDescriptionConverter.cs +++ b/src/Lanceur/Converters/QueryDescriptionConverter.cs @@ -1,9 +1,9 @@ using Lanceur.Core.Formatters; +using Lanceur.Infra.Formatters; using Splat; using System; using System.Globalization; using System.Windows.Data; -using Lanceur.Infra.Formatters; namespace Lanceur.Converters { diff --git a/src/Lanceur/Lanceur.csproj b/src/Lanceur/Lanceur.csproj index d09c8d3e..64332e4e 100644 --- a/src/Lanceur/Lanceur.csproj +++ b/src/Lanceur/Lanceur.csproj @@ -24,13 +24,16 @@ - - + + + + + @@ -41,9 +44,6 @@ - - Always - SettingsSingleFileGenerator Settings.Designer.cs diff --git a/src/Lanceur/Macros/Development/DebugMacro.cs b/src/Lanceur/Macros/Development/DebugMacro.cs index aa07fafd..1e4a7a93 100644 --- a/src/Lanceur/Macros/Development/DebugMacro.cs +++ b/src/Lanceur/Macros/Development/DebugMacro.cs @@ -2,9 +2,10 @@ using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Services; +using Lanceur.Infra.Logging; using Lanceur.SharedKernel.Mixins; -using Lanceur.Ui; using Lanceur.Utils; +using Microsoft.Extensions.Logging; using Microsoft.Toolkit.Uwp.Notifications; using Splat; using System.Collections.Generic; @@ -17,6 +18,12 @@ namespace Lanceur.Macros.Development [Macro("debug"), Description("Provides some debugging tools. But it is more an easter egg than something else")] public class DebugMacro : MacroQueryResult { + #region Fields + + private readonly ILogger _logger; + + #endregion Fields + #region Constructors internal DebugMacro(string name, string description, Cmdline query) @@ -24,6 +31,7 @@ internal DebugMacro(string name, string description, Cmdline query) Name = name; Query = query; Description = description; + _logger = Locator.Current.GetService().GetLogger(); } public DebugMacro() @@ -73,7 +81,8 @@ public override Task> ExecuteAsync(Cmdline cmdline = nu new DebugMacro("debug cache", "Displays thumbnails in the cache", Cmdline("debug cache") ), }, }; - AppLogFactory.Get().Debug($"Executed 'debug {cl.Name.ToLower()}' and found {result.Count()} item(s)"); + result = result.ToList(); + StaticLoggerFactory.GetLogger().LogDebug("Executed 'debug {Name}' and found {Result} item(s)", cl.Name.ToLower(), result.Count()); return Task.FromResult(result); } diff --git a/src/Lanceur/Macros/MultiMacro.cs b/src/Lanceur/Macros/MultiMacro.cs index da3eb345..8d4a5632 100644 --- a/src/Lanceur/Macros/MultiMacro.cs +++ b/src/Lanceur/Macros/MultiMacro.cs @@ -31,11 +31,11 @@ public class MultiMacro : MacroQueryResult #endregion Fields #region Constructors - public MultiMacro() : this(null, null, null) { } + public MultiMacro(int? delay = null, IExecutionManager executionManager = null, ISearchService searchService = null) { _delay = delay ?? DefaultDelay; diff --git a/src/Lanceur/NLog.config b/src/Lanceur/NLog.config deleted file mode 100644 index 1e23fdff..00000000 --- a/src/Lanceur/NLog.config +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - /> - - - - - - - - \ No newline at end of file diff --git a/src/Lanceur/NLogger.cs b/src/Lanceur/NLogger.cs deleted file mode 100644 index 33742664..00000000 --- a/src/Lanceur/NLogger.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Lanceur.Core.Services; -using NLog; -using System; - -namespace Lanceur -{ - internal class NLogger : IAppLogger - { - #region Fields - - private readonly Logger _logger; - - #endregion Fields - - #region Constructors - - public NLogger(Type sourceType) - { - _logger = LogManager.GetLogger(sourceType.FullName); - } - - #endregion Constructors - - #region Methods - - public void Debug(string message) => _logger.Debug(message); - - public void Debug(Exception ex) => _logger.Debug(ex); - - public void Error(string message, Exception ex = null) - { - if (ex != null) { _logger.Error(ex, message); } - else { _logger.Error(message); } - } - - public void Fatal(string message, Exception ex = null) - { - if (ex != null) { _logger.Fatal(ex, message); } - else { _logger.Fatal(message); } - } - - public void Info(string message) => _logger.Info(message); - - public void Trace(string message) => _logger.Trace(message); - - public void Warning(string message, Exception ex = null) - { - if (ex != null) { _logger.Warn(ex, message); } - else { _logger.Warn(message); } - } - - public void Warning(Exception ex) => Warning(ex.Message, ex); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur/NLoggerFactory.cs b/src/Lanceur/NLoggerFactory.cs deleted file mode 100644 index 30ee191f..00000000 --- a/src/Lanceur/NLoggerFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Lanceur.Core.Services; -using System; - -namespace Lanceur -{ - internal class NLoggerFactory : IAppLoggerFactory - { - #region Methods - - public IAppLogger GetLogger() => GetLogger(typeof(TCategory)); - - public IAppLogger GetLogger(Type categoryName) => new NLogger(categoryName); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur/ReactiveUILogger.cs b/src/Lanceur/ReactiveUILogger.cs deleted file mode 100644 index 68597bc7..00000000 --- a/src/Lanceur/ReactiveUILogger.cs +++ /dev/null @@ -1,71 +0,0 @@ -using NLog; -using System; -using System.ComponentModel; -using System.Globalization; -using ILogger = Splat.ILogger; -using LogLevel = Splat.LogLevel; -using NLogLevel = NLog.LogLevel; - -namespace Lanceur -{ - internal class ReactiveUILogger : ILogger - { - #region Fields - - private readonly Logger _logger; - - #endregion Fields - - #region Constructors - - public ReactiveUILogger() - { - _logger = LogManager.GetLogger("ReactiveUI"); - } - - #endregion Constructors - - #region Properties - - public LogLevel Level { get; set; } - - #endregion Properties - - #region Methods - - private NLogLevel GetLevel(LogLevel logLevel) - { - return logLevel switch - { - LogLevel.Debug => NLogLevel.Trace, - LogLevel.Info => NLogLevel.Debug, - LogLevel.Warn => NLogLevel.Warn, - LogLevel.Error => NLogLevel.Error, - LogLevel.Fatal => NLogLevel.Fatal, - _ => throw new NotSupportedException($"Log level '{logLevel}' not supported."), - }; - } - - public void Write([Localizable(false)] string message, LogLevel logLevel) - { - _logger.Log(GetLevel(logLevel), message); - } - - public void Write(Exception exception, [Localizable(false)] string message, LogLevel logLevel) - { - _logger.Log(GetLevel(logLevel), exception, CultureInfo.InvariantCulture, message); - } - - public void Write([Localizable(false)] string message, [Localizable(false)] Type type, LogLevel logLevel) - { - _logger.Log(GetLevel(logLevel), message); - } - - public void Write(Exception exception, [Localizable(false)] string message, [Localizable(false)] Type type, LogLevel logLevel) - { - _logger.Log(GetLevel(logLevel), exception, CultureInfo.InvariantCulture, message); - } - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur/ReservedKeywords/CentreAlias.cs b/src/Lanceur/ReservedKeywords/CentreAlias.cs index d2cdcf42..8ae0805a 100644 --- a/src/Lanceur/ReservedKeywords/CentreAlias.cs +++ b/src/Lanceur/ReservedKeywords/CentreAlias.cs @@ -1,14 +1,13 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Threading.Tasks; using Lanceur.Core; using Lanceur.Core.Models; using Lanceur.Core.Repositories.Config; using Lanceur.Infra.Win32.Utils; -using Lanceur.SharedKernel.Mixins; using Lanceur.Utils; +using Microsoft.Extensions.Logging; using Splat; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading.Tasks; namespace Lanceur.ReservedKeywords { @@ -35,10 +34,11 @@ private static void Save(Coordinate coordinate) public override Task> ExecuteAsync(Cmdline cmdline = null) { - var coordinate = ScreenRuler.SetDefaultPosition(); - AppLogFactory.Get() - .Info( - $"Put window at default position. (x: {coordinate.X} - y: {coordinate.Y}"); + var coordinate = ScreenRuler.SetDefaultPosition(); + StaticLoggerFactory.GetLogger() + .LogInformation("Put window at default position. (x: {X} - y: {Y}", + coordinate.X, + coordinate.Y); Save(coordinate); return NoResultAsync; diff --git a/src/Lanceur/ReservedKeywords/QuitAlias.cs b/src/Lanceur/ReservedKeywords/QuitAlias.cs index 54ae3abd..857f6b7a 100644 --- a/src/Lanceur/ReservedKeywords/QuitAlias.cs +++ b/src/Lanceur/ReservedKeywords/QuitAlias.cs @@ -1,6 +1,7 @@ using Lanceur.Core; using Lanceur.Core.Models; using Lanceur.Utils; +using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; @@ -22,7 +23,7 @@ public class QuitAlias : SelfExecutableQueryResult public override Task> ExecuteAsync(Cmdline cmdline = null) { Application.Current.Shutdown(); - this.Log().Info("Quit the application from alias 'Quit'"); + this.GetLogger().LogInformation("Quit the application from alias 'Quit'"); return NoResultAsync; } diff --git a/src/Lanceur/ReservedKeywords/SessionListAlias.cs b/src/Lanceur/ReservedKeywords/SessionListAlias.cs index 23d47ece..6c017765 100644 --- a/src/Lanceur/ReservedKeywords/SessionListAlias.cs +++ b/src/Lanceur/ReservedKeywords/SessionListAlias.cs @@ -21,7 +21,7 @@ public class SessionListAlias : SelfExecutableQueryResult #region Constructors - public SessionListAlias() : this(null, null) + public SessionListAlias() : this(null) { } diff --git a/src/Lanceur/SyntaxColoration/LUA-Mode.xml b/src/Lanceur/SyntaxColoration/LUA-Mode.xml index ef5b7267..906fac68 100644 --- a/src/Lanceur/SyntaxColoration/LUA-Mode.xml +++ b/src/Lanceur/SyntaxColoration/LUA-Mode.xml @@ -3,7 +3,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -36,7 +36,7 @@ ' ' - + @@ -44,7 +44,7 @@ " " - + diff --git a/src/Lanceur/Ui/ConventionalViewLocator.cs b/src/Lanceur/Ui/ConventionalViewLocator.cs index 9360c36b..e788807f 100644 --- a/src/Lanceur/Ui/ConventionalViewLocator.cs +++ b/src/Lanceur/Ui/ConventionalViewLocator.cs @@ -21,15 +21,15 @@ public IViewFor ResolveView(T viewModel, string contract = null) var viewType = Type.GetType(viewTypeName); if (viewType == null) { - this.Log().Error($"Could not find the view {viewTypeName} for view model {viewModelName}."); + this.Log().Error("Could not find the view {viewTypeName} for view model {viewModelName}.", viewTypeName, viewModelName); return null; } - this.Log().Info($"Find view {viewTypeName} for view model {viewModelName}."); + this.Log().Info("Find view {viewTypeName} for view model {viewModelName}.", viewTypeName, viewModelName); return Activator.CreateInstance(viewType) as IViewFor; } catch (Exception) { - this.Log().Error($"Could not instantiate view {viewTypeName}."); + this.Log().Error("Could not instantiate view {viewTypeName}.", viewTypeName); throw; } } diff --git a/src/Lanceur/Ui/UserNotification.cs b/src/Lanceur/Ui/UserNotification.cs index 2458c8f6..263549ed 100644 --- a/src/Lanceur/Ui/UserNotification.cs +++ b/src/Lanceur/Ui/UserNotification.cs @@ -1,5 +1,6 @@ using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using Splat; using System; @@ -9,16 +10,16 @@ public class UserNotification : IUserNotification { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly INotification _notification; #endregion Fields #region Constructors - public UserNotification(IAppLoggerFactory logFactory = null, INotification notification = null) + public UserNotification(ILoggerFactory logFactory = null, INotification notification = null) { - _log = Locator.Current.GetLogger(logFactory); + _logger = logFactory.GetLogger(); _notification = notification ?? Locator.Current.GetService(); ; } @@ -26,15 +27,17 @@ public UserNotification(IAppLoggerFactory logFactory = null, INotification notif #region Methods + //TODO: refactor logging... It's not optimised public void Error(string message, Exception ex) { - _log.Error(message, ex); + _logger.LogError(ex, message); _notification.Error(message); } + //TODO: refactor logging... It's not optimised public void Warning(string message, Exception ex = null) { - _log.Warning(message, ex); + _logger.LogWarning(message, ex); _notification.Warning(message); } diff --git a/src/Lanceur/Utils/AppLogFactory.cs b/src/Lanceur/Utils/AppLogFactory.cs deleted file mode 100644 index 0cb46749..00000000 --- a/src/Lanceur/Utils/AppLogFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Lanceur.Core.Models; -using Lanceur.Core.Services; -using Lanceur.Infra.Utils; -using Splat; -using System; - -namespace Lanceur.Utils -{ - internal static class AppLogFactory - { - #region Methods - - public static IAppLogger Get() => Locator.Current.GetLogger(typeof(TCategory)); - - public static IAppLogger Get(Type category) => Locator.Current.GetLogger(category); - - public static IAppLogger Log(this QueryResult _) => Get(); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Lanceur/Utils/ConnectionStrings/ConnectionString.cs b/src/Lanceur/Utils/ConnectionStrings/ConnectionString.cs index 0591ce65..78b067b3 100644 --- a/src/Lanceur/Utils/ConnectionStrings/ConnectionString.cs +++ b/src/Lanceur/Utils/ConnectionStrings/ConnectionString.cs @@ -1,6 +1,7 @@ using Lanceur.Core.Repositories.Config; using Lanceur.Core.Utils; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using System; using System.IO; @@ -36,7 +37,7 @@ public override string ToString() { if (!File.Exists(_dbPath)) { - AppLogFactory.Get().Warning($"The path '{_dbPath}' doesn't exist. A new database should be created!"); + StaticLoggerFactory.GetLogger().LogWarning("The path {DbPath} doesn't exist. A new database should be created!", _dbPath); } var path = Environment.ExpandEnvironmentVariables(_dbPath); return CSTRING_PATTERN.Format(path); diff --git a/src/Lanceur/Utils/ConnectionStrings/DebugConnectionString.cs b/src/Lanceur/Utils/ConnectionStrings/DebugConnectionString.cs index 8be2dac8..8fc93c9b 100644 --- a/src/Lanceur/Utils/ConnectionStrings/DebugConnectionString.cs +++ b/src/Lanceur/Utils/ConnectionStrings/DebugConnectionString.cs @@ -1,7 +1,7 @@ using Lanceur.Core.Utils; +using Lanceur.Infra.Constants; using Lanceur.SharedKernel.Mixins; using System; -using Lanceur.Infra.Constants; namespace Lanceur.Utils.ConnectionStrings { diff --git a/src/Lanceur/Utils/PackagedApps/PackageInformation.cs b/src/Lanceur/Utils/PackagedApps/PackageInformation.cs index a7cf9aa6..71d805ee 100644 --- a/src/Lanceur/Utils/PackagedApps/PackageInformation.cs +++ b/src/Lanceur/Utils/PackagedApps/PackageInformation.cs @@ -52,7 +52,6 @@ private static string Get(Package package, Func 0 ? visitor(apps[0]) : string.Empty; - } private static PackageVersion InitPackageVersion(string[] namespaces) @@ -71,9 +70,6 @@ private static PackageVersion InitPackageVersion(string[] namespaces) return versionFromNamespace[n]; } } - - //_log.Warning($"Trying to get the package version of the UWP program, but a unknown UWP appmanifest version is returned."); - return PackageVersion.Unknown; } @@ -106,24 +102,18 @@ private static string LogoUriFromManifest(AppxPackageHelper.IAppxManifestApplica /// http://www.hanselman.com/blog/GetNamespacesFromAnXMLDocumentWithXPathDocumentAndLINQToXML.aspx private static string[] XmlNamespaces(string path) { - XDocument z = XDocument.Load(path); - if (z.Root != null) - { - var namespaces = z.Root.Attributes(). - Where(a => a.IsNamespaceDeclaration). - GroupBy( - a => a.Name.Namespace == XNamespace.None ? string.Empty : a.Name.LocalName, - a => XNamespace.Get(a.Value) - ).Select( - g => g.First().ToString() - ).ToArray(); - return namespaces; - } - else - { - //_log.Error($"Error occurred while trying to get the XML from '{path}'", new ArgumentNullException()); - return Array.Empty(); - } + var document = XDocument.Load(path); + if (document.Root == null) return Array.Empty(); + + var namespaces = document.Root.Attributes(). + Where(a => a.IsNamespaceDeclaration). + GroupBy( + a => a.Name.Namespace == XNamespace.None ? string.Empty : a.Name.LocalName, + a => XNamespace.Get(a.Value) + ).Select( + g => g.First().ToString() + ).ToArray(); + return namespaces; } internal static string GetAppUserModelId(Package package) @@ -199,51 +189,37 @@ internal static string LogoPathFromUri(string uri, string location, string theme { return selected; } - else - { - int appIconSize = 36; - var targetSizes = new List { 16, 24, 30, 36, 44, 60, 72, 96, 128, 180, 256 }.AsParallel(); - Dictionary pathFactorPairs = new Dictionary(); - - foreach (var factor in targetSizes) - { - string simplePath = $"{prefix}.targetsize-{factor}{extension}"; - string suffixThemePath = $"{prefix}.targetsize-{factor}_{theme}{extension}"; - string prefixThemePath = $"{prefix}.{theme}_targetsize-{factor}{extension}"; - paths.Add(simplePath); - paths.Add(suffixThemePath); - paths.Add(prefixThemePath); + var appIconSize = 36; + var targetSizes = new List { 16, 24, 30, 36, 44, 60, 72, 96, 128, 180, 256 }.AsParallel(); + var pathFactorPairs = new Dictionary(); - pathFactorPairs.Add(simplePath, factor); - pathFactorPairs.Add(suffixThemePath, factor); - pathFactorPairs.Add(prefixThemePath, factor); - } + foreach (var factor in targetSizes) + { + var simplePath = $"{prefix}.targetsize-{factor}{extension}"; + var suffixThemePath = $"{prefix}.targetsize-{factor}_{theme}{extension}"; + var prefixThemePath = $"{prefix}.{theme}_targetsize-{factor}{extension}"; - paths = paths.OrderByDescending(x => x.Contains(theme)).ToList(); - var selectedIconPath = paths.OrderBy(x => - { - var val = pathFactorPairs.ContainsKey(x) ? pathFactorPairs[x] : default; - return Math.Abs(val - appIconSize); - }).FirstOrDefault(File.Exists); + paths.Add(simplePath); + paths.Add(suffixThemePath); + paths.Add(prefixThemePath); - if (!string.IsNullOrEmpty(selectedIconPath)) - { - return selectedIconPath; - } - else - { - //_log.Warning($"{uwp.UserModelId} can't find logo uri for {uri} in package location: {uwp.Location}"); - return string.Empty; - } + pathFactorPairs.Add(simplePath, factor); + pathFactorPairs.Add(suffixThemePath, factor); + pathFactorPairs.Add(prefixThemePath, factor); } + + paths = paths.OrderByDescending(x => x.Contains(theme)).ToList(); + var selectedIconPath = paths.OrderBy(x => + { + var val = pathFactorPairs.ContainsKey(x) ? pathFactorPairs[x] : default; + return Math.Abs(val - appIconSize); + }).FirstOrDefault(File.Exists); + + return !string.IsNullOrEmpty(selectedIconPath) ? selectedIconPath : string.Empty; } - else - { - //_log.Error($"|Unable to find extension from {uri} for {UserModelId} " - // + $"in package location {location}", new FileNotFoundException()); - return string.Empty; - } + + return string.Empty; } [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] diff --git a/src/Lanceur/Utils/PackagedApps/PackagedAppManager.cs b/src/Lanceur/Utils/PackagedApps/PackagedAppManager.cs index c3a5c4f4..6e5152f2 100644 --- a/src/Lanceur/Utils/PackagedApps/PackagedAppManager.cs +++ b/src/Lanceur/Utils/PackagedApps/PackagedAppManager.cs @@ -1,6 +1,6 @@ -using System; -using Lanceur.Core.Managers; +using Lanceur.Core.Managers; using Lanceur.Core.Responses; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -61,9 +61,9 @@ where p.HasInstallationPath() && p.IsInDirectory(srcDir) select p).ToList(); - var currentPkg = results.FirstOrDefault() + var currentPkg = results.FirstOrDefault() ?? throw new NullReferenceException($"No package for '{fileName}' found for the current user"); - + _cache.Add(fileName, currentPkg); return currentPkg; }); diff --git a/src/Lanceur/Utils/StaticLoggerFactory.cs b/src/Lanceur/Utils/StaticLoggerFactory.cs new file mode 100644 index 00000000..28935789 --- /dev/null +++ b/src/Lanceur/Utils/StaticLoggerFactory.cs @@ -0,0 +1,35 @@ +using Lanceur.Core.Models; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; +using Splat; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Lanceur.Utils +{ + internal static class StaticLoggerFactory + { + #region Methods + + public static ILogger GetLogger() => + Locator.Current.GetService().GetLogger(typeof(TCategory)); + + public static ILogger GetLogger(this QueryResult _) => GetLogger(); + + #endregion Methods + } + + internal class DefaultLoggerFactory : ILoggerFactory + { + #region Methods + + public void AddProvider(ILoggerProvider provider) + { } + + public ILogger CreateLogger(string categoryName) => new TraceLogger(); + + public void Dispose() + { } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Lanceur/Views/AppSettingsViewModel.cs b/src/Lanceur/Views/AppSettingsViewModel.cs index bb42a694..e26e5806 100644 --- a/src/Lanceur/Views/AppSettingsViewModel.cs +++ b/src/Lanceur/Views/AppSettingsViewModel.cs @@ -4,6 +4,7 @@ using Lanceur.Core.Repositories.Config; using Lanceur.Core.Services; using Lanceur.Infra.Managers; +using Lanceur.Infra.Win32.Restart; using Lanceur.Schedulers; using Lanceur.Ui; using ReactiveUI; @@ -15,7 +16,6 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; -using Lanceur.Infra.Win32.Restart; namespace Lanceur.Views { diff --git a/src/Lanceur/Views/DoubloonsViewModel.cs b/src/Lanceur/Views/DoubloonsViewModel.cs index 55e13767..7bde5639 100644 --- a/src/Lanceur/Views/DoubloonsViewModel.cs +++ b/src/Lanceur/Views/DoubloonsViewModel.cs @@ -79,17 +79,19 @@ public DoubloonsViewModel( #endregion Constructors #region Properties + [Reactive] private bool IsActivating { get; set; } public ReactiveCommand> Activate { get; private set; } - + public ViewModelActivator Activator { get; } = new(); public Interaction ConfirmRemove => _confirmRemove; [Reactive] public ObservableCollection Doubloons { get; set; } - public ReactiveCommand RemoveSelected { get; private set;} + public ReactiveCommand RemoveSelected { get; private set; } #endregion Properties #region Methods + private ObservableCollection OnActivate() { var doubloons = _service.GetDoubloons().ToArray(); diff --git a/src/Lanceur/Views/HistoryView.xaml.cs b/src/Lanceur/Views/HistoryView.xaml.cs index c2a778cc..1ce0bbc5 100644 --- a/src/Lanceur/Views/HistoryView.xaml.cs +++ b/src/Lanceur/Views/HistoryView.xaml.cs @@ -1,4 +1,5 @@ using Lanceur.Utils; +using Microsoft.Extensions.Logging; using ReactiveUI; using System; using System.Linq; @@ -38,7 +39,7 @@ public HistoryView() History.Plot.Legend(); History.Refresh(); } - else { AppLogFactory.Get().Warning("No history to display."); } + else { StaticLoggerFactory.GetLogger().LogWarning("No history to display"); } }; ViewModel.Activate.Execute().Subscribe(); diff --git a/src/Lanceur/Views/HistoryViewModel.cs b/src/Lanceur/Views/HistoryViewModel.cs index 2e102375..653f0849 100644 --- a/src/Lanceur/Views/HistoryViewModel.cs +++ b/src/Lanceur/Views/HistoryViewModel.cs @@ -1,8 +1,9 @@ using Lanceur.Core.Repositories; using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; using Lanceur.Schedulers; using Lanceur.Ui; +using Microsoft.Extensions.Logging; using ReactiveUI; using Splat; using System; @@ -16,7 +17,7 @@ public class HistoryViewModel : RoutableViewModel { #region Fields - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly ISchedulerProvider _schedulers; private readonly IDbRepository _service; @@ -27,13 +28,13 @@ public class HistoryViewModel : RoutableViewModel public HistoryViewModel( ISchedulerProvider schedulers = null, IDbRepository service = null, - IAppLoggerFactory logFactory = null, + ILoggerFactory logFactory = null, IUserNotification notify = null) { var l = Locator.Current; _schedulers = schedulers ?? l.GetService(); _service = service ?? l.GetService(); - _log = l.GetLogger(logFactory); + _logger = logFactory.GetLogger(); notify ??= l.GetService(); Activate = ReactiveCommand.Create(OnActivate, outputScheduler: _schedulers.MainThreadScheduler); @@ -54,11 +55,11 @@ public HistoryViewModel( private void OnActivate() { - var history = _service.GetUsage(Per.Day); - _log.Trace($"Loaded {history.Count()} item(s) from history"); + var history = _service.GetUsage(Per.Day).ToList(); + _logger.LogDebug("Loaded {Count} item(s) from history", history.Count); - var x = history.Select(x => x.X.ToOADate()); - var y = history.Select(x => x.Y); + var x = history.Select(p => p.X.ToOADate()); + var y = history.Select(p => p.Y); OnRefreshChart(x, y); } diff --git a/src/Lanceur/Views/KeywordsView.xaml.cs b/src/Lanceur/Views/KeywordsView.xaml.cs index 8fe5b4a0..b88344e0 100644 --- a/src/Lanceur/Views/KeywordsView.xaml.cs +++ b/src/Lanceur/Views/KeywordsView.xaml.cs @@ -1,4 +1,5 @@ using Lanceur.Converters.Reactive; +using Lanceur.Infra.Logging; using Lanceur.Ui; using Lanceur.Utils; using ReactiveUI; @@ -23,7 +24,7 @@ public KeywordsView() this.WhenActivated(d => { - AppLogFactory.Get().Trace($"Activating {nameof(KeywordsView)}"); + StaticLoggerFactory.GetLogger().LogActivate(); ViewModel.AskLuaEditor.RegisterHandler(interaction => { @@ -50,8 +51,8 @@ public KeywordsView() this.OneWayBind(ViewModel, vm => vm.IsBusy, v => v.BusyControl.Visibility).DisposeWith(d); this.OneWayBind(ViewModel, vm => vm.IsBusy, v => v.AliasList.Visibility, val => val.ToVisibilityInverted()).DisposeWith(d); this.OneWayBind( - ViewModel, - vm => vm.SelectedAlias, + ViewModel, + vm => vm.SelectedAlias, v => v.BtnDeleteAlias.Content, val => val is null ? "Delete" : val.Id == 0 ? "Discard" : "Delete").DisposeWith(d); diff --git a/src/Lanceur/Views/KeywordsViewModel.cs b/src/Lanceur/Views/KeywordsViewModel.cs index a43e790e..03f47418 100644 --- a/src/Lanceur/Views/KeywordsViewModel.cs +++ b/src/Lanceur/Views/KeywordsViewModel.cs @@ -5,11 +5,12 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; using Lanceur.Schedulers; using Lanceur.SharedKernel; using Lanceur.SharedKernel.Mixins; using Lanceur.Ui; +using Microsoft.Extensions.Logging; using ReactiveUI; using ReactiveUI.Fody.Helpers; using ReactiveUI.Validation.Abstractions; @@ -35,7 +36,7 @@ public class KeywordsViewModel : RoutableViewModel, IValidatableViewModel, IActi private readonly SourceList _aliases = new(); private readonly IDbRepository _aliasService; private readonly Scope _busyScope; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly INotification _notification; private readonly IUserNotification _notify; private readonly IPackagedAppSearchService _packagedAppSearchService; @@ -47,7 +48,7 @@ public class KeywordsViewModel : RoutableViewModel, IValidatableViewModel, IActi #region Constructors public KeywordsViewModel( - IAppLoggerFactory logFactory = null, + ILoggerFactory logFactory = null, IDbRepository searchService = null, ISchedulerProvider schedulers = null, IUserNotification notify = null, @@ -62,7 +63,7 @@ public KeywordsViewModel( _notify = notify ?? l.GetService(); _packagedAppSearchService = packagedAppSearchService ?? l.GetService(); _notification = notification ?? l.GetService(); - _log = l.GetLogger(logFactory); + _logger = logFactory.GetLogger(); _thumbnailManager = thumbnailManager ?? l.GetService(); _aliasService = searchService ?? l.GetService(); @@ -132,18 +133,19 @@ private async Task OnEditLuaScript() private async Task OnRemoveAliasAsync(AliasQueryResult alias) { + using var _ = _logger.BeginSingleScope("RemovedAlias", alias); if (alias == null) return Unit.Default; var remove = await ConfirmRemove.Handle(alias.Name); if (remove) { - _log.Info($"User removed alias '{alias.Name}'"); + _logger.LogInformation("User removed alias {Name}", alias.Name); _aliasService.Remove(alias); if (_aliases.Remove(alias)) { _notification.Information($"Removed alias '{alias.Name}'."); } - else { _log.Warning($"Impossible to remove the alias '{alias.Name}'"); } + else { _logger.LogWarning("Impossible to remove the alias {Name}", alias.Name); } } - else { _log.Debug($"User cancelled the remove of '{alias.Name}'."); } + else { _logger.LogDebug("User cancelled the remove of {Name}", alias.Name); } return Unit.Default; } @@ -168,7 +170,7 @@ private AliasQueryResult OnSaveOrUpdateAlias(AliasQueryResult alias) } catch (ApplicationException ex) { - _log.Warning(ex.Message); + _logger.LogWarning(ex, "An error occured while saving or updating alias"); _notify.Warning($"Error when {(created ? "creating" : "updating")} the alias: {ex.Message}"); return alias; } @@ -288,7 +290,7 @@ private void SetupValidations(CompositeDisposable d) response => { if (response == null) return "The names should not be empty."; - + return !response.Exists && !response.ExistingNames.Any() ? "The names should not be empty." : $"'{response.ExistingNames.JoinCsv()}' {(response.ExistingNames.Length <= 1 ? "is" : "are")} already used as alias."; @@ -298,6 +300,7 @@ private void SetupValidations(CompositeDisposable d) private void UpdateAliasWithSynonyms(AliasQueryResult alias) { + using var _ = _logger.BeginSingleScope("UpdatedAlias", alias); var toDel = _aliases.Items .Where(a => a.Id == alias.Id) .ToArray(); @@ -308,20 +311,19 @@ private void UpdateAliasWithSynonyms(AliasQueryResult alias) var names = alias.Synonyms.SplitCsv(); var errors = new List(); - + foreach (var name in names) { try { - _log.Trace($"Cloning alias (type: '{alias.GetType()}'. Thumbnail: '{alias.Thumbnail}'"); var toAdd = alias.CloneObject(); toAdd.Name = name; - _log.Trace($"Add cloned object (which is a synonym) to the list of alias (name: '{name}')"); + _logger.LogDebug("Add cloned object (which is a synonym) to the list of alias (name: {Name})", name); _aliases.Add(toAdd); } catch (Exception ex) { - _log.Warning($"Error occured while cloning object of type '{alias.GetType()}' with name '{name}'", ex); + _logger.LogWarning(ex, "Error occured while cloning {Name}", name); errors.Add(ex); } } diff --git a/src/Lanceur/Views/LuaEditorView.xaml b/src/Lanceur/Views/LuaEditorView.xaml index 1d6b9488..de2c9096 100644 --- a/src/Lanceur/Views/LuaEditorView.xaml +++ b/src/Lanceur/Views/LuaEditorView.xaml @@ -105,4 +105,4 @@ Content="Cancel" /> - + \ No newline at end of file diff --git a/src/Lanceur/Views/LuaEditorView.xaml.cs b/src/Lanceur/Views/LuaEditorView.xaml.cs index 2833f3a3..80949c0e 100644 --- a/src/Lanceur/Views/LuaEditorView.xaml.cs +++ b/src/Lanceur/Views/LuaEditorView.xaml.cs @@ -14,7 +14,12 @@ namespace Lanceur.Views /// public partial class LuaEditorView : Window { + #region Fields + private Script _luaCode; + + #endregion Fields + #region Constructors public LuaEditorView() diff --git a/src/Lanceur/Views/MainView.xaml b/src/Lanceur/Views/MainView.xaml index e3b80d3d..41714f52 100644 --- a/src/Lanceur/Views/MainView.xaml +++ b/src/Lanceur/Views/MainView.xaml @@ -134,8 +134,8 @@ MaxHeight="{StaticResource ResultBoxHeight}" HorizontalContentAlignment="Stretch" Background="Transparent" - ItemTemplateSelector="{StaticResource QueryResultSelector}" - ScrollViewer.HorizontalScrollBarVisibility="Disabled"/> + ItemTemplateSelector="{StaticResource QueryResultSelector}" + ScrollViewer.HorizontalScrollBarVisibility="Disabled" /> diff --git a/src/Lanceur/Views/MainView.xaml.cs b/src/Lanceur/Views/MainView.xaml.cs index e1bd65aa..b16097ab 100644 --- a/src/Lanceur/Views/MainView.xaml.cs +++ b/src/Lanceur/Views/MainView.xaml.cs @@ -2,11 +2,12 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories.Config; using Lanceur.Core.Requests; -using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; +using Lanceur.Infra.Win32.Utils; using Lanceur.SharedKernel.Mixins; using Lanceur.Utils; using Lanceur.Views.Mixins; +using Microsoft.Extensions.Logging; using NHotkey; using NHotkey.Wpf; using ReactiveUI; @@ -20,9 +21,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using System.Windows.Media; using System.Windows.Media.Animation; -using Lanceur.Infra.Win32.Utils; namespace Lanceur.Views { @@ -33,9 +32,9 @@ public partial class MainView : IViewFor { #region Fields + private readonly ILogger _logger; private readonly IAppConfigRepository _settings; private bool _isStoryBoardsFree = true; - private readonly IAppLogger _log; #endregion Fields @@ -45,11 +44,11 @@ public MainView() : this(null, null) { } - public MainView(IAppLoggerFactory factory, IAppConfigRepository settings) + public MainView(ILoggerFactory factory, IAppConfigRepository settings) { InitializeComponent(); - _log = Locator.Current.GetLogger(factory); + _logger = factory.GetLogger(); ViewModel = Locator.Current.GetService(); _settings = settings ?? Locator.Current.GetService(); @@ -178,14 +177,14 @@ where s.GetHashCode() == alias.GetHashCode() private void OnFadeInStoryBoardCompleted(object sender, EventArgs e) { _isStoryBoardsFree = true; - _log.Trace("Fade in Storyboard completed..."); + _logger.LogTrace("Fade in Storyboard completed..."); Visibility = Visibility.Visible; } private void OnFadeOutStoryBoardCompleted(object sender, EventArgs e) { _isStoryBoardsFree = true; - _log.Trace("Fade out Storyboard completed..."); + _logger.LogTrace("Fade out Storyboard completed..."); Visibility = Visibility.Collapsed; } @@ -193,7 +192,8 @@ private void OnPreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Up || e.Key == Key.Down) { - var collection = QueryResults.ItemsSource.Cast(); + var collection = QueryResults.ItemsSource + .Cast().ToList(); if (collection.CanNavigate() == false) { e.Handled = false; } else @@ -251,23 +251,23 @@ private void OnWindowMouseDown(object sender, MouseButtonEventArgs e) if (e.ChangedButton == MouseButton.Left) { DragMove(); } } - private void SetShortcut(Key key, ModifierKeys modifyer) + private void SetShortcut(Key key, ModifierKeys modifier) { try { - HotkeyManager.Current.AddOrReplace("OnShowWindow", key, modifyer, OnShowWindow); + HotkeyManager.Current.AddOrReplace("OnShowWindow", key, modifier, OnShowWindow); } catch (HotkeyAlreadyRegisteredException ex) { //Default values - _log?.Warning(ex.Message); + _logger.LogWarning(ex, "Impossible to set shortcut. (Key: {Key}, Modifier: {Modifier})", key, modifier); SetShortcut(Key.R, ModifierKeys.Shift | ModifierKeys.Windows); } } protected override void OnDeactivated(EventArgs e) { - _log?.Info("Window deactivated"); + _logger.LogInformation("Window deactivated"); HideControl(); } @@ -275,23 +275,22 @@ public void HideControl() { QueryTextBox.Text = string.Empty; - if (_isStoryBoardsFree) - { - _isStoryBoardsFree = false; - var storyBoard = FindResource("fadeOutStoryBoard") as Storyboard; - storyBoard.Begin(this); - } + if (!_isStoryBoardsFree) return; + + _isStoryBoardsFree = false; + var storyBoard = FindResource("fadeOutStoryBoard") as Storyboard; + storyBoard!.Begin(this); } public void ShowWindow() { - _log?.Info("Window showing"); - ViewModel.Activate.Execute().Subscribe(); + _logger.LogInformation("Window showing"); + ViewModel!.Activate.Execute().Subscribe(); if (_isStoryBoardsFree) { _isStoryBoardsFree = false; var storyBoard = FindResource("fadeInStoryBoard") as Storyboard; - storyBoard.Begin(this); + storyBoard!.Begin(this); Visibility = Visibility.Visible; QueryTextBox.Focus(); diff --git a/src/Lanceur/Views/MainViewModel.cs b/src/Lanceur/Views/MainViewModel.cs index 8f031521..8ff68d78 100644 --- a/src/Lanceur/Views/MainViewModel.cs +++ b/src/Lanceur/Views/MainViewModel.cs @@ -5,9 +5,10 @@ using Lanceur.Core.Repositories.Config; using Lanceur.Core.Requests; using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; using Lanceur.Schedulers; using Lanceur.SharedKernel.Mixins; +using Microsoft.Extensions.Logging; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Splat; @@ -27,7 +28,7 @@ public partial class MainViewModel : ReactiveObject private readonly ICmdlineManager _cmdlineManager; private readonly IDbRepository _dbRepository; private readonly IExecutionManager _executor; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly ISearchService _searchService; private readonly ISettingsFacade _settingsFacade; @@ -37,7 +38,7 @@ public partial class MainViewModel : ReactiveObject public MainViewModel( ISchedulerProvider schedulerProvider = null, - IAppLoggerFactory logFactory = null, + ILoggerFactory loggerFactory = null, ISearchService searchService = null, ICmdlineManager cmdlineService = null, IUserNotification notify = null, @@ -49,7 +50,7 @@ public MainViewModel( var l = Locator.Current; notify ??= l.GetService(); - _log = Locator.Current.GetLogger(logFactory); + _logger = loggerFactory.GetLogger(); _searchService = searchService ?? l.GetService(); _cmdlineManager = cmdlineService ?? l.GetService(); _dbRepository = dataService ?? l.GetService(); @@ -246,7 +247,9 @@ private AliasResponse OnActivate() ? _searchService.GetAll().ToArray() : Array.Empty(); - _log.Trace($"{(_settingsFacade.Application.Window.ShowResult ? $"View activation: show all {aliases.Length} result(s)" : "View activation: display nothing")}"); + _logger.LogInformation( + "MainViewModel activated. There is {Length} alias(es) to show. (Show all results on search box show: {ShowResult})", + aliases.Length, _settingsFacade.Application.Window.ShowResult); return new() { CurrentSessionName = sessionName, @@ -259,6 +262,7 @@ private AliasResponse OnActivate() private async Task OnExecuteAliasAsync(AliasExecutionRequest request) { request ??= new(); + using var _ = _logger.BeginSingleScope("ExecuteAliasRequest", request); if (request.AliasToExecute is null) { return new(); } @@ -269,11 +273,10 @@ private async Task OnExecuteAliasAsync(AliasExecutionRequest requ ExecuteWithPrivilege = request.RunAsAdmin, }); - _log.Trace($"Execution of '{request.Query}' returned {(response?.Results?.Count() ?? 0)} result(s)."); return new() { - Results = response?.Results ?? Array.Empty(), - KeepAlive = response?.HasResult ?? false + Results = response.Results ?? Array.Empty(), + KeepAlive = response.HasResult }; } @@ -294,12 +297,12 @@ private Task OnSearchAliasAsync(string criterion) var query = _cmdlineManager.BuildFromText(criterion); - _log.Debug($"Search: criterion '{criterion}'"); + _logger.LogInformation("Search criterion: {Criterion}", criterion); var results = _searchService.Search(query) .ToArray(); - _log.Trace($"Search: Found {results.Length} element(s)"); + _logger.LogDebug("Search: Found {Length} element(s)", results.Length); return new AliasResponse() { Results = results, @@ -313,7 +316,7 @@ private NavigationResponse OnSelectNextResult() var currentIndex = Results.IndexOf(GetCurrentAlias()); var nextAlias = Results.GetNextItem(currentIndex); - _log.Trace($"Selecting next result. [Index: {nextAlias?.Name}]"); + _logger.LogTrace("Selecting next result. [Index: {Name}]", nextAlias.Name); return NavigationResponse.InactiveFromResult(nextAlias); } @@ -324,7 +327,7 @@ private NavigationResponse OnSelectPreviousResult() var currentIndex = Results.IndexOf(GetCurrentAlias()); var previousAlias = Results.GetPreviousItem(currentIndex); - _log.Trace($"Selecting previous result. [Index: {previousAlias?.Name}]"); + _logger.LogTrace("Selecting previous result. [Index: {Name}]", previousAlias.Name); return NavigationResponse.InactiveFromResult(previousAlias); } diff --git a/src/Lanceur/Views/PluginsViewModel.cs b/src/Lanceur/Views/PluginsViewModel.cs index db25f122..2978088c 100644 --- a/src/Lanceur/Views/PluginsViewModel.cs +++ b/src/Lanceur/Views/PluginsViewModel.cs @@ -1,10 +1,10 @@ using Lanceur.Core.Plugins; using Lanceur.Core.Repositories; using Lanceur.Core.Services; +using Lanceur.Infra.Win32.Restart; using Lanceur.Schedulers; using Lanceur.SharedKernel.Mixins; using Lanceur.Ui; -using Lanceur.Utils; using Lanceur.Views.Mixins; using ReactiveUI; using ReactiveUI.Fody.Helpers; @@ -16,7 +16,6 @@ using System.Reactive; using System.Reactive.Linq; using System.Threading.Tasks; -using Lanceur.Infra.Win32.Restart; namespace Lanceur.Views; diff --git a/src/Lanceur/Views/SessionsViewModel.cs b/src/Lanceur/Views/SessionsViewModel.cs index 7b23dfa9..8e4b0713 100644 --- a/src/Lanceur/Views/SessionsViewModel.cs +++ b/src/Lanceur/Views/SessionsViewModel.cs @@ -2,10 +2,11 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; using Lanceur.Models; using Lanceur.Schedulers; using Lanceur.Ui; +using Microsoft.Extensions.Logging; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Splat; @@ -25,7 +26,7 @@ public class SessionsViewModel : RoutableViewModel private readonly IDbRepository _aliasService; private readonly Interaction _confirmRemove; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly INotification _notification; private readonly ISchedulerProvider _schedulers; private readonly IThumbnailManager _thumbnailManager; @@ -36,7 +37,7 @@ public class SessionsViewModel : RoutableViewModel public SessionsViewModel( ISchedulerProvider schedulers = null, - IAppLoggerFactory logFactory = null, + ILoggerFactory logFactory = null, IDbRepository aliasService = null, IUserNotification notify = null, IThumbnailManager thumbnailManager = null, @@ -44,7 +45,7 @@ public SessionsViewModel( { var l = Locator.Current; notify ??= l.GetService(); - _log = l.GetLogger(logFactory); + _logger = logFactory.GetLogger(); _schedulers = schedulers ?? l.GetService(); _aliasService = aliasService ?? l.GetService(); _thumbnailManager = thumbnailManager ?? l.GetService(); @@ -155,7 +156,7 @@ private async Task OnRemoveSessionAsync(SessionModel session) if (delete) { _aliasService.Remove(session.ToEntity()); - _log.Trace($"Removed session with id '{session?.Id ?? -1}'"); + _logger.LogInformation("Removed session with id {Id}", session.Id); _notification.Information($"Session '{session.Name}' removed."); return session; } @@ -164,22 +165,19 @@ private async Task OnRemoveSessionAsync(SessionModel session) private SessionModel OnSaveSession(SessionModel session) { - if (session is not null) + if (session is null) { - _log.Trace($"Save session {session.Id}"); - var entity = session.ToEntity(); - - _aliasService.Update(ref entity); - - session.Id = entity.Id; - _notification.Information($"Session '{session.Name}' updated."); - return session; - } - else - { - _log.Warning($"Trying to change the default session to a null."); + _logger.LogWarning("Trying to change the default session to a null"); return null; } + + var entity = session.ToEntity(); + + _notification.Information($"Updating session {session.Name}"); + _aliasService.Update(ref entity); + + session.Id = entity.Id; + return session; } #endregion Methods diff --git a/src/Lanceur/Views/SettingsViewModel.cs b/src/Lanceur/Views/SettingsViewModel.cs index 97ee978a..248acfdb 100644 --- a/src/Lanceur/Views/SettingsViewModel.cs +++ b/src/Lanceur/Views/SettingsViewModel.cs @@ -1,7 +1,8 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Services; -using Lanceur.Infra.Utils; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Splat; @@ -17,7 +18,7 @@ public class SettingsViewModel : ReactiveObject, IScreen private readonly HistoryViewModel _historyVm; private readonly InvalidAliasViewModel _invalidAliasVm; private readonly KeywordsViewModel _keywordVm; - private readonly IAppLogger _log; + private readonly ILogger _logger; private readonly MostUsedViewModel _mostUsedVm; private readonly PluginsViewModel _pluginsViewModel; private readonly IDbRepository _service; @@ -30,7 +31,7 @@ public class SettingsViewModel : ReactiveObject, IScreen #region Constructors public SettingsViewModel( - IAppLoggerFactory logFactory = null, + ILoggerFactory logFactory = null, KeywordsViewModel keywordVm = null, SessionsViewModel sessionsVm = null, AppSettingsViewModel settingsVm = null, @@ -47,7 +48,7 @@ public SettingsViewModel( Router = l.GetService(); notify ??= l.GetService(); - _log = l.GetLogger(logFactory); + _logger = logFactory.GetLogger(); _keywordVm = keywordVm ?? l.GetService(); _sessionsVm = sessionsVm ?? l.GetService(); _settingsVm = settingsVm ?? l.GetService(); @@ -85,14 +86,15 @@ public SettingsViewModel( private IObservable OnAddAlias(string aliasName) { _keywordVm.AliasToCreate = AliasQueryResult.FromName(aliasName); - _log.Debug($"Request creation of alias '{aliasName}'"); + _logger.LogDebug("Request creation of alias {AliasName}", aliasName); return Router.Navigate.Execute(_keywordVm); } - private IObservable OnPushNavigation(string arg) + private IObservable OnPushNavigation(string route) { - _log.Trace($"Navigate to '{arg ?? ""}'"); - switch (arg.ToLower()) + route ??= ""; + _logger.LogInformation("Navigate to {Route}", route); + switch (route.ToLower()) { case "keywordsview": var sessionName = _service.GetDefaultSession()?.FullName ?? "N.A."; @@ -132,7 +134,7 @@ private IObservable OnPushNavigation(string arg) return Router.Navigate.Execute(_pluginsViewModel); default: - Title = $"The view '{arg}' do not exist."; + Title = $"The view '{route}' do not exist."; return Router.Navigate.Execute(_settingsVm); } } diff --git a/src/Lanceur/Views/TrendsView.xaml.cs b/src/Lanceur/Views/TrendsView.xaml.cs index e9d42470..d8423465 100644 --- a/src/Lanceur/Views/TrendsView.xaml.cs +++ b/src/Lanceur/Views/TrendsView.xaml.cs @@ -1,4 +1,5 @@ using Lanceur.Utils; +using Microsoft.Extensions.Logging; using ReactiveUI; using ScottPlot; using System; @@ -47,7 +48,7 @@ private static void SetChart(WpfPlot ctrl, IEnumerable days, IEnumerable ctrl.Plot.Legend(); ctrl.Refresh(); } - else { AppLogFactory.Get().Warning("No history to display."); } + else { StaticLoggerFactory.GetLogger().LogWarning("No history to display"); } } #endregion Methods diff --git a/src/Lanceur/Xaml/Styles.xaml b/src/Lanceur/Xaml/Styles.xaml index de1e8e90..28c805e7 100644 --- a/src/Lanceur/Xaml/Styles.xaml +++ b/src/Lanceur/Xaml/Styles.xaml @@ -1,8 +1,8 @@  + xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:sys="clr-namespace:System;assembly=mscorlib"> 0:0:0:0.03 0:0:0:0.25 diff --git a/src/Lanceur/Xaml/Templates.xaml b/src/Lanceur/Xaml/Templates.xaml index d1df333c..8334f342 100644 --- a/src/Lanceur/Xaml/Templates.xaml +++ b/src/Lanceur/Xaml/Templates.xaml @@ -1,10 +1,10 @@  + xmlns:vm="clr-namespace:Lanceur.Core.Models;assembly=Lanceur.Core" + xmlns:p="clr-namespace:Lanceur.Core.Plugins;assembly=Lanceur.Core"> diff --git a/src/Lanceur/Xaml/ThemeManager.cs b/src/Lanceur/Xaml/ThemeManager.cs index 627d3144..421f9b5a 100644 --- a/src/Lanceur/Xaml/ThemeManager.cs +++ b/src/Lanceur/Xaml/ThemeManager.cs @@ -1,7 +1,8 @@ using ControlzEx.Theming; -using Lanceur.Core.Services; -using Lanceur.Utils; +using Lanceur.Infra.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Win32; +using Splat; using System; using System.Collections.Generic; using System.Windows; @@ -14,9 +15,9 @@ internal class ThemeManager private const string DarkTheme = "Dark.Accent1"; private const string LightTheme = "Light.Accent1"; - private static readonly IAppLogger Log = AppLogFactory.Get(); - private Application _app; private static ThemeManager _instance; + private readonly ILogger _logger; + private Application _app; #endregion Fields @@ -24,6 +25,7 @@ internal class ThemeManager private ThemeManager(Application app) { + _logger = Locator.Current.GetService().GetLogger(); _app = app; var lightThemeUri = new Uri("pack://application:,,,/Xaml/Themes/LightTheme.xaml"); @@ -106,7 +108,7 @@ public void SetTheme(Themes? theme = null) _ => throw new NotSupportedException($"The theme '{theme}' is not supported!") }; - Log.Trace($"Applying theme '{themeToApply}'. Asked theme is '{theme}'"); + _logger.LogDebug("Applying theme {ThemeToApply}. Requested theme is {Theme}", themeToApply, theme); ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, themeToApply); } diff --git a/src/Tests/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs b/src/Tests/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs index 52797415..42ea4834 100644 --- a/src/Tests/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs +++ b/src/Tests/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs @@ -6,6 +6,7 @@ using Lanceur.Infra.SQLite; using Lanceur.Infra.SQLite.DbActions; using Lanceur.Tests.SQLite; +using Microsoft.Extensions.Logging; using NSubstitute; using System.Data.SQLite; using Xunit; @@ -36,7 +37,7 @@ private static AliasQueryResult BuildAlias(string name = null, RunAs runAs = Run private static AliasDbAction BuildAliasDbAction(SQLiteConnection connection) { var scope = new SQLiteSingleConnectionManager(connection); - var log = Substitute.For(); + var log = Substitute.For(); var action = new AliasDbAction(scope, log); return action; } @@ -44,7 +45,7 @@ private static AliasDbAction BuildAliasDbAction(SQLiteConnection connection) private static SQLiteRepository BuildDataService(SQLiteConnection connection) { var scope = new SQLiteSingleConnectionManager(connection); - var log = Substitute.For(); + var log = Substitute.For(); var conv = Substitute.For(); var service = new SQLiteRepository(scope, log, conv); return service; diff --git a/src/Tests/Lanceur.Tests/BusinessLogic/MacroShould.cs b/src/Tests/Lanceur.Tests/BusinessLogic/MacroShould.cs index 13896a02..5785962c 100644 --- a/src/Tests/Lanceur.Tests/BusinessLogic/MacroShould.cs +++ b/src/Tests/Lanceur.Tests/BusinessLogic/MacroShould.cs @@ -11,6 +11,7 @@ using Lanceur.Tests.SQLite; using Lanceur.Tests.Utils.Macros; using Lanceur.Utils; +using Microsoft.Extensions.Logging; using NSubstitute; using System.Data.SQLite; using System.Reflection; @@ -22,12 +23,21 @@ namespace Lanceur.Tests.BusinessLogic; public class MacroShould : SQLiteTest { + #region Fields + private readonly ITestOutputHelper _output; + #endregion Fields + + #region Constructors + public MacroShould(ITestOutputHelper output) { _output = output; } + + #endregion Constructors + #region Methods [Fact] @@ -36,7 +46,7 @@ public void BeCastedToSelfExecutableQueryResult() // ARRANGE var srcNamespace = typeof(MultiMacro).Namespace; var asm = Assembly.GetAssembly(typeof(MultiMacro)); - + var types = asm.GetTypes() .Where(type => { @@ -147,7 +157,7 @@ public void BeRecognisedAsAMacro() public void HaveDefaultMacro() { var asm = Assembly.GetAssembly(typeof(MultiMacro)); - var logFactory = Substitute.For(); + var logFactory = Substitute.For(); var repository = Substitute.For(); var manager = new MacroManager(asm, logFactory, repository); @@ -221,7 +231,7 @@ public void NotHaveDoubloonsWhenMacroUsedMultipleTimes() new() { Name = "macro_3", FileName = "@multi@" } }; - var logger = Substitute.For(); + var logger = Substitute.For(); var repository = Substitute.For(); var asm = Assembly.GetExecutingAssembly(); var manager = new MacroManager(asm, logger, repository); @@ -277,7 +287,7 @@ private static IConvertionService GetConversionService() public static IDbRepository GetDataService(SQLiteConnection db) { - var log = Substitute.For(); + var log = Substitute.For(); var conv = GetConversionService(); var service = new SQLiteRepository(new SQLiteSingleConnectionManager(db), log, conv); return service; diff --git a/src/Tests/Lanceur.Tests/BusinessLogic/SearchShould.cs b/src/Tests/Lanceur.Tests/BusinessLogic/SearchShould.cs index 729a05e6..ffa8e32a 100644 --- a/src/Tests/Lanceur.Tests/BusinessLogic/SearchShould.cs +++ b/src/Tests/Lanceur.Tests/BusinessLogic/SearchShould.cs @@ -12,6 +12,7 @@ using Lanceur.Tests.Logging; using Lanceur.Tests.SQLite; using Lanceur.Tests.Utils; +using Microsoft.Extensions.Logging; using NSubstitute; using Xunit; using Xunit.Abstractions; @@ -22,8 +23,6 @@ public class SearchShould : SQLiteTest { #region Fields - private readonly IAppLoggerFactory _testLoggerFactory; - private const string SqlCreateAlias = @" insert into alias (id, file_name, arguments, id_session) values (1000, '@multi@', '@alias2@@alias3', 1); insert into alias_name (id, id_alias, name) values (1000, 1000, 'alias1'); @@ -34,13 +33,15 @@ public class SearchShould : SQLiteTest insert into alias (id, file_name, arguments,id_session) values (3000, 'arg', 'c:\dummy\dummy.exe', 1); insert into alias_name (id, id_alias, name) values (3000, 3000, 'alias3');"; + private readonly ILoggerFactory _testLoggerFactory; + #endregion Fields #region Constructors public SearchShould(ITestOutputHelper output) { - _testLoggerFactory = new XUnitLoggerFactory(output); + _testLoggerFactory = new MicrosoftLoggingLoggerFactory(output); } #endregion Constructors @@ -74,36 +75,49 @@ public void NOT_HaveNullParameters() } [Fact] - public void ReturnValues() + public void ReturnNoResultMessageWhenMisconfiguredMacro() { - var macroManager = Substitute.For(); + // ARRANGE + const string sql = SqlCreateAlias + + @" + insert into alias (id, file_name, id_session) values (4000, '@zzzz@', 1); + insert into alias_name (id, id_alias, name) values (4000, 4000, 'zz');"; + + using var db = BuildFreshDb(sql); + using var conn = new SQLiteSingleConnectionManager(db); + var thumbnailManager = Substitute.For(); - var service = new SearchService(new DebugStoreLoader(), macroManager, thumbnailManager); - var query = new Cmdline("code"); + var converter = Substitute.For(); + var repository = new SQLiteRepository(conn, _testLoggerFactory, converter); + var storeLoader = Substitute.For(); + storeLoader.Load().Returns(new[] { new AliasStore(repository) }); - var result = service.Search(query) - .ToArray(); + var asm = Assembly.GetExecutingAssembly(); + var service = new SearchService(storeLoader, new MacroManager(asm, repository: repository), thumbnailManager); + // ACT + var result = service.Search(new("z")).ToArray(); + + // ASSERT using (new AssertionScope()) { - result.Should().HaveCount(1); - result.ElementAt(0).IsResult.Should().BeFalse(); + result.Should().HaveCountGreaterThan(0); + result[0].Name.Should().Be("No result found"); } } [Fact] public void ReturnResultWithExactMatchOnTop() { - - var dt = DateTime.Now; + var dt = DateTime.Now; var converter = Substitute.For(); var sql = @$" insert into alias (id, file_name, arguments, id_session) values (1000, 'un', '@alias2@@alias3', 1); insert into alias_name (id, id_alias, name) values (1001, 1000, 'un'); - + insert into alias (id, file_name, arguments, id_session) values (2000, 'deux', '@alias2@@alias3', 1); insert into alias_name (id, id_alias, name) values (1002, 2000, 'deux'); - + insert into alias (id, file_name, arguments, id_session) values (3000, 'trois', '@alias2@@alias3', 1); insert into alias_name (id, id_alias, name) values (1003, 3000, 'trois'); -- @@ -124,7 +138,7 @@ public void ReturnResultWithExactMatchOnTop() "; // ARRANGE - using var db = BuildFreshDb(sql); + using var db = BuildFreshDb(sql); using var conn = new SQLiteSingleConnectionManager(db); const string criterion = "u"; @@ -136,7 +150,7 @@ public void ReturnResultWithExactMatchOnTop() var macroManager = Substitute.For(); macroManager.Handle(Arg.Any()) .Returns(results); - + var searchService = new SearchService( stores, macroManager, @@ -146,7 +160,7 @@ public void ReturnResultWithExactMatchOnTop() // ACT var result = searchService.Search(new(criterion)) .ToArray(); - + // ASSERT using (new AssertionScope()) { @@ -157,37 +171,23 @@ public void ReturnResultWithExactMatchOnTop() } [Fact] - public void ReturnNoResultMessageWhenMisconfiguredMacro() + public void ReturnValues() { - // ARRANGE - const string sql = SqlCreateAlias - + @" - insert into alias (id, file_name, id_session) values (4000, '@zzzz@', 1); - insert into alias_name (id, id_alias, name) values (4000, 4000, 'zz');"; - - using var db = BuildFreshDb(sql); - using var conn = new SQLiteSingleConnectionManager(db); - + var macroManager = Substitute.For(); var thumbnailManager = Substitute.For(); - var converter = Substitute.For(); - var repository = new SQLiteRepository(conn, _testLoggerFactory, converter); - var storeLoader = Substitute.For(); - storeLoader.Load().Returns(new[] { new AliasStore(repository) }); - - var asm = Assembly.GetExecutingAssembly(); - var service = new SearchService(storeLoader, new MacroManager(asm, repository: repository), thumbnailManager); - - // ACT - var result = service.Search(new("z")).ToArray(); + var service = new SearchService(new DebugStoreLoader(), macroManager, thumbnailManager); + var query = new Cmdline("code"); + + var result = service.Search(query) + .ToArray(); - // ASSERT using (new AssertionScope()) { - result.Should().HaveCountGreaterThan(0); - result[0].Name.Should().Be("No result found"); + result.Should().HaveCount(1); + result.ElementAt(0).IsResult.Should().BeFalse(); } - } + #endregion Methods } } \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/BusinessLogic/SessionManagerShould.cs b/src/Tests/Lanceur.Tests/BusinessLogic/SessionManagerShould.cs index f383a920..07ef024a 100644 --- a/src/Tests/Lanceur.Tests/BusinessLogic/SessionManagerShould.cs +++ b/src/Tests/Lanceur.Tests/BusinessLogic/SessionManagerShould.cs @@ -4,6 +4,7 @@ using Lanceur.Infra.SQLite; using Lanceur.SharedKernel.Mixins; using Lanceur.Tests.SQLite; +using Microsoft.Extensions.Logging; using NSubstitute; using System.Data.SQLite; using Xunit; @@ -37,7 +38,7 @@ public void HaveTenSessions() { var scope = new SQLiteSingleConnectionManager(BuildConnection()); CreateTableAndPopulate(scope); - var service = new SQLiteRepository(scope, Substitute.For(), Substitute.For()); + var service = new SQLiteRepository(scope, Substitute.For(), Substitute.For()); service.GetSessions().Should().HaveCount(10); } diff --git a/src/Tests/Lanceur.Tests/Converters/StringConverterShould.cs b/src/Tests/Lanceur.Tests/Converters/StringConverterShould.cs index d7c11856..67ea7b27 100644 --- a/src/Tests/Lanceur.Tests/Converters/StringConverterShould.cs +++ b/src/Tests/Lanceur.Tests/Converters/StringConverterShould.cs @@ -49,7 +49,7 @@ public void IndicateCorrectDescriptionWhenUsingLimitedStringFormatter(string inp var converter = new QueryDescriptionConverter(formatter); var description = converter.Convert(input, null, null, null) as string; - + description.Should().NotBeNull(); description!.Length.Should().BeLessOrEqualTo(LimitedStringLengthFormatter.MaxLength + 5); } diff --git a/src/Tests/Lanceur.Tests/Functional/ExecutionManagerShould.cs b/src/Tests/Lanceur.Tests/Functional/ExecutionManagerShould.cs index 2495cd06..2039a948 100644 --- a/src/Tests/Lanceur.Tests/Functional/ExecutionManagerShould.cs +++ b/src/Tests/Lanceur.Tests/Functional/ExecutionManagerShould.cs @@ -3,9 +3,9 @@ using Lanceur.Core.Models; using Lanceur.Core.Repositories; using Lanceur.Core.Requests; -using Lanceur.Core.Services; using Lanceur.Infra.Managers; using Lanceur.Macros; +using Microsoft.Extensions.Logging; using NSubstitute; using Xunit; @@ -26,7 +26,7 @@ public async Task ExecuteMultiMacro(string cmd, string parameters) .Returns(cmdline); var mgr = new ExecutionManager( - Substitute.For(), + Substitute.For(), Substitute.For(), Substitute.For(), cmdlineManager diff --git a/src/Tests/Lanceur.Tests/Logging/BaseLogger.cs b/src/Tests/Lanceur.Tests/Logging/BaseLogger.cs deleted file mode 100644 index be54b66d..00000000 --- a/src/Tests/Lanceur.Tests/Logging/BaseLogger.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Runtime.CompilerServices; -using Xunit.Abstractions; - -namespace Lanceur.Tests.Logging -{ - public class BaseLogger - { - #region Fields - - private readonly ITestOutputHelper _output; - - #endregion Fields - - #region Constructors - - public BaseLogger(ITestOutputHelper output) - { - ArgumentNullException.ThrowIfNull(nameof(output)); - _output = output; - } - - #endregion Constructors - - #region Methods - - protected void Write(string message, [CallerMemberName] string method = null) => _output.WriteLine($"[{method,-6}] {message}"); - - protected void Write(string message, Exception ex, [CallerMemberName] string method = null) => _output.WriteLine($"[{method,-6}] {message} - {ex}"); - - protected void Write(Exception ex, [CallerMemberName] string method = null) => _output.WriteLine($"[{method,-6}] {ex}"); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/BaseTestOutputHelperDecorator.cs b/src/Tests/Lanceur.Tests/Logging/BaseTestOutputHelperDecorator.cs new file mode 100644 index 00000000..974541c8 --- /dev/null +++ b/src/Tests/Lanceur.Tests/Logging/BaseTestOutputHelperDecorator.cs @@ -0,0 +1,40 @@ +using Lanceur.SharedKernel.Mixins; +using Xunit.Abstractions; + +namespace Lanceur.Tests.Logging +{ + public class BaseTestOutputHelperDecorator + { + #region Fields + + private readonly ITestOutputHelper _output; + + #endregion Fields + + #region Constructors + + protected BaseTestOutputHelperDecorator(ITestOutputHelper output) + { + ArgumentNullException.ThrowIfNull(nameof(output)); + _output = output; + } + + #endregion Constructors + + #region Methods + + protected void Write(Exception ex, string message, object[] propertyValues) + { + var msg = $"{(propertyValues.Length == 0 ? message : message.Format(propertyValues))}"; + if (ex is not null) + { + msg += $" - {ex}"; + } + _output.WriteLine(msg); + } + + protected void Write(string message) => Write(null, message, Array.Empty()); + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/MicrosoftLoggingLoggerFactory.cs b/src/Tests/Lanceur.Tests/Logging/MicrosoftLoggingLoggerFactory.cs new file mode 100644 index 00000000..46dc9f1c --- /dev/null +++ b/src/Tests/Lanceur.Tests/Logging/MicrosoftLoggingLoggerFactory.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace Lanceur.Tests.Logging +{ + public class MicrosoftLoggingLoggerFactory : ILoggerFactory + { + #region Fields + + private readonly ITestOutputHelper _output; + + #endregion Fields + + #region Constructors + + public MicrosoftLoggingLoggerFactory(ITestOutputHelper output) + { + _output = output; + } + + #endregion Constructors + + #region Methods + + public void AddProvider(ILoggerProvider provider) + { } + + public ILogger CreateLogger(string categoryName) => new TestOutputHelperDecoratorForMicrosoftLogging(_output); + + public void Dispose() + { } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/TestAppLoggerFactory.cs b/src/Tests/Lanceur.Tests/Logging/TestAppLoggerFactory.cs deleted file mode 100644 index e1845f6e..00000000 --- a/src/Tests/Lanceur.Tests/Logging/TestAppLoggerFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Lanceur.Core.Services; - -namespace Lanceur.Tests.Logging -{ - internal class TestAppLoggerFactory : IAppLoggerFactory - { - #region Fields - - private readonly IAppLogger _appLogger = new TraceLogger(); - - #endregion Fields - - #region Methods - - public IAppLogger GetLogger() => _appLogger; - - public IAppLogger GetLogger(Type sourceType) => _appLogger; - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDecoratorForMicrosoftLogging.cs b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDecoratorForMicrosoftLogging.cs new file mode 100644 index 00000000..af1fae8a --- /dev/null +++ b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDecoratorForMicrosoftLogging.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace Lanceur.Tests.Logging +{ + public class TestOutputHelperDecoratorForMicrosoftLogging : BaseTestOutputHelperDecorator, ILogger + { + #region Constructors + + public TestOutputHelperDecoratorForMicrosoftLogging(ITestOutputHelper output) : base(output) + { + } + + #endregion Constructors + + #region Methods + + private static string ToShortLevel(LogLevel logLevel) + { + return logLevel switch + { + LogLevel.Trace => "Trace", + LogLevel.Debug => "Debug", + LogLevel.Information => "Info ", + LogLevel.Warning => "Warn ", + LogLevel.Error => "Error", + LogLevel.Critical => "Fatal", + LogLevel.None => " ", + _ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null) + }; + } + + public IDisposable BeginScope(TState state) where TState : notnull => + new TestOutputHelperDisposable(state, Write); + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + var message = formatter(state, exception); + var parameters = new object[] { eventId, ToShortLevel(logLevel), message }; + Write(exception, "[{1}] {2}", parameters); + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDisposable.cs b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDisposable.cs new file mode 100644 index 00000000..bc123a31 --- /dev/null +++ b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperDisposable.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json; + +namespace Lanceur.Tests.Logging; + +public class TestOutputHelperDisposable : IDisposable +{ + #region Fields + + private readonly object _state; + private readonly Action _write; + + #endregion Fields + + #region Constructors + + public TestOutputHelperDisposable(object state, Action write) + { + _state = state; + _write = write; + } + + #endregion Constructors + + #region Methods + + public void Dispose() + { + var json = JsonConvert.SerializeObject(_state, Formatting.Indented); + _write($"[Scope] Dumped scope:\r\n{json}"); + } + + #endregion Methods +} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/TestOutputHelperMixin.cs b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperMixin.cs index 06065ca3..f4afa1c6 100644 --- a/src/Tests/Lanceur.Tests/Logging/TestOutputHelperMixin.cs +++ b/src/Tests/Lanceur.Tests/Logging/TestOutputHelperMixin.cs @@ -7,7 +7,7 @@ public static class TestOutputHelperMixin { #region Fields - private static string TAB = " "; + private const string Tab = " "; #endregion Fields @@ -21,13 +21,13 @@ public static class TestOutputHelperMixin public static void Assert(this ITestOutputHelper output) => output.Write("---- ASSERT", nameof(Info)); - public static void Debug(this ITestOutputHelper output, string message) => output.Write($"{TAB}{message}"); + public static void Debug(this ITestOutputHelper output, string message) => output.Write($"{Tab}{message}"); - public static void Error(this ITestOutputHelper output, string message) => output.Write($"{TAB}{message}"); + public static void Error(this ITestOutputHelper output, string message) => output.Write($"{Tab}{message}"); - public static void Info(this ITestOutputHelper output, string message) => output.Write($"{TAB}{message}"); + public static void Info(this ITestOutputHelper output, string message) => output.Write($"{Tab}{message}"); - public static void Warn(this ITestOutputHelper output, string message) => output.Write($"{TAB}{message}"); + public static void Warn(this ITestOutputHelper output, string message) => output.Write($"{Tab}{message}"); #endregion Methods } diff --git a/src/Tests/Lanceur.Tests/Logging/TestReactiveUiLogger.cs b/src/Tests/Lanceur.Tests/Logging/TestReactiveUiLogger.cs deleted file mode 100644 index d769d7b1..00000000 --- a/src/Tests/Lanceur.Tests/Logging/TestReactiveUiLogger.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Splat; -using System.ComponentModel; -using Xunit.Abstractions; - -namespace Lanceur.Tests.Logging -{ - public class TestReactiveUiLogger : BaseLogger, ILogger - { - #region Constructors - - public TestReactiveUiLogger(ITestOutputHelper output) : base(output) - { - } - - #endregion Constructors - - #region Properties - - public LogLevel Level => throw new NotImplementedException(); - - #endregion Properties - - #region Methods - - private string Wrap(string message) => $" -- ReactiveUI -- {message,-6}"; - - public void Write([Localizable(false)] string message, LogLevel logLevel) => Write(Wrap(message), $"{logLevel}"); - - public void Write(Exception exception, [Localizable(false)] string message, LogLevel logLevel) => Write(Wrap(message), $"{logLevel}"); - - public void Write([Localizable(false)] string message, [Localizable(false)] Type type, LogLevel logLevel) => Write(Wrap(message), $"{logLevel}"); - - public void Write(Exception exception, [Localizable(false)] string message, [Localizable(false)] Type type, LogLevel logLevel) => Write(Wrap(message), exception, $"{logLevel}"); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/XUnitLogger.cs b/src/Tests/Lanceur.Tests/Logging/XUnitLogger.cs deleted file mode 100644 index 88825d53..00000000 --- a/src/Tests/Lanceur.Tests/Logging/XUnitLogger.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Lanceur.Core.Services; -using Xunit.Abstractions; - -namespace Lanceur.Tests.Logging -{ - public class XUnitLogger : BaseLogger, IAppLogger - { - #region Constructors - - public XUnitLogger(ITestOutputHelper output) : base(output) - { - } - - #endregion Constructors - - #region Methods - - public void Debug(string message) => Write(message); - - public void Debug(Exception ex) => Write(ex); - - public void Error(string message, Exception ex = null) => Write(message, ex); - - public void Fatal(string message, Exception ex = null) => Write(message); - - public void Info(string message) => Write(message); - - public void Trace(string message) => Write(message); - - public void Warning(string message, Exception ex = null) => Write(message); - - public void Warning(Exception ex) => Write(ex); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Logging/XUnitLoggerFactory.cs b/src/Tests/Lanceur.Tests/Logging/XUnitLoggerFactory.cs deleted file mode 100644 index 2c88c6f4..00000000 --- a/src/Tests/Lanceur.Tests/Logging/XUnitLoggerFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Lanceur.Core.Services; -using Xunit.Abstractions; - -namespace Lanceur.Tests.Logging -{ - public class XUnitLoggerFactory : IAppLoggerFactory - { - #region Fields - - private readonly ITestOutputHelper _output; - - #endregion Fields - - #region Constructors - - public XUnitLoggerFactory(ITestOutputHelper output) - { - _output = output; - } - - #endregion Constructors - - #region Methods - - public IAppLogger GetLogger() => new XUnitLogger(_output); - - public IAppLogger GetLogger(Type sourceType) => new XUnitLogger(_output); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/SQL/SqlBuilder.cs b/src/Tests/Lanceur.Tests/SQL/SqlBuilder.cs index 060a6de8..f6d9d1a3 100644 --- a/src/Tests/Lanceur.Tests/SQL/SqlBuilder.cs +++ b/src/Tests/Lanceur.Tests/SQL/SqlBuilder.cs @@ -22,18 +22,6 @@ public SqlBuilder(SqlBuilder initialSql = null) #region Methods - public SqlBuilder AppendSynonyms(long idAlias, params string[] synonyms) - { - if(synonyms is null || synonyms.Length == 0) { throw new ArgumentNullException(nameof(synonyms), "You should provide names for the alias"); } - - foreach (var synonym in synonyms) - { - _sql.Append($"insert into alias_name(id_alias, name) values ({idAlias}, '{synonym}');"); - _sql.AppendNewLine(); - } - return this; - } - public SqlBuilder AppendAlias(long idAlias, string fileName, string arguments) { _sql.Append($"insert into alias (id, file_name, arguments, id_session) values ({idAlias}, '{fileName}', '{arguments}', 1);"); @@ -48,6 +36,18 @@ public SqlBuilder AppendArgument(long idAlias, string name, string argument) return this; } + public SqlBuilder AppendSynonyms(long idAlias, params string[] synonyms) + { + if (synonyms is null || synonyms.Length == 0) { throw new ArgumentNullException(nameof(synonyms), "You should provide names for the alias"); } + + foreach (var synonym in synonyms) + { + _sql.Append($"insert into alias_name(id_alias, name) values ({idAlias}, '{synonym}');"); + _sql.AppendNewLine(); + } + return this; + } + public override string ToString() => _sql.ToString(); #endregion Methods diff --git a/src/Tests/Lanceur.Tests/SQLite/SQLiteTest.cs b/src/Tests/Lanceur.Tests/SQLite/SqliteTest.cs similarity index 100% rename from src/Tests/Lanceur.Tests/SQLite/SQLiteTest.cs rename to src/Tests/Lanceur.Tests/SQLite/SqliteTest.cs diff --git a/src/Tests/Lanceur.Tests/SQLite/SQLiteUpdateServiceShould.cs b/src/Tests/Lanceur.Tests/SQLite/SqliteUpdateServiceShould.cs similarity index 100% rename from src/Tests/Lanceur.Tests/SQLite/SQLiteUpdateServiceShould.cs rename to src/Tests/Lanceur.Tests/SQLite/SqliteUpdateServiceShould.cs diff --git a/src/Tests/Lanceur.Tests/Utils/Builders/KeywordsViewModelBuilder.cs b/src/Tests/Lanceur.Tests/Utils/Builders/KeywordsViewModelBuilder.cs index d505cd3f..b305dcd5 100644 --- a/src/Tests/Lanceur.Tests/Utils/Builders/KeywordsViewModelBuilder.cs +++ b/src/Tests/Lanceur.Tests/Utils/Builders/KeywordsViewModelBuilder.cs @@ -5,6 +5,7 @@ using Lanceur.Tests.Logging; using Lanceur.Ui; using Lanceur.Views; +using Microsoft.Extensions.Logging; using NSubstitute; using System.Reactive.Concurrency; using Xunit.Abstractions; @@ -16,9 +17,9 @@ internal class KeywordsViewModelBuilder #region Fields private IDbRepository _dbRepository; - private IAppLoggerFactory _loggerFactory; - private TestSchedulerProvider _schedulerProvider; + private ILoggerFactory _loggerFactory; private IPackagedAppSearchService _packagedAppSearchService; + private TestSchedulerProvider _schedulerProvider; #endregion Fields @@ -57,11 +58,11 @@ public KeywordsViewModelBuilder With(IPackagedAppSearchService packagedAppSearch public KeywordsViewModelBuilder With(ITestOutputHelper output) { - _loggerFactory = new XUnitLoggerFactory(output); + _loggerFactory = new MicrosoftLoggingLoggerFactory(output); return this; } - public KeywordsViewModelBuilder With(IAppLoggerFactory loggerFactory) + public KeywordsViewModelBuilder With(ILoggerFactory loggerFactory) { _loggerFactory = loggerFactory; return this; diff --git a/src/Tests/Lanceur.Tests/Utils/Builders/MainViewModelBuilder.cs b/src/Tests/Lanceur.Tests/Utils/Builders/MainViewModelBuilder.cs index a2f63825..9b718eb0 100644 --- a/src/Tests/Lanceur.Tests/Utils/Builders/MainViewModelBuilder.cs +++ b/src/Tests/Lanceur.Tests/Utils/Builders/MainViewModelBuilder.cs @@ -27,12 +27,6 @@ internal class MainViewModelBuilder #region Methods - internal MainViewModelBuilder With(ISettingsFacade settingsFacade) - { - _appConfigService = settingsFacade; - return this; - } - public MainViewModel Build() { ArgumentNullException.ThrowIfNull(_output); @@ -43,16 +37,22 @@ public MainViewModel Build() return new( schedulerProvider: _schedulerProvider ?? throw new ArgumentNullException($"No scheduler configured for the ViewModel to test."), - logFactory: new XUnitLoggerFactory(_output), searchService: _searchService ?? Substitute.For(), cmdlineService: new CmdlineManager(), executor: _executionManager ?? Substitute.For(), notify: Substitute.For(), appConfigService: _appConfigService ?? settingsFacade, - dataService: Substitute.For() + dataService: Substitute.For(), + loggerFactory: new MicrosoftLoggingLoggerFactory(_output) ); } + public MainViewModelBuilder With(ISettingsFacade settingsFacade) + { + _appConfigService = settingsFacade; + return this; + } + public MainViewModelBuilder With(ITestOutputHelper output) { _output = output; diff --git a/src/Tests/Lanceur.Tests/Utils/DebugMacroExecutor.cs b/src/Tests/Lanceur.Tests/Utils/DebugMacroExecutor.cs index 04d9e0c1..40ab95eb 100644 --- a/src/Tests/Lanceur.Tests/Utils/DebugMacroExecutor.cs +++ b/src/Tests/Lanceur.Tests/Utils/DebugMacroExecutor.cs @@ -1,7 +1,6 @@ using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Requests; -using Lanceur.Macros; using Lanceur.Macros.Development; using Xunit; @@ -17,7 +16,7 @@ public async Task ExecuteAsync(ExecutionRequest request) { return new() { - Results = await macro.ExecuteAsync(new Cmdline("debug")), + Results = await macro.ExecuteAsync(new("debug")), }; } else diff --git a/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs b/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs index 3332a3b1..b525f52b 100644 --- a/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs +++ b/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs @@ -1,7 +1,7 @@ using Lanceur.Core; using Lanceur.Core.Models; -using System.ComponentModel; using Lanceur.SharedKernel.Mixins; +using System.ComponentModel; namespace Lanceur.Tests.Utils.Macros { @@ -10,8 +10,10 @@ public class MultiMacroTest : MacroQueryResult { #region Constructors - public MultiMacroTest() : this(null) { } - + public MultiMacroTest() : this(null) + { + } + public MultiMacroTest(string parameters = null) { Name = Guid.NewGuid().ToString(); diff --git a/src/Tests/Lanceur.Tests/ViewModels/KeywordViewModelShould.cs b/src/Tests/Lanceur.Tests/ViewModels/KeywordViewModelShould.cs index af804fe1..5eaf3064 100644 --- a/src/Tests/Lanceur.Tests/ViewModels/KeywordViewModelShould.cs +++ b/src/Tests/Lanceur.Tests/ViewModels/KeywordViewModelShould.cs @@ -42,155 +42,155 @@ public KeywordViewModelShould(ITestOutputHelper output) #region Methods [Fact] - public void BeAbleToRemoveSynonym()=> new TestScheduler().With(scheduler => - { - // ARRANGE - const long idAlias = 10; - var sql = new SqlBuilder().AppendAlias(idAlias, "@multi@", "@alias2@@alias3") - .AppendSynonyms(idAlias, "multi1", "multi2", "multi3") - .AppendAlias(20, "alias2", "action1") - .AppendSynonyms(20, "alias2") - .AppendAlias(30, "alias3", "action2") - .AppendSynonyms(30, "alias3") - .ToString(); - - var connectionMgr = new SQLiteSingleConnectionManager(BuildFreshDb(sql)); - - var logger = new XUnitLoggerFactory(_output); - var cfg = new MapperConfiguration(cfg => + public void BeAbleToRemoveSynonym() => new TestScheduler().With(scheduler => { - cfg.CreateMap(); + // ARRANGE + const long idAlias = 10; + var sql = new SqlBuilder().AppendAlias(idAlias, "@multi@", "@alias2@@alias3") + .AppendSynonyms(idAlias, "multi1", "multi2", "multi3") + .AppendAlias(20, "alias2", "action1") + .AppendSynonyms(20, "alias2") + .AppendAlias(30, "alias3", "action2") + .AppendSynonyms(30, "alias3") + .ToString(); + + var connectionMgr = new SQLiteSingleConnectionManager(BuildFreshDb(sql)); + + var logger = new MicrosoftLoggingLoggerFactory(_output); + var cfg = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }); + var conversionService = new AutoMapperConverter(new Mapper(cfg)); + var dbRepository = new SQLiteRepository(connectionMgr, logger, conversionService); + + var vm = new KeywordsViewModelBuilder() + .With(scheduler) + .With(logger) + .With(dbRepository) + .Build(); + + // ACT + vm.Activate(new()); + vm.SearchQuery = "multi"; + scheduler.AdvanceBy(200.Milliseconds().Ticks); + + vm.SelectedAlias.Synonyms = "multi1, multi2"; + vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); + scheduler.Start(); + + // ASSERT + using (new AssertionScope()) + { + // The database should have one less synonym + var countSql = $"select count(*) from alias_name where id_alias = {idAlias}"; + connectionMgr.WithinTransaction(tx => (long)tx.Connection.ExecuteScalar(countSql)) + .Should().Be(2); + // And the UI also... + vm.Aliases.Should().HaveCount(2); + } }); - var conversionService = new AutoMapperConverter(new Mapper(cfg)); - var dbRepository = new SQLiteRepository(connectionMgr, logger, conversionService); - - var vm = new KeywordsViewModelBuilder() - .With(scheduler) - .With(logger) - .With(dbRepository) - .Build(); - - // ACT - vm.Activate(new()); - vm.SearchQuery = "multi"; - scheduler.AdvanceBy(200.Milliseconds().Ticks); - - vm.SelectedAlias.Synonyms = "multi1, multi2"; - vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); - scheduler.Start(); - - // ASSERT - using (new AssertionScope()) - { - // The database should have one less synonym - var countSql = $"select count(*) from alias_name where id_alias = {idAlias}"; - connectionMgr.WithinTransaction(tx => (long)tx.Connection.ExecuteScalar(countSql)) - .Should().Be(2); - // And the UI also... - vm.Aliases.Should().HaveCount(2); - } - }); [Fact] public void CreateAliasAndSelectIt() => new TestScheduler().With(scheduler => - { - // ARRANGE - var dbRepository = Substitute.For(); - dbRepository.SelectNames(Arg.Any()) - .Returns(new ExistingNameResponse(Array.Empty())); + { + // ARRANGE + var dbRepository = Substitute.For(); + dbRepository.SelectNames(Arg.Any()) + .Returns(new ExistingNameResponse(Array.Empty())); - var vm = new KeywordsViewModelBuilder() - .With(scheduler) - .With(_output) - .With(dbRepository) - .Build(); + var vm = new KeywordsViewModelBuilder() + .With(scheduler) + .With(_output) + .With(dbRepository) + .Build(); - var synonyms = Guid.NewGuid().ToString(); - var fileName = Guid.NewGuid().ToString(); + var synonyms = Guid.NewGuid().ToString(); + var fileName = Guid.NewGuid().ToString(); - // ACT + // ACT - vm.Activate(new()); - scheduler.Start(); - vm.CreatingAlias.Execute().Subscribe(); - var hash = vm.SelectedAlias.GetHashCode(); + vm.Activate(new()); + scheduler.Start(); + vm.CreatingAlias.Execute().Subscribe(); + var hash = vm.SelectedAlias.GetHashCode(); - vm.SelectedAlias.Synonyms = synonyms; - vm.SelectedAlias.FileName = fileName; + vm.SelectedAlias.Synonyms = synonyms; + vm.SelectedAlias.FileName = fileName; - vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); + vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); - // ASSERT - vm.SelectedAlias.GetHashCode().Should().Be(hash); - }); + // ASSERT + vm.SelectedAlias.GetHashCode().Should().Be(hash); + }); [Fact] public void CreateAliasForPackagedApp() => new TestScheduler().With(scheduler => - { - // ARRANGE - var packagedAppSearchService = Substitute.For(); - packagedAppSearchService.GetByInstalledDirectory(Arg.Any()) - .Returns(new List - { new() { AppUserModelId = Guid.NewGuid().ToString() } }); - - var vm = new KeywordsViewModelBuilder().With(scheduler) - .With(_output) - .With(packagedAppSearchService) - .Build(); - - // ACT - vm.Activate(new()); - vm.CreatingAlias.Execute().Subscribe(); - vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); - - // ASSERT - vm.SelectedAlias.FileName.Should().StartWith("package:"); - }); + { + // ARRANGE + var packagedAppSearchService = Substitute.For(); + packagedAppSearchService.GetByInstalledDirectory(Arg.Any()) + .Returns(new List + { new() { AppUserModelId = Guid.NewGuid().ToString() } }); + + var vm = new KeywordsViewModelBuilder().With(scheduler) + .With(_output) + .With(packagedAppSearchService) + .Build(); + + // ACT + vm.Activate(new()); + vm.CreatingAlias.Execute().Subscribe(); + vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); + + // ASSERT + vm.SelectedAlias.FileName.Should().StartWith("package:"); + }); [Theory] [InlineData("multi, ")] [InlineData("multi,")] public void NotBeAbleToCreateEmptyAlias(string synonyms) => new TestScheduler().With(scheduler => - { - // ARRANGE - var sql = new SqlBuilder().AppendAlias(10, "@multi@", "@alias2@@alias3") - .AppendSynonyms(10, "multi1", "multi2", "multi3") - .AppendAlias(20, "alias2", "action1") - .AppendSynonyms(20, "alias2") - .AppendAlias(30, "alias3", "action2") - .AppendSynonyms(30, "alias3") - .ToString(); - - var connectionMgr = new SQLiteSingleConnectionManager(BuildFreshDb(sql)); - - var logger = new XUnitLoggerFactory(_output); - var cfg = new MapperConfiguration(cfg => { - cfg.CreateMap(); + // ARRANGE + var sql = new SqlBuilder().AppendAlias(10, "@multi@", "@alias2@@alias3") + .AppendSynonyms(10, "multi1", "multi2", "multi3") + .AppendAlias(20, "alias2", "action1") + .AppendSynonyms(20, "alias2") + .AppendAlias(30, "alias3", "action2") + .AppendSynonyms(30, "alias3") + .ToString(); + + var connectionMgr = new SQLiteSingleConnectionManager(BuildFreshDb(sql)); + + var logger = new MicrosoftLoggingLoggerFactory(_output); + var cfg = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }); + var conversionService = new AutoMapperConverter(new Mapper(cfg)); + var dbRepository = new SQLiteRepository(connectionMgr, logger, conversionService); + + var vm = new KeywordsViewModelBuilder() + .With(scheduler) + .With(logger) + .With(dbRepository) + .Build(); + // ACT + vm.Activate(new()); + vm.SearchQuery = "multi1"; + scheduler.Start(); + + vm.SelectedAlias.Synonyms = synonyms; + vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); + + vm.Activate(new()); + vm.SearchQuery = "multi1"; + scheduler.AdvanceBy(200.Milliseconds().Ticks); + + // ASSERT + vm.ValidationAliasExists.IsValid.Should().BeTrue(); }); - var conversionService = new AutoMapperConverter(new Mapper(cfg)); - var dbRepository = new SQLiteRepository(connectionMgr, logger, conversionService); - - var vm = new KeywordsViewModelBuilder() - .With(scheduler) - .With(logger) - .With(dbRepository) - .Build(); - // ACT - vm.Activate(new()); - vm.SearchQuery = "multi1"; - scheduler.Start(); - - vm.SelectedAlias.Synonyms = synonyms; - vm.SaveOrUpdateAlias.Execute(vm.SelectedAlias).Subscribe(); - - vm.Activate(new()); - vm.SearchQuery = "multi1"; - scheduler.AdvanceBy(200.Milliseconds().Ticks); - - // ASSERT - vm.ValidationAliasExists.IsValid.Should().BeTrue(); - }); [Fact] public async Task RefreshThumbnailsWithoutRemovingAdditionalParameters() @@ -213,7 +213,7 @@ public async Task RefreshThumbnailsWithoutRemovingAdditionalParameters() .ToString(); var connectionMgr = new SQLiteSingleConnectionManager(BuildFreshDb(sql)); - var loggerFactory = new XUnitLoggerFactory(_output); + var loggerFactory = new MicrosoftLoggingLoggerFactory(_output); var cfg = new MapperConfiguration(cfg => { diff --git a/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.Execute.cs b/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.Execute.cs index 19d5ab93..f083d68b 100644 --- a/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.Execute.cs +++ b/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.Execute.cs @@ -7,6 +7,7 @@ using Lanceur.Infra.Managers; using Lanceur.Tests.Utils.Builders; using Lanceur.Tests.Utils.ReservedAliases; +using Microsoft.Extensions.Logging; using Microsoft.Reactive.Testing; using NSubstitute; using ReactiveUI.Testing; @@ -188,7 +189,7 @@ public void NotExecuteWhenNoResult() new TestScheduler().With(scheduler => { // ARRANGE - var logFactory = Substitute.For(); + var logFactory = Substitute.For(); var wildcardManager = Substitute.For(); var dataService = Substitute.For(); var cmdlineManager = Substitute.For(); diff --git a/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.cs b/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.cs index 041703eb..d2ee1dd6 100644 --- a/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.cs +++ b/src/Tests/Lanceur.Tests/ViewModels/MainViewModelShould.cs @@ -7,16 +7,17 @@ using Lanceur.Core.Requests; using Lanceur.Core.Services; using Lanceur.Infra.Managers; +using Lanceur.Macros.Development; using Lanceur.Tests.Utils; using Lanceur.Tests.Utils.Builders; using Lanceur.Tests.Utils.ReservedAliases; using Lanceur.Views.Mixins; +using Microsoft.Extensions.Logging; using Microsoft.Reactive.Testing; using NSubstitute; using ReactiveUI.Testing; using Splat; using System.Reactive.Concurrency; -using Lanceur.Macros.Development; using Xunit; using Xunit.Abstractions; @@ -48,7 +49,7 @@ public void HaveResultWhenQueryIsArithmetic(string expression, string result) new TestScheduler().With(scheduler => { // ARRANGE - Substitute.For(); + Substitute.For(); var executor = Substitute.For(); executor.ExecuteAsync(Arg.Any()) @@ -76,7 +77,7 @@ public void HaveResultWhenQueryIsArithmetic(string expression, string result) vm.CurrentAlias?.Name?.Should().Be(result); }); } - + [Fact] public void NotifyWhenCriterionChanges() {