Implement new TaskQueue and add LogFormatBuilder

This commit is contained in:
Stone_Red
2024-03-14 11:23:32 +01:00
parent df7a14bd6e
commit cb6d3f9271
11 changed files with 670 additions and 240 deletions
+26 -14
View File
@@ -1,10 +1,9 @@
using Stone_Red_C_Sharp_Utilities;
using Stone_Red_C_Sharp_Utilities.Logging;
using Stone_Red_C_Sharp_Utilities.Logging;
using Stone_Red_C_Sharp_Utilities.Tasks;
using Stone_Red_Utilities.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Stone_Red_C_Sharp_Utilities_Test
@@ -17,45 +16,58 @@ namespace Stone_Red_C_Sharp_Utilities_Test
{
FatalConfig = new OutputConfig()
{
Color = ConsoleColor.DarkRed,
ConsoleColor = ConsoleColor.DarkRed,
LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File
},
ErrorConfig = new OutputConfig()
{
Color = ConsoleColor.Red,
ConsoleColor = ConsoleColor.Red,
LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File
},
WarnConfig = new OutputConfig()
{
Color = ConsoleColor.Yellow,
ConsoleColor = ConsoleColor.Yellow,
LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File
},
InfoConfig = new OutputConfig()
{
Color = ConsoleColor.White,
ConsoleColor = ConsoleColor.White,
LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File
},
DebugConfig = new OutputConfig()
{
Color = ConsoleColor.Gray,
ConsoleColor = ConsoleColor.Gray,
LogTarget = LogTarget.Console | LogTarget.DebugConsole
},
FormatConfig = new FormatConfig()
{
ConsoleFormat = $"{{{LogFormatType.DateTime}:HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Message}}}"
//ConsoleFormat = $"{{{LogFormatType.DateTime}:HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Message}}}"
ConsoleFormat = new LogFormatBuilder().DateTime("HH:mm:ss").Text(" | ").LogSeverity(padding: -5).Text(" | ").Message()
}
}
};
private static async Task Main()
private static void Main()
{
TaskQueue taskQueue = new TaskQueue();
await taskQueue.Enqueue(() => Console.WriteLine("YES1"));
await taskQueue.Enqueue(() => Console.WriteLine("YES2"));
await taskQueue.Enqueue(() => Thread.Sleep(2000));
await taskQueue.Enqueue(() => Console.WriteLine("YES3"));
_ = taskQueue.Enqueue(CreateTask(0, 1000)).Subscribe((Task t) => logger.LogInfo("Task 0 completed"));
_ = taskQueue.Enqueue(CreateTask(1, 100)).Subscribe((Task t) => logger.LogInfo("Task 1 completed"));
_ = taskQueue.Enqueue(CreateTask(2, 2000)).Subscribe((Task t) => logger.LogInfo("Task 2 completed"));
_ = taskQueue.Enqueue(CreateTask(3, 500)).Subscribe((Task t) => logger.LogInfo("Task 3 completed"));
logger.Log("wow", LogSeverity.Info);
_ = Console.ReadLine();
}
private static Task CreateTask(int i, int delay)
{
return new Task(async () =>
{
logger.LogInfo($"Start task {i}");
await Task.Delay(delay);
logger.LogInfo($"End task {i}");
});
}
}
}
@@ -1,8 +1,8 @@
using Stone_Red_C_Sharp_Utilities.Logging;
using Stone_Red_Utilities.Logging;
using System;
namespace Stone_Red_Utilities.Logging
namespace Stone_Red_C_Sharp_Utilities.Logging
{
/// <summary>
/// Logging configuration.
@@ -48,7 +48,7 @@ namespace Stone_Red_Utilities.Logging
/// <summary>
/// The console color of the log message.
/// </summary>
public ConsoleColor Color { get; set; } = ConsoleColor.White;
public ConsoleColor ConsoleColor { get; set; } = ConsoleColor.White;
/// <summary>
/// The target for the log message.
@@ -69,16 +69,16 @@ namespace Stone_Red_Utilities.Logging
/// <summary>
/// The format for the debug console.
/// </summary>
public string DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
public LogFormatBuilder DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
/// <summary>
/// The format for the console.
/// </summary>
public string ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
public LogFormatBuilder ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
/// <summary>
/// The format for the log file.
/// </summary>
public string FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
public LogFormatBuilder FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
}
}
@@ -0,0 +1,147 @@
using System.Text;
namespace Stone_Red_C_Sharp_Utilities.Logging
{
/// <summary>
/// A builder for <see cref="FormatConfig"/>
/// </summary>
public class LogFormatBuilder
{
private readonly StringBuilder stringBuilder = new StringBuilder();
/// <summary>
/// Creates a new <see cref="LogFormatBuilder"/> instance.
/// </summary>
public LogFormatBuilder()
{
}
/// <summary>
/// Creates a new <see cref="LogFormatBuilder"/> instance.
/// </summary>
/// <param name="value">The inital format.</param>
public LogFormatBuilder(string value)
{
_ = stringBuilder.Append(value);
}
/// <summary>
/// Appends text to the log format.
/// </summary>
/// <param name="value">The text to append.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder Text(string value)
{
_ = stringBuilder.Append(value);
return this;
}
/// <summary>
/// Appends the log datie time to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder DateTime(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.DateTime},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the log severity to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder LogSeverity(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.LogSeverity},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the line number to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder LineNumber(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.LineNumber},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the file path to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder FilePath(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.FilePath},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the log source to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder MemberName(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.MemberName},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the log source to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder Source(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.Source},{padding}{GetFormat(format)}}}");
return this;
}
/// <summary>
/// Appends the log message to the log format.
/// </summary>
/// <param name="format">The format to apply.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
public LogFormatBuilder Message(string format = "", int padding = 0)
{
_ = stringBuilder.Append($"{{{LogFormatType.Message},{padding}{GetFormat(format)}}}");
return this;
}
private string GetFormat(string format)
{
return string.IsNullOrWhiteSpace(format) ? string.Empty : $":{format}";
}
/// <summary>
/// Converts the <see cref="LogFormatBuilder" to <see cref="string"/>/>
/// </summary>
/// <param name="value">The <see cref="LogFormatBuilder"/> to convert.</param>
public static implicit operator string(LogFormatBuilder value)
{
return value.stringBuilder.ToString();
}
/// <summary>
/// Converts the <see cref="string" to <see cref="LogFormatBuilder"/>/>
/// </summary>
/// <param name="value">The <see cref="stringBuilder"/> to convert.</param>
public static implicit operator LogFormatBuilder(string value)
{
return new LogFormatBuilder(value);
}
}
}
@@ -1,7 +1,7 @@
namespace Stone_Red_Utilities.Logging
namespace Stone_Red_C_Sharp_Utilities.Logging
{
/// <summary>
/// Specifies the info type of the log message format.
/// Specifies the info type of the log message format.
/// </summary>
public static class LogFormatType
{
@@ -11,7 +11,7 @@
public const string DateTime = "<DateTime>";
/// <summary>
/// The <see cref="Logging.LogSeverity"/> of the log message.
/// The <see cref="LogSeverity"/> of the log message.
/// </summary>
public const string LogSeverity = "<LogSeverity>";
@@ -0,0 +1,283 @@
using Stone_Red_Utilities.Logging;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
namespace Stone_Red_C_Sharp_Utilities.Logging
{
/// <summary>
/// Class used for logging
/// </summary>
public class Logger
{
/// <summary>
/// The logging configuration.
/// </summary>
public LogConfig Config { get; set; }
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void Log(string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void Log(string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogInfo(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogWarn(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogWarn(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogError(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogFatal(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogFatal(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogDebug(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output if the condition is met
/// </summary>
/// <param name="condition"></param>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogIf(bool condition, string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (condition)
{
WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
}
/// <summary>
/// Log the message to the specified output if the condition is met
/// </summary>
/// <param name="condition"></param>
/// <param name="message"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogIf(bool condition, string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (condition)
{
WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
}
/// <summary>
/// Clears the log file
/// </summary>
public void ClearLogFile(LogSeverity logSeverity)
{
OutputConfig outputConfig = GetOutputConfig(logSeverity);
lock (outputConfig)
{
if (File.Exists(outputConfig.FilePath))
{
File.WriteAllText(outputConfig.FilePath, string.Empty);
}
}
}
private void WriteLog(string message, string source, LogSeverity logSeverity, string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0)
{
Config ??= new LogConfig();
string consoleOutput = GetFormattedString(Config.FormatConfig.ConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
string debugOutput = GetFormattedString(Config.FormatConfig.DebugConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
string fileOutput = GetFormattedString(Config.FormatConfig.FileFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
OutputConfig outputConfig = GetOutputConfig(logSeverity);
if ((outputConfig.LogTarget & LogTarget.Console) == LogTarget.Console)
{
ConsoleExt.WriteLine(consoleOutput, outputConfig.ConsoleColor);
}
if ((outputConfig.LogTarget & LogTarget.DebugConsole) == LogTarget.DebugConsole)
{
Trace.WriteLine(debugOutput);
}
lock (outputConfig)
{
if ((outputConfig.LogTarget & LogTarget.File) == LogTarget.File)
{
if (!File.Exists(outputConfig.FilePath))
{
File.Create(outputConfig.FilePath).Close();
}
File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput });
}
}
}
private OutputConfig GetOutputConfig(LogSeverity logSeverity)
{
return logSeverity switch
{
LogSeverity.Fatal => Config.FatalConfig,
LogSeverity.Error => Config.ErrorConfig,
LogSeverity.Warn => Config.WarnConfig,
LogSeverity.Info => Config.InfoConfig,
_ => Config.DebugConfig
};
}
private string GetFormattedString(string format, LogSeverity logSeverity, string source, string message, string memberName, string sourceFilePath, int sourceLineNumber)
{
format = format
.Replace(LogFormatType.DateTime, "0")
.Replace(LogFormatType.LogSeverity, "1")
.Replace(LogFormatType.LineNumber, "2")
.Replace(LogFormatType.FilePath, "3")
.Replace(LogFormatType.MemberName, "4")
.Replace(LogFormatType.Source, "5")
.Replace(LogFormatType.Message, "6");
return string.Format(format, DateTime.Now, logSeverity.ToString().ToUpper(), sourceLineNumber, sourceFilePath, memberName, source, message);
}
}
}
@@ -1,158 +0,0 @@
using Stone_Red_Utilities.Logging;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
namespace Stone_Red_C_Sharp_Utilities.Logging
{
/// <summary>
/// Class used for logging
/// </summary>
public class Logger
{
/// <summary>
/// The logging configuration.
/// </summary>
public LogConfig Config { get; set; }
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void Log(string message, string source, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output
/// </summary>
/// <param name="message"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void Log(string message, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
/// <summary>
/// Log the message to the specified output if the condition is met
/// </summary>
/// <param name="condition"></param>
/// <param name="message"></param>
/// <param name="source"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogIf(bool condition, string message, string source, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (condition)
{
WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
}
/// <summary>
/// Log the message to the specified output if the condition is met
/// </summary>
/// <param name="condition"></param>
/// <param name="message"></param>
/// <param name="logSeverity"></param>
/// <param name="memberName"></param>
/// <param name="sourceFilePath"></param>
/// <param name="sourceLineNumber"></param>
public void LogIf(bool condition, string message, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (condition)
{
WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber);
}
}
/// <summary>
/// Clears the log file
/// </summary>
public void ClearLogFile(LogSeverity logSeverity)
{
OutputConfig outputConfig = GetOutputConfig(logSeverity);
lock (outputConfig)
{
if (File.Exists(outputConfig.FilePath))
{
File.WriteAllText(outputConfig.FilePath, string.Empty);
}
}
}
private void WriteLog(string message, string source, LogSeverity logSeverity, string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0)
{
Config ??= new LogConfig();
string consoleOutput = GetFormattedString(Config.FormatConfig.ConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
string debugOutput = GetFormattedString(Config.FormatConfig.DebugConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
string fileOutput = GetFormattedString(Config.FormatConfig.FileFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber);
OutputConfig outputConfig = GetOutputConfig(logSeverity);
if ((outputConfig.LogTarget & LogTarget.Console) == LogTarget.Console)
{
ConsoleExt.WriteLine(consoleOutput, outputConfig.Color);
}
if ((outputConfig.LogTarget & LogTarget.DebugConsole) == LogTarget.DebugConsole)
{
Trace.WriteLine(debugOutput);
}
lock (outputConfig)
{
if ((outputConfig.LogTarget & LogTarget.File) == LogTarget.File)
{
if (!File.Exists(outputConfig.FilePath))
{
File.Create(outputConfig.FilePath).Close();
}
File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput });
}
}
}
private OutputConfig GetOutputConfig(LogSeverity logSeverity)
{
return logSeverity switch
{
LogSeverity.Fatal => Config.FatalConfig,
LogSeverity.Error => Config.ErrorConfig,
LogSeverity.Warn => Config.WarnConfig,
LogSeverity.Info => Config.InfoConfig,
_ => Config.DebugConfig
};
}
private string GetFormattedString(string format, LogSeverity logSeverity, string source, string message, string memberName, string sourceFilePath, int sourceLineNumber)
{
format = format
.Replace(LogFormatType.DateTime, "0")
.Replace(LogFormatType.LogSeverity, "1")
.Replace(LogFormatType.LineNumber, "2")
.Replace(LogFormatType.FilePath, "3")
.Replace(LogFormatType.MemberName, "4")
.Replace(LogFormatType.Source, "5")
.Replace(LogFormatType.Message, "6");
return string.Format(format, DateTime.Now, logSeverity.ToString().ToUpper(), sourceLineNumber, sourceFilePath, memberName, source, message);
}
}
}
@@ -33,6 +33,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Reactive" Version="6.0.0" />
<PackageReference Include="System.Reactive.Linq" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="5.0.2" />
<PackageReference Include="Vsxmd" Version="1.4.5">
<PrivateAssets>all</PrivateAssets>
-59
View File
@@ -1,59 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Stone_Red_C_Sharp_Utilities
{
/// <summary>
/// An <see langword="asnyc"/> queue.
/// </summary>
public class TaskQueue
{
private readonly SemaphoreSlim semaphore;
/// <summary>
/// Creates a new <see cref="TaskQueue"/>
/// </summary>
public TaskQueue()
{
semaphore = new SemaphoreSlim(1);
}
/// <summary>
/// Enqueues a <see cref="Func{T}"/>.
/// </summary>
/// <typeparam name="T">The return type.</typeparam>
/// <param name="function">The code to enqueue.</param>
/// <returns>A <see cref="Task{T}"/> to await</returns>
public async Task<T> Enqueue<T>(Func<T> function)
{
await semaphore.WaitAsync();
try
{
return await Task.Run(function);
}
finally
{
_ = semaphore.Release();
}
}
/// <summary>
/// Enqueues an <see cref="Action"/>.
/// </summary>
/// <param name="function">The code to enqueue.</param>
/// <returns>A <see cref="Task{T}"/> to await</returns>
public async Task Enqueue(Action function)
{
await semaphore.WaitAsync();
try
{
await Task.Run(function);
}
finally
{
_ = semaphore.Release();
}
}
}
}
@@ -0,0 +1,78 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Stone_Red_C_Sharp_Utilities.Tasks
{
/// <summary>
/// An <see langword="asnyc"/> queue.
/// </summary>
public class BlockingTaskQueue : ITaskQueue
{
private readonly SemaphoreSlim semaphore;
/// <summary>
/// Creates a new <see cref="BlockingTaskQueue"/>
/// </summary>
public BlockingTaskQueue()
{
semaphore = new SemaphoreSlim(1);
}
/// <inheritdoc cref="ITaskQueue.Enqueue{T}(Func{T})"/>
public async Task<T> Enqueue<T>(Func<T> function)
{
await semaphore.WaitAsync();
try
{
return await Task.Run(function);
}
finally
{
_ = semaphore.Release();
}
}
/// <inheritdoc cref="ITaskQueue.Enqueue(Action)"/>
public async Task Enqueue(Action function)
{
await semaphore.WaitAsync();
try
{
await Task.Run(function);
}
finally
{
_ = semaphore.Release();
}
}
/// <inheritdoc cref="ITaskQueue.Enqueue(Task)"/>
public async Task Enqueue(Task task)
{
await semaphore.WaitAsync();
try
{
await task;
}
finally
{
_ = semaphore.Release();
}
}
/// <inheritdoc cref="ITaskQueue.Enqueue{T}(Task{T})"/>
public async Task<T> Enqueue<T>(Task<T> task)
{
await semaphore.WaitAsync();
try
{
return await task;
}
finally
{
_ = semaphore.Release();
}
}
}
}
@@ -0,0 +1,37 @@
using System;
using System.Threading.Tasks;
namespace Stone_Red_C_Sharp_Utilities.Tasks
{
internal interface ITaskQueue
{
/// <summary>
/// Enqueues a <see cref="Func{T}"/>.
/// </summary>
/// <typeparam name="T">The return type.</typeparam>
/// <param name="function">The code to enqueue.</param>
/// <returns>A <see cref="Task{T}"/> to await</returns>
public Task<T> Enqueue<T>(Func<T> function);
/// <summary>
/// Enqueues an <see cref="Action"/>.
/// </summary>
/// <param name="function">The code to enqueue.</param>
/// <returns>A <see cref="Task{T}"/> to await</returns>
public Task Enqueue(Action function);
/// <summary>
/// Enqueues an <see cref="Task"/>.
/// </summary>
/// <param name="task">The code to enqueue.</param>
/// <returns>A <see cref="Task"/> to await</returns>
public Task Enqueue(Task task);
/// <summary>
/// Enqueues an <see cref="Task"/>.
/// </summary>
/// <param name="task">The code to enqueue.</param>
/// <returns>A <see cref="Task"/> to await</returns>
public Task<T> Enqueue<T>(Task<T> task);
}
}
@@ -0,0 +1,88 @@
using System;
using System.Collections.Concurrent;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks;
namespace Stone_Red_C_Sharp_Utilities.Tasks
{
/// <summary>
/// An <see langword="asnyc"/> queue.
/// </summary>
public class TaskQueue
{
private readonly ConcurrentQueue<(Task Task, Action Callback)> tasks = new ConcurrentQueue<(Task Task, Action Callback)>();
private bool processing = false;
/// <inheritdoc cref="ITaskQueue.Enqueue{T}(Func{T})"/>
public IObservable<Task<T>> Enqueue<T>(Func<T> function)
{
Subject<Task<T>> subject = new Subject<Task<T>>();
Task<T> task = new Task<T>(function);
tasks.Enqueue((task, () => subject.OnNext(task)));
ProcessTasks();
return subject.AsObservable();
}
/// <inheritdoc cref="ITaskQueue.Enqueue(Action)"/>
public IObservable<Task> Enqueue(Action function)
{
Subject<Task> subject = new Subject<Task>();
Task task = new Task(function);
tasks.Enqueue((task, () => subject.OnNext(task)));
ProcessTasks();
return subject.AsObservable();
}
/// <inheritdoc cref="ITaskQueue.Enqueue(Task)"/>
public IObservable<Task> Enqueue(Task task)
{
Subject<Task> subject = new Subject<Task>();
tasks.Enqueue((task, () => subject.OnNext(task)));
ProcessTasks();
return subject.AsObservable();
}
/// <inheritdoc cref="ITaskQueue.Enqueue{T}(Task{T})"/>
public IObservable<Task<T>> Enqueue<T>(Task<T> task)
{
Subject<Task<T>> subject = new Subject<Task<T>>();
tasks.Enqueue((task, () => subject.OnNext(task)));
ProcessTasks();
return subject.AsObservable();
}
private async void ProcessTasks()
{
if (processing)
{
return;
}
processing = true;
while (tasks.TryDequeue(out (Task Task, Action Callback) container))
{
if (container.Task.Status == TaskStatus.Created)
{
container.Task.Start();
}
await container.Task;
container.Callback?.Invoke();
}
}
}
}