Skip to content

Instantly share code, notes, and snippets.

@Saplonily
Last active August 31, 2023 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Saplonily/2b23e2cfa00223fa27c483af098d27e1 to your computer and use it in GitHub Desktop.
Save Saplonily/2b23e2cfa00223fa27c483af098d27e1 to your computer and use it in GitHub Desktop.
SalLogger, 但是单文件 (附较低语言版本的源码)
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Saladim.SalLogger
{
public delegate string LogFormatter(
LogLevel logLevel,
string section,
string? subSection,
string content
);
public delegate void LogAction(string content);
public partial class Logger
{
internal static readonly LogFormatter DefaultFormatter = DefaultFormatAction;
internal static string DefaultFormatAction(LogLevel logLevel, string section, string? subSection, string content)
=> $"[{DateTime.Now.TimeOfDay:hh\\:mm\\:ss\\.f}] [{logLevel}:{section}" + (subSection is null ? "" : $"/{subSection}") + $"]: {content}";
internal LogFormatter? Formatter = DefaultFormatter;
internal LogAction? LogAction;
internal LogLevel LogLevelLimit = LogLevel.Info;
internal Logger() { }
protected void LogRaw(string content)
{
LogAction?.Invoke(content);
}
public bool NeedLogging(LogLevel logLevel)
=> (int)logLevel >= (int)LogLevelLimit;
public void LogRaw(LogLevel logLevel, string str)
{
if (NeedLogging(logLevel))
{
LogRaw(str);
}
}
public void Log(LogLevel logLevel, string section, string? subSection, string content)
{
if (!NeedLogging(logLevel)) return;
string? str = Formatter?.Invoke(logLevel, section, subSection, content);
if (str is null) return;
LogRaw(str);
}
public void Log(LogLevel logLevel, string section, string content)
=> Log(logLevel, section, null, content);
public void Log(LogLevel logLevel, string section, string? subSection,
Exception exception, string? prefix = null, string? suffix = null, bool autoExtractChain = true)
{
if (!NeedLogging(logLevel)) return;
StringBuilder sb = new();
bool writePrefix = prefix is not null;
if (exception.InnerException is not null && autoExtractChain)
{
var exs = GetChainedExceptions(exception);
var firstException = exs[0];
if (writePrefix)
{
sb.AppendLine(prefix);
sb.Append(" - ");
}
sb.AppendLine($"{firstException.GetType()} - {firstException.Message}");
var enumator = exs.GetEnumerator();
enumator.MoveNext();
while (enumator.MoveNext())
{
sb.Append(" - ");
sb.AppendLine($"{enumator.Current.GetType()} - {enumator.Current.Message}");
sb.AppendLine(enumator.Current.StackTrace);
}
}
else
{
if (writePrefix)
{
sb.AppendLine(prefix);
sb.Append(" ");
}
sb.AppendLine($"{exception.GetType()} - {exception.Message}");
sb.Append(exception.StackTrace);
if (writePrefix) sb.AppendLine();
}
if (suffix is not null) sb.Append(" " + suffix);
this.Log(logLevel, section, subSection, sb.ToString());
}
public void Log(LogLevel logLevel, string section,
Exception exception, string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(logLevel, section, null, exception, prefix, suffix, autoExtractChain);
[DebuggerStepThrough]
public static List<Exception> GetChainedExceptions(Exception exception)
{
List<Exception> list = new();
Exception? cur = exception;
while (cur != null)
{
list.Add(cur);
cur = cur.InnerException;
}
return list;
}
}
public partial class Logger
{
#region Trace
public void LogTrace(string section, string subSection, string content)
=> Log(LogLevel.Trace, section, subSection, content);
public void LogTrace(string section, string content)
=> Log(LogLevel.Trace, section, null, content);
public void LogTrace(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Trace, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogTrace(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Trace, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Debug
public void LogDebug(string section, string subSection, string content)
=> Log(LogLevel.Debug, section, subSection, content);
public void LogDebug(string section, string content)
=> Log(LogLevel.Debug, section, null, content);
public void LogDebug(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Debug, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogDebug(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Debug, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Info
public void LogInfo(string section, string subSection, string content)
=> Log(LogLevel.Info, section, subSection, content);
public void LogInfo(string section, string content)
=> Log(LogLevel.Info, section, null, content);
public void LogInfo(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Info, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogInfo(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Info, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Warn
public void LogWarn(string section, string subSection, string content)
=> Log(LogLevel.Warn, section, subSection, content);
public void LogWarn(string section, string content)
=> Log(LogLevel.Warn, section, null, content);
public void LogWarn(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Warn, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogWarn(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Warn, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Error
public void LogError(string section, string subSection, string content)
=> Log(LogLevel.Error, section, subSection, content);
public void LogError(string section, string content)
=> Log(LogLevel.Error, section, null, content);
public void LogError(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Error, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogError(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Error, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Fatal
public void LogFatal(string section, string subSection, string content)
=> Log(LogLevel.Fatal, section, subSection, content);
public void LogFatal(string section, string content)
=> Log(LogLevel.Fatal, section, null, content);
public void LogFatal(string section, string subSection, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Fatal, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogFatal(string section, Exception exception,
string? prefix = null, string? suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Fatal, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
}
public enum LogLevel
{
Trace,
Debug,
Info,
Warn,
Error,
Fatal
}
public partial class LoggerBuilder
{
private LogAction? actions;
private LogFormatter? formatter;
private LogLevel levelLimit = LogLevel.Info;
private bool useCustomFormatter = false;
public Logger Build()
{
Logger logger = new()
{
LogAction = actions,
LogLevelLimit = levelLimit
};
if (useCustomFormatter)
{
logger.Formatter = formatter;
}
return logger;
}
public LoggerBuilder WithLevelLimit(LogLevel lowestLogLevel)
{
levelLimit = lowestLogLevel;
return this;
}
public LoggerBuilder WithAction(LogAction action)
{
actions += action;
return this;
}
public LoggerBuilder WithFormatter(LogFormatter formatter)
{
this.useCustomFormatter = true;
this.formatter = formatter;
return this;
}
public LoggerBuilder WithLogToConsole()
=> WithAction(Console.WriteLine);
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Saladim.SalLogger
{
public delegate string LogFormatter(
LogLevel logLevel,
string section,
string subSection,
string content
);
public delegate void LogAction(string content);
public partial class Logger
{
internal static readonly LogFormatter DefaultFormatter = DefaultFormatAction;
internal static string DefaultFormatAction(LogLevel logLevel, string section, string subSection, string content)
=> $"[{DateTime.Now.TimeOfDay:hh\\:mm\\:ss\\.f}] [{logLevel}:{section}" + (subSection == null ? "" : $"/{subSection}") + $"]: {content}";
internal LogFormatter Formatter = DefaultFormatter;
internal LogAction LogAction;
internal LogLevel LogLevelLimit = LogLevel.Info;
internal Logger() { }
protected void LogRaw(string content)
{
LogAction.Invoke(content);
}
public bool NeedLogging(LogLevel logLevel)
=> (int)logLevel >= (int)LogLevelLimit;
public void LogRaw(LogLevel logLevel, string str)
{
if (NeedLogging(logLevel))
{
LogRaw(str);
}
}
public void Log(LogLevel logLevel, string section, string subSection, string content)
{
if (!NeedLogging(logLevel)) return;
string str = Formatter.Invoke(logLevel, section, subSection, content);
if (str == null) return;
LogRaw(str);
}
public void Log(LogLevel logLevel, string section, string content)
=> Log(logLevel, section, null, content);
public void Log(LogLevel logLevel, string section, string subSection,
Exception exception, string prefix = null, string suffix = null, bool autoExtractChain = true)
{
if (!NeedLogging(logLevel)) return;
StringBuilder sb = new StringBuilder();
bool writePrefix = prefix != null;
if (exception.InnerException != null && autoExtractChain)
{
var exs = GetChainedExceptions(exception);
var firstException = exs[0];
if (writePrefix)
{
sb.AppendLine(prefix);
sb.Append(" - ");
}
sb.AppendLine($"{firstException.GetType()} - {firstException.Message}");
var enumator = exs.GetEnumerator();
enumator.MoveNext();
while (enumator.MoveNext())
{
sb.Append(" - ");
sb.AppendLine($"{enumator.Current.GetType()} - {enumator.Current.Message}");
sb.AppendLine(enumator.Current.StackTrace);
}
}
else
{
if (writePrefix)
{
sb.AppendLine(prefix);
sb.Append(" ");
}
sb.AppendLine($"{exception.GetType()} - {exception.Message}");
sb.Append(exception.StackTrace);
if (writePrefix) sb.AppendLine();
}
if (suffix != null) sb.Append(" " + suffix);
this.Log(logLevel, section, subSection, sb.ToString());
}
public void Log(LogLevel logLevel, string section,
Exception exception, string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(logLevel, section, null, exception, prefix, suffix, autoExtractChain);
[DebuggerStepThrough]
public static List<Exception> GetChainedExceptions(Exception exception)
{
List<Exception> list = new List<Exception>();
Exception cur = exception;
while (cur != null)
{
list.Add(cur);
cur = cur.InnerException;
}
return list;
}
}
public partial class Logger
{
#region Trace
public void LogTrace(string section, string subSection, string content)
=> Log(LogLevel.Trace, section, subSection, content);
public void LogTrace(string section, string content)
=> Log(LogLevel.Trace, section, null, content);
public void LogTrace(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Trace, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogTrace(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Trace, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Debug
public void LogDebug(string section, string subSection, string content)
=> Log(LogLevel.Debug, section, subSection, content);
public void LogDebug(string section, string content)
=> Log(LogLevel.Debug, section, null, content);
public void LogDebug(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Debug, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogDebug(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Debug, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Info
public void LogInfo(string section, string subSection, string content)
=> Log(LogLevel.Info, section, subSection, content);
public void LogInfo(string section, string content)
=> Log(LogLevel.Info, section, null, content);
public void LogInfo(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Info, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogInfo(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Info, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Warn
public void LogWarn(string section, string subSection, string content)
=> Log(LogLevel.Warn, section, subSection, content);
public void LogWarn(string section, string content)
=> Log(LogLevel.Warn, section, null, content);
public void LogWarn(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Warn, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogWarn(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Warn, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Error
public void LogError(string section, string subSection, string content)
=> Log(LogLevel.Error, section, subSection, content);
public void LogError(string section, string content)
=> Log(LogLevel.Error, section, null, content);
public void LogError(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Error, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogError(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Error, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
#region Fatal
public void LogFatal(string section, string subSection, string content)
=> Log(LogLevel.Fatal, section, subSection, content);
public void LogFatal(string section, string content)
=> Log(LogLevel.Fatal, section, null, content);
public void LogFatal(string section, string subSection, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Fatal, section, subSection, exception, prefix, suffix, autoExtractChain);
public void LogFatal(string section, Exception exception,
string prefix = null, string suffix = null, bool autoExtractChain = true)
=> Log(LogLevel.Fatal, section, null, exception, prefix, suffix, autoExtractChain);
#endregion
}
public enum LogLevel
{
Trace,
Debug,
Info,
Warn,
Error,
Fatal
}
public partial class LoggerBuilder
{
private LogAction actions;
private LogFormatter formatter;
private LogLevel levelLimit = LogLevel.Info;
private bool useCustomFormatter = false;
public Logger Build()
{
Logger logger = new Logger()
{
LogAction = actions,
LogLevelLimit = levelLimit
};
if (useCustomFormatter)
{
logger.Formatter = formatter;
}
return logger;
}
public LoggerBuilder WithLevelLimit(LogLevel lowestLogLevel)
{
levelLimit = lowestLogLevel;
return this;
}
public LoggerBuilder WithAction(LogAction action)
{
actions += action;
return this;
}
public LoggerBuilder WithFormatter(LogFormatter formatter)
{
this.useCustomFormatter = true;
this.formatter = formatter;
return this;
}
public LoggerBuilder WithLogToConsole()
=> WithAction(Console.WriteLine);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment