diff --git a/DTLib.Logging/DTLib.Logging.csproj b/DTLib.Logging/DTLib.Logging.csproj new file mode 100644 index 0000000..4dc0bc5 --- /dev/null +++ b/DTLib.Logging/DTLib.Logging.csproj @@ -0,0 +1,23 @@ + + + + net6.0;net48 + 10 + disable + disable + true + embedded + False + Debug;Release + AnyCPU;x64;x86;arm64 + + + + + + + + + + + diff --git a/DTLib.Logging/Global.cs b/DTLib.Logging/Global.cs new file mode 100644 index 0000000..6f7c1f3 --- /dev/null +++ b/DTLib.Logging/Global.cs @@ -0,0 +1,11 @@ +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text; +global using System.Threading.Tasks; +global using DTLib.Extensions; +global using DTLib.Filesystem; + +namespace DTLib.Logging.New; + diff --git a/DTLib.Logging/LogFormats/DefaultLogFormat.cs b/DTLib.Logging/LogFormats/DefaultLogFormat.cs new file mode 100644 index 0000000..144f637 --- /dev/null +++ b/DTLib.Logging/LogFormats/DefaultLogFormat.cs @@ -0,0 +1,28 @@ +namespace DTLib.Logging.New; + +public class DefaultLogFormat : ILogFormat +{ + + public bool PrintTimeStamp { get; set; } + public bool PrintContext { get; set; } + public bool PrintSeverity { get; set; } + + public DefaultLogFormat(bool printTimeStamp = false, bool printContext = true, bool printSeverity = true) + { + PrintTimeStamp = printTimeStamp; + PrintContext = printContext; + PrintSeverity = printSeverity; + } + + public string CreateMessage(string context, LogSeverity severity, object message) + { + var sb = new StringBuilder(); + if (PrintTimeStamp) sb.Append('[').Append(DateTime.Now.ToString(MyTimeFormat.ForText)).Append(']'); + if(PrintContext) sb.Append('[').Append(context).Append(']'); + if(PrintSeverity) sb.Append('[').Append(severity.ToString()).Append(']'); + if (sb.Length != 0) sb.Append(": "); + sb.Append(message.ToString()); + sb.Append('\n'); + return sb.ToString(); + } +} \ No newline at end of file diff --git a/DTLib.Logging/LogFormats/ILogFormat.cs b/DTLib.Logging/LogFormats/ILogFormat.cs new file mode 100644 index 0000000..3b1834f --- /dev/null +++ b/DTLib.Logging/LogFormats/ILogFormat.cs @@ -0,0 +1,10 @@ +namespace DTLib.Logging.New; + +public interface ILogFormat +{ + bool PrintTimeStamp { get; set; } + bool PrintContext { get; set; } + bool PrintSeverity { get; set; } + + string CreateMessage(string context, LogSeverity severity, object message); +} \ No newline at end of file diff --git a/DTLib.Logging/LogSeverity.cs b/DTLib.Logging/LogSeverity.cs new file mode 100644 index 0000000..dd8ddec --- /dev/null +++ b/DTLib.Logging/LogSeverity.cs @@ -0,0 +1,9 @@ +namespace DTLib.Logging.New; + +public enum LogSeverity +{ + Debug=1, + Info=2, + Warn=4, + Error=8 +} \ No newline at end of file diff --git a/DTLib.Logging/Loggers/CompositeLogger.cs b/DTLib.Logging/Loggers/CompositeLogger.cs new file mode 100644 index 0000000..d6a0c0c --- /dev/null +++ b/DTLib.Logging/Loggers/CompositeLogger.cs @@ -0,0 +1,38 @@ +namespace DTLib.Logging.New; + +/// +/// This class can be used for unite many loggers into one +/// +public class CompositeLogger : ILogger +{ + public ILogFormat Format { get; } + protected ILogger[] _loggers; + + public CompositeLogger(ILogFormat format, params ILogger[] loggers) + { + Format = format; + _loggers = loggers; + } + + public CompositeLogger(params ILogger[] loggers) : this(new DefaultLogFormat(), loggers) + {} + + + public void Log(string context, LogSeverity severity, object message, ILogFormat format) + { + for (int i = 0; i < _loggers.Length; i++) + _loggers[i].Log(context, severity, message, format); + } + + public void Log(string context, LogSeverity severity, object message) + => Log(context, severity, message, Format); + + + public void Dispose() + { + for (int i = 0; i < _loggers.Length; i++) + { + _loggers[i].Dispose(); + } + } +} \ No newline at end of file diff --git a/DTLib.Logging/Loggers/ConsoleLogger.cs b/DTLib.Logging/Loggers/ConsoleLogger.cs new file mode 100644 index 0000000..6f9e660 --- /dev/null +++ b/DTLib.Logging/Loggers/ConsoleLogger.cs @@ -0,0 +1,33 @@ +namespace DTLib.Logging.New; + +// вывод лога в консоль и файл +public class ConsoleLogger : ILogger +{ + readonly object consolelocker = new(); + public ILogFormat Format { get; } + + public ConsoleLogger(ILogFormat format) + => Format = format; + + public ConsoleLogger() : this(new DefaultLogFormat()) + {} + + + public void Log(string context, LogSeverity severity, object message, ILogFormat format) + { + var msg = format.CreateMessage(context, severity, message); + lock (consolelocker) + ColoredConsole.Write(msg); + } + + public void Log(string context, LogSeverity severity, object message) + => Log(context, severity, message, Format); + + + public void Dispose() + { + lock (consolelocker) {} + } + + ~ConsoleLogger() => Dispose(); +} diff --git a/DTLib.Logging/Loggers/FileLogger.cs b/DTLib.Logging/Loggers/FileLogger.cs new file mode 100644 index 0000000..bfd1de7 --- /dev/null +++ b/DTLib.Logging/Loggers/FileLogger.cs @@ -0,0 +1,52 @@ +namespace DTLib.Logging.New; + +public class FileLogger : ILogger +{ + public ILogFormat Format { get; } + + public string LogfileName { get; protected set; } + public System.IO.FileStream LogfileStream { get; protected set; } + + public FileLogger(string logfile, ILogFormat format) + { + Format = format; + LogfileName = logfile; + LogfileStream = File.OpenAppend(logfile); + } + + public FileLogger(string logfile) : this(logfile, new DefaultLogFormat()) + {} + + public FileLogger(string dir, string programName, ILogFormat format) + : this($"{dir}{Путь.Разд}{programName}_{DateTime.Now.ToString(MyTimeFormat.ForFileNames)}.log", format) + {} + + public FileLogger(string dir, string programName) : this(dir, programName, new DefaultLogFormat()) + {} + + public void Log(string context, LogSeverity severity, object message, ILogFormat format) + { + var msg = format.CreateMessage(context, severity, format).ToBytes(StringConverter.UTF8); + lock (LogfileStream) + { + LogfileStream.Write(msg); + LogfileStream.Flush(); + } + } + + public void Log(string context, LogSeverity severity, object message) + => Log(context, severity, message, Format); + + public virtual void Dispose() + { + try + { + LogfileStream?.Flush(); + LogfileStream?.Close(); + LogfileStream?.Dispose(); + } + catch (ObjectDisposedException) { } + } + + ~FileLogger() => Dispose(); +} diff --git a/DTLib.Logging/Loggers/ILogger.cs b/DTLib.Logging/Loggers/ILogger.cs new file mode 100644 index 0000000..3fbbdfb --- /dev/null +++ b/DTLib.Logging/Loggers/ILogger.cs @@ -0,0 +1,9 @@ +namespace DTLib.Logging.New; + +public interface ILogger : IDisposable +{ + + ILogFormat Format { get; } + void Log(string context, LogSeverity severity, object message); + void Log(string context, LogSeverity severity, object message, ILogFormat format); +} \ No newline at end of file diff --git a/DTLib.Logging/Microsoft/LoggerService.cs b/DTLib.Logging/Microsoft/LoggerService.cs new file mode 100644 index 0000000..e24b827 --- /dev/null +++ b/DTLib.Logging/Microsoft/LoggerService.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Logging; + +namespace DTLib.Logging.New.Microsoft; + +public class LoggerService : IServiceProvider +{ + ILogger _logger; + + public LoggerService(ILogger logger) + { + _logger = logger; + } + + public object GetService(Type serviceType) + { + return new MyLoggerWrapper(_logger); + } +} \ No newline at end of file diff --git a/DTLib.Logging/Microsoft/MyLoggerWrapper.cs b/DTLib.Logging/Microsoft/MyLoggerWrapper.cs new file mode 100644 index 0000000..1295d6d --- /dev/null +++ b/DTLib.Logging/Microsoft/MyLoggerWrapper.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Logging; + +namespace DTLib.Logging.New.Microsoft; + +internal class MyLoggerWrapper : ILogger +{ + private ILogger _logger; + public MyLoggerWrapper(ILogger logger)=> + _logger = logger; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + string message = formatter(state, exception); + _logger.Log(nameof(TCaller), LogSeverity_FromLogLevel(logLevel), message); + } + + private bool _isEnabled=true; + public bool IsEnabled(LogLevel logLevel) => _isEnabled; + + public IDisposable BeginScope(TState state) + { + throw new NotImplementedException(); + } + + static LogSeverity LogSeverity_FromLogLevel(LogLevel l) + => l switch + { + LogLevel.Trace => LogSeverity.Debug, + LogLevel.Debug => LogSeverity.Debug, + LogLevel.Information => LogSeverity.Info, + LogLevel.Warning => LogSeverity.Warn, + LogLevel.Error => LogSeverity.Error, + LogLevel.Critical => LogSeverity.Error, + LogLevel.None => throw new NotImplementedException("LogLevel.None is not supported"), + _ => throw new ArgumentOutOfRangeException(nameof(l), l, null) + } + ; +} \ No newline at end of file diff --git a/DTLib.Tests/DTLib.Tests.csproj b/DTLib.Tests/DTLib.Tests.csproj index cce9ae1..240d82e 100644 --- a/DTLib.Tests/DTLib.Tests.csproj +++ b/DTLib.Tests/DTLib.Tests.csproj @@ -21,6 +21,7 @@ + diff --git a/DTLib.Tests/Program.cs b/DTLib.Tests/Program.cs index de48fb1..a30fcb4 100644 --- a/DTLib.Tests/Program.cs +++ b/DTLib.Tests/Program.cs @@ -8,7 +8,7 @@ global using DTLib; global using DTLib.Extensions; global using DTLib.Filesystem; global using DTLib.Dtsod; -global using static DTLib.Logging.Tester; +global using static DTLib.Tests.TesterLog; global using static DTLib.Tests.Program; using DTLib.Logging; diff --git a/DTLib/Logging/Tester.cs b/DTLib.Tests/Tester.cs similarity index 62% rename from DTLib/Logging/Tester.cs rename to DTLib.Tests/Tester.cs index 36709e9..d868e1a 100644 --- a/DTLib/Logging/Tester.cs +++ b/DTLib.Tests/Tester.cs @@ -1,9 +1,9 @@ using System.Diagnostics; -using System.Globalization; +using DTLib.Logging; -namespace DTLib.Logging; +namespace DTLib.Tests; -public static class Tester +public static class TesterLog { public static void LogOperationTime(string op_name, int repeats, Action operation) { @@ -13,6 +13,6 @@ public static class Tester operation(); clock.Stop(); double time=(double)(clock.ElapsedTicks)/Stopwatch.Frequency/repeats; - Log("y",$"operation ","b",op_name,"y"," lasted ","b",time.ToString(MyTimeFormat.ForText),"y"," seconds"); + PublicLog.Log("y",$"operation ","b",op_name,"y"," lasted ","b",time.ToString(MyTimeFormat.ForText),"y"," seconds"); } } \ No newline at end of file diff --git a/DTLib.sln b/DTLib.sln index d8569c9..b461fe0 100644 --- a/DTLib.sln +++ b/DTLib.sln @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.Dtsod", "DTLib.Dtsod\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.Network", "DTLib.Network\DTLib.Network.csproj", "{24B7D0A2-0462-424D-B3F5-29A6655FE472}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.Logging", "DTLib.Logging\DTLib.Logging.csproj", "{00B76172-32BB-4B72-9891-47FAEF63386C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {24B7D0A2-0462-424D-B3F5-29A6655FE472}.Debug|Any CPU.Build.0 = Debug|Any CPU {24B7D0A2-0462-424D-B3F5-29A6655FE472}.Release|Any CPU.ActiveCfg = Release|Any CPU {24B7D0A2-0462-424D-B3F5-29A6655FE472}.Release|Any CPU.Build.0 = Release|Any CPU + {00B76172-32BB-4B72-9891-47FAEF63386C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00B76172-32BB-4B72-9891-47FAEF63386C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00B76172-32BB-4B72-9891-47FAEF63386C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00B76172-32BB-4B72-9891-47FAEF63386C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE