From 09d57c4585583b7bc74eaddaf047370cd531c029 Mon Sep 17 00:00:00 2001 From: wherewhere Date: Wed, 27 Sep 2023 17:02:52 +0800 Subject: [PATCH] Replace Microsoft.Extensions.Logging with custom ILogger --- .../AdbCommandLineClient.Async.cs | 2 - .../AdbCommandLineClient.cs | 21 +-- AdvancedSharpAdbClient/AdbSocket.Async.cs | 16 -- AdvancedSharpAdbClient/AdbSocket.cs | 59 +------ .../AdvancedSharpAdbClient.csproj | 126 ++------------- .../DeviceCommands/PackageManager.Async.cs | 15 +- .../DeviceCommands/PackageManager.cs | 34 +--- AdvancedSharpAdbClient/DeviceMonitor.Async.cs | 17 -- AdvancedSharpAdbClient/DeviceMonitor.cs | 19 +-- .../Extensions/LoggerExtensions.cs | 149 +++++++++++------- AdvancedSharpAdbClient/Logs/Enums/LogLevel.cs | 52 ++++++ .../Logs/Interfaces/ILogger.cs | 35 ++++ .../Logs/Interfaces/ILoggerFactory.cs | 28 ++++ AdvancedSharpAdbClient/Logs/LoggerProvider.cs | 34 ++++ AdvancedSharpAdbClient/Logs/NullLogger.cs | 34 ++++ AdvancedSharpAdbClient/Logs/NullLoggerT.cs | 55 ------- .../Properties/GlobalUsings.cs | 5 - .../Receivers/ConsoleOutputReceiver.cs | 43 +---- 18 files changed, 309 insertions(+), 435 deletions(-) create mode 100644 AdvancedSharpAdbClient/Logs/Enums/LogLevel.cs create mode 100644 AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs create mode 100644 AdvancedSharpAdbClient/Logs/Interfaces/ILoggerFactory.cs create mode 100644 AdvancedSharpAdbClient/Logs/LoggerProvider.cs create mode 100644 AdvancedSharpAdbClient/Logs/NullLogger.cs delete mode 100644 AdvancedSharpAdbClient/Logs/NullLoggerT.cs diff --git a/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs b/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs index 609b68c3..b6ed11cf 100644 --- a/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs +++ b/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs @@ -32,9 +32,7 @@ public virtual async Task GetVersionAsync(CancellationToken cancellatio if (version < AdbServer.RequiredAdbVersion) { AdbException ex = new($"Required minimum version of adb: {AdbServer.RequiredAdbVersion}. Current version is {version}"); -#if HAS_LOGGER logger.LogError(ex, ex.Message); -#endif throw ex; } diff --git a/AdvancedSharpAdbClient/AdbCommandLineClient.cs b/AdvancedSharpAdbClient/AdbCommandLineClient.cs index 5a8b8ed7..4aea2e19 100644 --- a/AdvancedSharpAdbClient/AdbCommandLineClient.cs +++ b/AdvancedSharpAdbClient/AdbCommandLineClient.cs @@ -3,6 +3,7 @@ // using AdvancedSharpAdbClient.Exceptions; +using AdvancedSharpAdbClient.Logs; using System; using System.Collections.Generic; using System.ComponentModel; @@ -22,27 +23,18 @@ public partial class AdbCommandLineClient : IAdbCommandLineClient /// protected const string AdbVersionPattern = "^.*(\\d+)\\.(\\d+)\\.(\\d+)$"; -#if HAS_LOGGER /// /// The logger to use when logging messages. /// protected readonly ILogger logger; -#endif -#if !HAS_LOGGER -#pragma warning disable CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Initializes a new instance of the class. /// /// The path to the adb.exe executable. /// Don't check adb file name when . /// The logger to use when logging. - public AdbCommandLineClient(string adbPath, bool isForce = false -#if HAS_LOGGER - , ILogger logger = null -#endif - ) + public AdbCommandLineClient(string adbPath, bool isForce = false, ILogger logger = null) { if (adbPath.IsNullOrWhiteSpace()) { @@ -77,13 +69,8 @@ public AdbCommandLineClient(string adbPath, bool isForce = false this.EnsureIsValidAdbFile(adbPath); AdbPath = adbPath; -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } -#if !HAS_LOGGER -#pragma warning restore CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Gets the path to the adb.exe executable. @@ -107,9 +94,7 @@ public virtual Version GetVersion() if (version < AdbServer.RequiredAdbVersion) { AdbException ex = new($"Required minimum version of adb: {AdbServer.RequiredAdbVersion}. Current version is {version}"); -#if HAS_LOGGER logger.LogError(ex, ex.Message); -#endif throw ex; } diff --git a/AdvancedSharpAdbClient/AdbSocket.Async.cs b/AdvancedSharpAdbClient/AdbSocket.Async.cs index 34559e0b..8cc83f7e 100644 --- a/AdvancedSharpAdbClient/AdbSocket.Async.cs +++ b/AdvancedSharpAdbClient/AdbSocket.Async.cs @@ -28,14 +28,9 @@ public virtual async Task SendAsync(byte[] data, int offset, int length, Cancell throw new AdbException("channel EOF"); } } -#if HAS_LOGGER catch (SocketException ex) { logger.LogError(ex, ex.Message); -#else - catch (SocketException) - { -#endif throw; } } @@ -115,16 +110,12 @@ public virtual async Task ReadAsync(byte[] data, int length, CancellationTo if (count < 0) { -#if HAS_LOGGER logger.LogError("read: channel EOF"); -#endif throw new AdbException("EOF"); } else if (count == 0) { -#if HAS_LOGGER logger.LogInformation("DONE with Read"); -#endif } else { @@ -244,14 +235,9 @@ protected virtual async Task WriteAsync(byte[] data, CancellationToken can { await SendAsync(data, -1, cancellationToken); } -#if HAS_LOGGER catch (IOException e) { logger.LogError(e, e.Message); -#else - catch (IOException) - { -#endif return false; } @@ -278,9 +264,7 @@ protected virtual async Task ReadAdbResponseInnerAsync(Cancellation { string message = await ReadStringAsync(cancellationToken); rasps.Message = message; -#if HAS_LOGGER logger.LogError($"Got reply '{ReplyToString(reply)}', diag='{rasps.Message}'"); -#endif } return rasps; diff --git a/AdvancedSharpAdbClient/AdbSocket.cs b/AdvancedSharpAdbClient/AdbSocket.cs index ccb296bd..19e66e68 100644 --- a/AdvancedSharpAdbClient/AdbSocket.cs +++ b/AdvancedSharpAdbClient/AdbSocket.cs @@ -31,33 +31,22 @@ public partial class AdbSocket : IAdbSocket /// protected readonly ITcpSocket socket; -#if HAS_LOGGER /// /// The logger to use when logging messages. /// protected readonly ILogger logger; -#endif -#if !HAS_LOGGER -#pragma warning disable CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Initializes a new instance of the class. /// /// The at which the Android Debug Bridge is listening for clients. /// The logger to use when logging. - public AdbSocket(EndPoint endPoint -#if HAS_LOGGER - , ILogger logger = null -#endif - ) + public AdbSocket(EndPoint endPoint, ILogger logger = null) { socket = new TcpSocket(); socket.Connect(endPoint); socket.ReceiveBufferSize = ReceiveBufferSize; -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } /// @@ -66,11 +55,7 @@ public AdbSocket(EndPoint endPoint /// The host address at which the Android Debug Bridge is listening for clients. /// The port at which the Android Debug Bridge is listening for clients. /// The logger to use when logging. - public AdbSocket(string host, int port -#if HAS_LOGGER - , ILogger logger = null -#endif - ) + public AdbSocket(string host, int port, ILogger logger = null) { if (string.IsNullOrEmpty(host)) { @@ -86,24 +71,18 @@ public AdbSocket(string host, int port socket = new TcpSocket(); socket.Connect(endPoint); socket.ReceiveBufferSize = ReceiveBufferSize; -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } -#if !HAS_LOGGER -#pragma warning restore CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Initializes a new instance of the class. /// /// The at which the Android Debug Bridge is listening for clients. - public AdbSocket(ITcpSocket socket) + /// The logger to use when logging. + public AdbSocket(ITcpSocket socket, ILogger logger = null) { this.socket = socket; -#if HAS_LOGGER - logger ??= NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } /// @@ -143,14 +122,9 @@ public virtual void Send(byte[] data, int offset, int length) throw new AdbException("channel EOF"); } } -#if HAS_LOGGER catch (SocketException sex) { logger.LogError(sex, sex.Message); -#else - catch (SocketException) - { -#endif throw; } } @@ -222,16 +196,12 @@ public virtual int Read(byte[] data, int length) count = socket.Receive(buffer, bufferLength, SocketFlags.None); if (count < 0) { -#if HAS_LOGGER logger.LogError("read: channel EOF"); -#endif throw new AdbException("EOF"); } else if (count == 0) { -#if HAS_LOGGER logger.LogInformation("DONE with Read"); -#endif } else { @@ -364,14 +334,9 @@ protected virtual bool Write(byte[] data) { Send(data, -1); } -#if HAS_LOGGER catch (IOException e) { logger.LogError(e, e.Message); -#else - catch (IOException) - { -#endif return false; } @@ -397,9 +362,7 @@ protected virtual AdbResponse ReadAdbResponseInner() { string message = ReadString(); rasps.Message = message; -#if HAS_LOGGER - logger.LogError($"Got reply '{ReplyToString(reply)}', diag='{rasps.Message}'"); -#endif + logger.LogError("Got reply '{0}', diag='{1}'", ReplyToString(reply), rasps.Message); } return rasps; @@ -417,17 +380,11 @@ protected virtual string ReplyToString(byte[] reply) { result = Encoding.ASCII.GetString(reply); } -#if HAS_LOGGER catch (DecoderFallbackException e) { logger.LogError(e, e.Message); -#else - catch (DecoderFallbackException) - { -#endif result = string.Empty; } - return result; } diff --git a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj index 98083f69..450e5d0c 100644 --- a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj +++ b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj @@ -4,8 +4,6 @@ False True True - True - False $(NoWarn);CS1685;CA2254 @@ -55,145 +53,39 @@ - + - - - - - - - - - + - + $(DefineConstants);HAS_TASK - + $(DefineConstants);HAS_BUFFERS - - $(DefineConstants);HAS_LOGGER - - - + $(DefineConstants);HAS_DRAWING - + $(DefineConstants);HAS_DRAWING - + $(DefineConstants);HAS_INDEXRANGE - + $(DefineConstants);HAS_RUNTIMEINFORMATION - - $(DefineConstants);HAS_LOGGER;HAS_OLDLOGGER - - - + $(DefineConstants);HAS_PROCESS;HAS_SERIALIZATION diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs index 8daf99c9..c5b58471 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs @@ -358,9 +358,7 @@ protected virtual async Task SyncPackageToDeviceAsync(string localFilePa // workitem: 19711 string remoteFilePath = LinuxPath.Combine(TempInstallationDirectory, packageFileName); -#if HAS_LOGGER logger.LogDebug(packageFileName, $"Uploading {packageFileName} onto device '{Device.Serial}'"); -#endif using (ISyncService sync = syncServiceFactory(client, Device)) { @@ -373,9 +371,8 @@ protected virtual async Task SyncPackageToDeviceAsync(string localFilePa await #endif using Stream stream = File.OpenRead(localFilePath); -#if HAS_LOGGER + logger.LogDebug($"Uploading file onto device '{Device.Serial}'"); -#endif // As C# can't use octal, the octal literal 666 (rw-Permission) is here converted to decimal (438) await sync.PushAsync(stream, remoteFilePath, 438, File.GetLastWriteTime(localFilePath), null, cancellationToken); @@ -383,14 +380,9 @@ protected virtual async Task SyncPackageToDeviceAsync(string localFilePa return remoteFilePath; } -#if HAS_LOGGER catch (IOException e) { logger.LogError(e, $"Unable to open sync connection! reason: {e.Message}"); -#else - catch (IOException) - { -#endif throw; } finally @@ -413,14 +405,9 @@ protected virtual async Task RemoveRemotePackageAsync(string remoteFilePath, Can { await client.ExecuteShellCommandAsync(Device, $"rm \"{remoteFilePath}\"", null, cancellationToken); } -#if HAS_LOGGER catch (IOException e) { logger.LogError(e, $"Failed to delete temporary package: {e.Message}"); -#else - catch (IOException) - { -#endif throw; } } diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs index ff57eef4..8439f9ef 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs @@ -3,6 +3,7 @@ // using AdvancedSharpAdbClient.Exceptions; +using AdvancedSharpAdbClient.Logs; using System; using System.Collections.Generic; using System.Diagnostics; @@ -31,12 +32,10 @@ public partial class PackageManager /// protected const string ListThirdPartyOnly = "pm list packages -f -3"; -#if HAS_LOGGER /// /// The logger to use when logging messages. /// protected readonly ILogger logger; -#endif /// /// The to use when communicating with the device. @@ -55,9 +54,6 @@ public partial class PackageManager /// public event EventHandler InstallProgressChanged; -#if !HAS_LOGGER -#pragma warning disable CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Initializes a new instance of the class. /// @@ -71,11 +67,7 @@ public partial class PackageManager /// A value indicating whether to skip the initial refresh of the package list or not. /// Used mainly by unit tests. /// The logger to use when logging. - public PackageManager(IAdbClient client, DeviceData device, bool thirdPartyOnly = false, Func syncServiceFactory = null, bool skipInit = false -#if HAS_LOGGER - , ILogger logger = null -#endif - ) + public PackageManager(IAdbClient client, DeviceData device, bool thirdPartyOnly = false, Func syncServiceFactory = null, bool skipInit = false , ILogger logger = null ) { Device = device ?? throw new ArgumentNullException(nameof(device)); Packages = []; @@ -89,13 +81,8 @@ public PackageManager(IAdbClient client, DeviceData device, bool thirdPartyOnly RefreshPackages(); } -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } -#if !HAS_LOGGER -#pragma warning restore CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Gets a value indicating whether this package manager only lists third party applications, @@ -438,9 +425,7 @@ protected virtual string SyncPackageToDevice(string localFilePath, Action using AdvancedSharpAdbClient.Exceptions; +using AdvancedSharpAdbClient.Logs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -37,12 +38,10 @@ public partial class DeviceMonitor : IDeviceMonitor private bool disposed = false; -#if HAS_LOGGER /// /// The logger to use when logging messages. /// protected readonly ILogger logger; -#endif /// /// The list of devices currently connected to the Android Debug Bridge. @@ -80,30 +79,18 @@ public partial class DeviceMonitor : IDeviceMonitor /// public event EventHandler DeviceDisconnected; -#if !HAS_LOGGER -#pragma warning disable CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// /// Initializes a new instance of the class. /// /// The that manages the connection with the adb server. /// The logger to use when logging. - public DeviceMonitor(IAdbSocket socket -#if HAS_LOGGER - , ILogger logger = null -#endif - ) + public DeviceMonitor(IAdbSocket socket, ILogger logger = null) { Socket = socket ?? throw new ArgumentNullException(nameof(socket)); devices = []; Devices = devices.AsReadOnly(); -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif + this.logger = logger ?? LoggerProvider.CreateLogger(); } -#if !HAS_LOGGER -#pragma warning restore CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif /// public ReadOnlyCollection Devices { get; private set; } diff --git a/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs b/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs index 89af0cbd..e54c84c7 100644 --- a/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs @@ -1,19 +1,17 @@ -#if HAS_OLDLOGGER -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// -using Microsoft.Extensions.Logging.Internal; using System; +using AdvancedSharpAdbClient.Logs; -namespace Microsoft.Extensions.Logging +namespace AdvancedSharpAdbClient { /// /// ILogger extension methods for common scenarios. /// - public static class LoggerExtensionsEx + public static class LoggerExtensions { - private static readonly Func _messageFormatter = MessageFormatter; - //------------------------------------------DEBUG------------------------------------------// /// @@ -24,8 +22,22 @@ public static class LoggerExtensionsEx /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogDebug(exception, "Error while processing request from {Address}", address) - public static void LogDebug(this ILogger logger, Exception exception, string message, params object[] args) => + public static void LogDebug(this ILogger logger, Exception exception, string message, params object[] args) + { logger.Log(LogLevel.Debug, exception, message, args); + } + + /// + /// Formats and writes a debug log message. + /// + /// The to write to. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug("Processing request from {Address}", address) + public static void LogDebug(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Debug, message, args); + } //------------------------------------------TRACE------------------------------------------// @@ -37,8 +49,22 @@ public static void LogDebug(this ILogger logger, Exception exception, string mes /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogTrace(exception, "Error while processing request from {Address}", address) - public static void LogTrace(this ILogger logger, Exception exception, string message, params object[] args) => + public static void LogTrace(this ILogger logger, Exception exception, string message, params object[] args) + { logger.Log(LogLevel.Trace, exception, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// The to write to. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace("Processing request from {Address}", address) + public static void LogTrace(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Trace, message, args); + } //------------------------------------------INFORMATION------------------------------------------// @@ -50,8 +76,22 @@ public static void LogTrace(this ILogger logger, Exception exception, string mes /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogInformation(exception, "Error while processing request from {Address}", address) - public static void LogInformation(this ILogger logger, Exception exception, string message, params object[] args) => + public static void LogInformation(this ILogger logger, Exception exception, string message, params object[] args) + { logger.Log(LogLevel.Information, exception, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// The to write to. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation("Processing request from {Address}", address) + public static void LogInformation(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Information, message, args); + } //------------------------------------------WARNING------------------------------------------// @@ -63,86 +103,85 @@ public static void LogInformation(this ILogger logger, Exception exception, stri /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogWarning(exception, "Error while processing request from {Address}", address) - public static void LogWarning(this ILogger logger, Exception exception, string message, params object[] args) => + public static void LogWarning(this ILogger logger, Exception exception, string message, params object[] args) + { logger.Log(LogLevel.Warning, exception, message, args); - - //------------------------------------------ERROR------------------------------------------// + } /// - /// Formats and writes an error log message. + /// Formats and writes a warning log message. /// /// The to write to. - /// The exception to log. /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - /// logger.LogError(exception, "Error while processing request from {Address}", address) - public static void LogError(this ILogger logger, Exception exception, string message, params object[] args) => - logger.Log(LogLevel.Error, exception, message, args); + /// logger.LogWarning("Processing request from {Address}", address) + public static void LogWarning(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Warning, message, args); + } - //------------------------------------------CRITICAL------------------------------------------// + //------------------------------------------ERROR------------------------------------------// /// - /// Formats and writes a critical log message. + /// Formats and writes an error log message. /// /// The to write to. /// The exception to log. /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - /// logger.LogCritical(exception, "Error while processing request from {Address}", address) - public static void LogCritical(this ILogger logger, Exception exception, string message, params object[] args) => - logger.Log(LogLevel.Critical, exception, message, args); + /// logger.LogError(exception, "Error while processing request from {Address}", address) + public static void LogError(this ILogger logger, Exception exception, string message, params object[] args) + { + logger.Log(LogLevel.Error, exception, message, args); + } /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes an error log message. /// /// The to write to. - /// Entry will be written on this level. - /// Format string of the log message. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, string message, params object[] args) => - logger.Log(logLevel, 0, null, message, args); + /// logger.LogError("Processing request from {Address}", address) + public static void LogError(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Error, message, args); + } + + //------------------------------------------CRITICAL------------------------------------------// /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a critical log message. /// /// The to write to. - /// Entry will be written on this level. - /// The event id associated with the log. - /// Format string of the log message. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, string message, params object[] args) => - logger.Log(logLevel, eventId, null, message, args); + /// logger.LogCritical(exception, "Error while processing request from {Address}", address) + public static void LogCritical(this ILogger logger, Exception exception, string message, params object[] args) + { + logger.Log(LogLevel.Critical, exception, message, args); + } /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a critical log message. /// /// The to write to. - /// Entry will be written on this level. - /// The exception to log. - /// Format string of the log message. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, Exception exception, string message, params object[] args) => - logger.Log(logLevel, 0, exception, message, args); + /// logger.LogCritical("Processing request from {Address}", address) + public static void LogCritical(this ILogger logger, string message, params object[] args) + { + logger.Log(LogLevel.Critical, message, args); + } /// /// Formats and writes a log message at the specified log level. /// /// The to write to. /// Entry will be written on this level. - /// The event id associated with the log. - /// The exception to log. /// Format string of the log message. /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, string message, params object[] args) - { - if (logger == null) { throw new ArgumentNullException(nameof(logger)); } - - logger.Log(logLevel, eventId, new FormattedLogValues(message, args), exception, _messageFormatter); - } - - //------------------------------------------HELPERS------------------------------------------// - - private static string MessageFormatter(FormattedLogValues state, Exception error) => state.ToString(); + public static void Log(this ILogger logger, LogLevel logLevel, string message, params object[] args) => + logger.Log(logLevel, null, message, args); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Logs/Enums/LogLevel.cs b/AdvancedSharpAdbClient/Logs/Enums/LogLevel.cs new file mode 100644 index 00000000..0578c31c --- /dev/null +++ b/AdvancedSharpAdbClient/Logs/Enums/LogLevel.cs @@ -0,0 +1,52 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +namespace AdvancedSharpAdbClient.Logs +{ + /// + /// Defines logging severity levels. + /// + public enum LogLevel : byte + { + /// + /// Logs that contain the most detailed messages. These messages may contain sensitive application data. + /// These messages are disabled by default and should never be enabled in a production environment. + /// + Trace = 0, + + /// + /// Logs that are used for interactive investigation during development. These logs should primarily contain + /// information useful for debugging and have no long-term value. + /// + Debug = 1, + + /// + /// Logs that track the general flow of the application. These logs should have long-term value. + /// + Information = 2, + + /// + /// Logs that highlight an abnormal or unexpected event in the application flow, but do not otherwise cause the + /// application execution to stop. + /// + Warning = 3, + + /// + /// Logs that highlight when the current flow of execution is stopped due to a failure. These should indicate a + /// failure in the current activity, not an application-wide failure. + /// + Error = 4, + + /// + /// Logs that describe an unrecoverable application or system crash, or a catastrophic failure that requires + /// immediate attention. + /// + Critical = 5, + + /// + /// Not used for writing log messages. Specifies that a logging category should not write any messages. + /// + None = 6, + } +} diff --git a/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs b/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs new file mode 100644 index 00000000..fa3460e8 --- /dev/null +++ b/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; + +namespace AdvancedSharpAdbClient.Logs +{ + /// + /// Represents a type used to perform logging. + /// + /// Aggregates most logging patterns to a single method. + public interface ILogger + { + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// The exception to log. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + void Log(LogLevel logLevel, Exception exception, string message, params object[] args); + } + + /// + /// A generic interface for logging where the category name is derived from the specified + /// type name. + /// Generally used to enable activation of a named from dependency injection. + /// + /// The type whose name is used for the logger category name. + public interface ILogger : ILogger + { + + } +} diff --git a/AdvancedSharpAdbClient/Logs/Interfaces/ILoggerFactory.cs b/AdvancedSharpAdbClient/Logs/Interfaces/ILoggerFactory.cs new file mode 100644 index 00000000..62f1096b --- /dev/null +++ b/AdvancedSharpAdbClient/Logs/Interfaces/ILoggerFactory.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; + +namespace AdvancedSharpAdbClient.Logs +{ + /// + /// Represents a type used to configure the logging system and create instances of . + /// + public interface ILoggerFactory : IDisposable + { + /// + /// Creates a new instance. + /// + /// The category name for messages produced by the logger. + /// The . + ILogger CreateLogger(string categoryName); + + /// + /// Creates a new instance. + /// + /// The category name for messages produced by the logger. + /// The . + ILogger CreateLogger(); + } +} diff --git a/AdvancedSharpAdbClient/Logs/LoggerProvider.cs b/AdvancedSharpAdbClient/Logs/LoggerProvider.cs new file mode 100644 index 00000000..f2bc3026 --- /dev/null +++ b/AdvancedSharpAdbClient/Logs/LoggerProvider.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +namespace AdvancedSharpAdbClient.Logs +{ + /// + /// Provides a mechanism for creating instances of and classes. + /// + public static class LoggerProvider + { + private static ILoggerFactory _loggerFactory = null; + + /// + /// Sets the current log provider based on logger factory. + /// + /// The logger factory. + public static void SetLogProvider(ILoggerFactory loggerFactory) => _loggerFactory = loggerFactory; + + /// + /// Creates a new instance. + /// + /// The category name for messages produced by the logger. + /// A new instance. + public static ILogger CreateLogger(string category) => _loggerFactory == null ? NullLogger.Instance : _loggerFactory.CreateLogger(category); + + /// + /// Creates a new instance using the full name of the given type. + /// + /// The type. + /// The that was created + public static ILogger CreateLogger() => _loggerFactory == null ? NullLogger.Instance : _loggerFactory.CreateLogger(); + } +} diff --git a/AdvancedSharpAdbClient/Logs/NullLogger.cs b/AdvancedSharpAdbClient/Logs/NullLogger.cs new file mode 100644 index 00000000..229254cc --- /dev/null +++ b/AdvancedSharpAdbClient/Logs/NullLogger.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; + +namespace AdvancedSharpAdbClient.Logs +{ + /// + /// Minimalistic logger that does nothing. + /// + public class NullLogger : ILogger + { + /// + /// Returns the shared instance of . + /// + public static NullLogger Instance { get; } = new(); + + /// + public void Log(LogLevel logLevel, Exception exception, string message, params object[] args) { } + } + + /// + /// Minimalistic logger that does nothing. + /// + public class NullLogger : NullLogger, ILogger + { + /// + /// Returns an instance of . + /// + /// An instance of . + public static new NullLogger Instance { get; } = new(); + } +} diff --git a/AdvancedSharpAdbClient/Logs/NullLoggerT.cs b/AdvancedSharpAdbClient/Logs/NullLoggerT.cs deleted file mode 100644 index 8d60373b..00000000 --- a/AdvancedSharpAdbClient/Logs/NullLoggerT.cs +++ /dev/null @@ -1,55 +0,0 @@ -#if HAS_OLDLOGGER -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Logging; -using System; - -namespace Microsoft.Extensions.Logging.Abstractions -{ - /// - /// Minimalistic logger that does nothing. - /// - public class NullLogger : ILogger - { - /// - /// Returns an instance of . - /// - /// An instance of . - public static readonly NullLogger Instance = new(); - - /// - public IDisposable BeginScope(TState state) => NullScope.Instance; - - /// - /// - /// This method ignores the parameters and does nothing. - /// - public void Log( - LogLevel logLevel, - EventId eventId, - TState state, - Exception exception, - Func formatter) - { - } - - /// - public bool IsEnabled(LogLevel logLevel) => false; - } - - internal sealed class NullScope : IDisposable - { - public static NullScope Instance { get; } = new NullScope(); - - private NullScope() - { - } - - /// - public void Dispose() - { - } - } -} -#endif diff --git a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs index 56cd0031..24e9282d 100644 --- a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs +++ b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs @@ -30,11 +30,6 @@ global using System.Threading.Tasks; #endif -#if HAS_LOGGER -global using Microsoft.Extensions.Logging; -global using Microsoft.Extensions.Logging.Abstractions; -#endif - #if HAS_BUFFERS global using System.Buffers; #endif diff --git a/AdvancedSharpAdbClient/Receivers/ConsoleOutputReceiver.cs b/AdvancedSharpAdbClient/Receivers/ConsoleOutputReceiver.cs index 69265c31..97082d73 100644 --- a/AdvancedSharpAdbClient/Receivers/ConsoleOutputReceiver.cs +++ b/AdvancedSharpAdbClient/Receivers/ConsoleOutputReceiver.cs @@ -3,6 +3,7 @@ // using AdvancedSharpAdbClient.Exceptions; +using AdvancedSharpAdbClient.Logs; using System.Collections.Generic; using System.IO; using System.Text; @@ -14,46 +15,24 @@ namespace AdvancedSharpAdbClient /// Receives console output, and makes the console output available as a . To /// fetch the console output that was received, used the method. /// - public partial class ConsoleOutputReceiver : MultiLineReceiver + /// The logger to use when logging. + public partial class ConsoleOutputReceiver(ILogger logger = null) : MultiLineReceiver { /// /// The default to use when parsing the output. /// protected const RegexOptions DefaultRegexOptions = RegexOptions.Singleline | RegexOptions.IgnoreCase; -#if HAS_LOGGER /// /// The logger to use when logging messages. /// - protected readonly ILogger logger; -#endif + protected readonly ILogger logger = logger ?? LoggerProvider.CreateLogger(); /// /// A which receives all output from the device. /// protected readonly StringBuilder output = new(); -#if !HAS_LOGGER -#pragma warning disable CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif - /// - /// Initializes a new instance of the class. - /// - /// The logger to use when logging. - public ConsoleOutputReceiver( -#if HAS_LOGGER - ILogger logger = null -#endif - ) - { -#if HAS_LOGGER - this.logger = logger ?? NullLogger.Instance; -#endif - } -#if !HAS_LOGGER -#pragma warning restore CS1572 // XML 注释中有 param 标记,但是没有该名称的参数 -#endif - /// /// Gets a that represents the current . /// @@ -70,35 +49,27 @@ public virtual void ThrowOnError(string line) { if (line.EndsWith(": not found")) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: '{line}'"); -#endif throw new FileNotFoundException($"The remote execution returned: '{line}'"); } if (line.EndsWith("No such file or directory")) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: {line}"); -#endif throw new FileNotFoundException($"The remote execution returned: '{line}'"); } // for "unknown options" if (line.Contains("Unknown option")) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: {line}"); -#endif throw new UnknownOptionException($"The remote execution returned: '{line}'"); } // for "aborting" commands if (AbortingRegex().IsMatch(line)) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: {line}"); -#endif throw new CommandAbortingException($"The remote execution returned: '{line}'"); } @@ -106,9 +77,7 @@ public virtual void ThrowOnError(string line) // cmd: applet not found if (AppletRegex().IsMatch(line)) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: '{line}'"); -#endif throw new FileNotFoundException($"The remote execution returned: '{line}'"); } @@ -116,9 +85,7 @@ public virtual void ThrowOnError(string line) // workitem: 16822 if (DeniedRegex().IsMatch(line)) { -#if HAS_LOGGER logger.LogWarning($"The remote execution returned: '{line}'"); -#endif throw new PermissionDeniedException($"The remote execution returned: '{line}'"); } } @@ -137,9 +104,7 @@ protected override void ProcessNewLines(IEnumerable lines) continue; } output.AppendLine(line); -#if HAS_LOGGER logger.LogDebug(line); -#endif } }