mirror of
https://github.com/Ellpeck/ExtremelySimpleLogger.git
synced 2024-11-27 11:58:34 +01:00
Compare commits
5 commits
66842eec40
...
5ca1073125
Author | SHA1 | Date | |
---|---|---|---|
5ca1073125 | |||
8e5bd41a47 | |||
034497201e | |||
cb824c73fc | |||
096bc98a05 |
6 changed files with 326 additions and 10 deletions
|
@ -5,6 +5,7 @@ using System.IO;
|
||||||
namespace ExtremelySimpleLogger {
|
namespace ExtremelySimpleLogger {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="Sink"/> that writes log output to <see cref="Console.Out"/> or <see cref="Console.Error"/>.
|
/// A <see cref="Sink"/> that writes log output to <see cref="Console.Out"/> or <see cref="Console.Error"/>.
|
||||||
|
/// This class is a variation of the <see cref="WriterSink"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ConsoleSink : Sink {
|
public class ConsoleSink : Sink {
|
||||||
|
|
||||||
|
@ -17,15 +18,17 @@ namespace ExtremelySimpleLogger {
|
||||||
{LogLevel.Error, ConsoleColor.DarkRed},
|
{LogLevel.Error, ConsoleColor.DarkRed},
|
||||||
{LogLevel.Fatal, ConsoleColor.DarkRed}
|
{LogLevel.Fatal, ConsoleColor.DarkRed}
|
||||||
};
|
};
|
||||||
private readonly object locker = new object();
|
|
||||||
private readonly TextWriter console;
|
private readonly TextWriter console;
|
||||||
|
private readonly bool useAnsiCodes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new console sink with the given settings.
|
/// Creates a new console sink with the given settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="error">Whether to log to <see cref="Console.Error"/> instead of <see cref="Console.Out"/>.</param>
|
/// <param name="error">Whether to log to <see cref="Console.Error"/> instead of <see cref="Console.Out"/>.</param>
|
||||||
public ConsoleSink(bool error = false) {
|
/// <param name="useAnsiCodes">Whether to wrap log output text in ANSI escape codes using <see cref="Extensions.WrapAnsiCode"/> instead of using the <see cref="Console.ForegroundColor"/> and <see cref="Console.ResetColor"/>. This may work better on some terminals.</param>
|
||||||
|
public ConsoleSink(bool error = false, bool useAnsiCodes = false) {
|
||||||
this.console = error ? Console.Error : Console.Out;
|
this.console = error ? Console.Error : Console.Out;
|
||||||
|
this.useAnsiCodes = useAnsiCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -63,12 +66,17 @@ namespace ExtremelySimpleLogger {
|
||||||
/// <param name="level">The importance level of this message</param>
|
/// <param name="level">The importance level of this message</param>
|
||||||
/// <param name="s">The message to log</param>
|
/// <param name="s">The message to log</param>
|
||||||
protected override void Log(Logger logger, LogLevel level, string s) {
|
protected override void Log(Logger logger, LogLevel level, string s) {
|
||||||
lock (this.locker) {
|
lock (this.console) {
|
||||||
var color = this.GetColor(level);
|
var color = this.GetColor(level);
|
||||||
if (color.HasValue)
|
if (color.HasValue) {
|
||||||
Console.ForegroundColor = color.Value;
|
if (this.useAnsiCodes) {
|
||||||
|
s = s.WrapAnsiCode(color.Value);
|
||||||
|
} else {
|
||||||
|
Console.ForegroundColor = color.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.console.WriteLine(s);
|
this.console.WriteLine(s);
|
||||||
if (color.HasValue)
|
if (color.HasValue && !this.useAnsiCodes)
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
ExtremelySimpleLogger/Extensions.cs
Normal file
45
ExtremelySimpleLogger/Extensions.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace ExtremelySimpleLogger {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extension methods for logging-related activities, like converting <see cref="ConsoleColor"/> to ANSI color codes.
|
||||||
|
/// </summary>
|
||||||
|
public static class Extensions {
|
||||||
|
|
||||||
|
private static readonly int[] AnsiCodes = new[] {
|
||||||
|
ConsoleColor.Black, ConsoleColor.DarkRed, ConsoleColor.DarkGreen, ConsoleColor.DarkYellow,
|
||||||
|
ConsoleColor.DarkBlue, ConsoleColor.DarkMagenta, ConsoleColor.DarkCyan, ConsoleColor.Gray,
|
||||||
|
ConsoleColor.DarkGray, ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Yellow,
|
||||||
|
ConsoleColor.Blue, ConsoleColor.Magenta, ConsoleColor.Cyan, ConsoleColor.White
|
||||||
|
}.Select((s, i) => (int) s).ToArray();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the given <see cref="ConsoleColor"/> to its ANSI escape sequence representation. If the supplied <paramref name="color"/> is <see langword="null"/>, the reset escape sequence for the given color type will be returned.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The color. If <see langword="null"/>, the reset escape sequence for the given color type will be returned.</param>
|
||||||
|
/// <param name="background">Whether to return a background color. If this is <see langword="false"/>, a foreground color is returned instead.</param>
|
||||||
|
/// <returns>The ANSI escape sequence representation of the given <paramref name="color"/>.</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">If the <paramref name="color"/> is not in defined range.</exception>
|
||||||
|
public static string ToAnsiCode(this ConsoleColor? color, bool background = false) {
|
||||||
|
if (color.HasValue) {
|
||||||
|
if (color < 0 || (int) color >= Extensions.AnsiCodes.Length)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(color), color, null);
|
||||||
|
return $"\x1B[{(background ? 48 : 38)};5;{Extensions.AnsiCodes[(int) color]}m";
|
||||||
|
}
|
||||||
|
return $"\x1B[{(background ? 49 : 39)}m";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the given string in the ANSI escape sequence representation of the given <paramref name="color"/> and the appropriate reset escape sequence using <see cref="ToAnsiCode"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s">The string to wrap.</param>
|
||||||
|
/// <param name="color">The color.</param>
|
||||||
|
/// <param name="background">Whether to use <paramref name="color"/> as a background color. If this is <see langword="false"/>, a foreground color is used instead.</param>
|
||||||
|
/// <returns>The given string, wrapped in ANSI color codes.</returns>
|
||||||
|
public static string WrapAnsiCode(this string s, ConsoleColor color, bool background = false) {
|
||||||
|
return Extensions.ToAnsiCode(color, background) + s + Extensions.ToAnsiCode(null, background);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageIcon>Logo.png</PackageIcon>
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
<VersionPrefix>1.3.3</VersionPrefix>
|
<VersionPrefix>1.4.1</VersionPrefix>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace ExtremelySimpleLogger {
|
namespace ExtremelySimpleLogger {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implementation of a <see cref="TextWriter"/> that writes to a <see cref="Logger"/>.
|
/// Implementation of a <see cref="TextWriter"/> that writes to a <see cref="Logger"/>.
|
||||||
|
/// The log writer constructs a message based on calls to <see cref="Write(string)"/> and its variations and then submits the message to the underlying <see cref="Logger"/> when <see cref="WriteLine()"/> or <see cref="Flush"/> is called. <see cref="WriteLine(string)"/> and its variations submit the message immediately.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LogWriter : TextWriter {
|
public class LogWriter : TextWriter {
|
||||||
|
|
||||||
|
@ -59,17 +59,237 @@ namespace ExtremelySimpleLogger {
|
||||||
this.line.Append(value);
|
this.line.Append(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(char[] buffer) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(bool value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(int value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(uint value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(long value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(ulong value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(float value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(double value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(decimal value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(object value) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(string format, object arg0) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.AppendFormat(this.FormatProvider, format, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(string format, object arg0, object arg1) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.AppendFormat(this.FormatProvider, format, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(string format, object arg0, object arg1, object arg2) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.AppendFormat(this.FormatProvider, format, arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(string format, params object[] arg) {
|
||||||
|
lock (this.logger)
|
||||||
|
this.line.AppendFormat(this.FormatProvider, format, arg);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteLine(string value) {
|
public override void WriteLine(string value) {
|
||||||
this.Write(value);
|
this.Write(value);
|
||||||
this.WriteLine();
|
this.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(char value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(char[] buffer) {
|
||||||
|
this.Write(buffer);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(char[] buffer, int index, int count) {
|
||||||
|
this.Write(buffer, index, count);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(bool value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(int value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(uint value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(long value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(ulong value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(float value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(double value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(decimal value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(object value) {
|
||||||
|
this.Write(value);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(string format, object arg0) {
|
||||||
|
this.Write(format, arg0);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(string format, object arg0, object arg1) {
|
||||||
|
this.Write(format, arg0, arg1);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(string format, object arg0, object arg1, object arg2) {
|
||||||
|
this.Write(format, arg0, arg1, arg2);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void WriteLine(string format, params object[] arg) {
|
||||||
|
this.Write(format, arg);
|
||||||
|
this.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteLine() {
|
public override void WriteLine() {
|
||||||
this.Flush();
|
this.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteAsync(char value) {
|
||||||
|
return Task.Run(() => this.Write(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteAsync(string value) {
|
||||||
|
return Task.Run(() => this.Write(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteAsync(char[] buffer, int index, int count) {
|
||||||
|
return Task.Run(() => this.Write(buffer, index, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteLineAsync(char value) {
|
||||||
|
return Task.Run(() => this.WriteLine(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteLineAsync(string value) {
|
||||||
|
return Task.Run(() => this.WriteLine(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteLineAsync(char[] buffer, int index, int count) {
|
||||||
|
return Task.Run(() => this.WriteLine(buffer, index, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteLineAsync() {
|
||||||
|
return Task.Run(this.WriteLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task FlushAsync() {
|
||||||
|
return Task.Run(this.Flush);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Flush() {
|
public override void Flush() {
|
||||||
lock (this.logger) {
|
lock (this.logger) {
|
||||||
|
|
43
ExtremelySimpleLogger/WriterSink.cs
Normal file
43
ExtremelySimpleLogger/WriterSink.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace ExtremelySimpleLogger {
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="Sink"/> that writes log output to an underlying <see cref="TextWriter"/>.
|
||||||
|
/// Note that <see cref="ConsoleSink"/> is a variation of this sink that additionally includes console colors.
|
||||||
|
/// </summary>
|
||||||
|
public class WriterSink : Sink {
|
||||||
|
|
||||||
|
private readonly TextWriter writer;
|
||||||
|
private readonly bool autoClose;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new writer sink with the given settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer to write to.</param>
|
||||||
|
/// <param name="autoClose">Whether the underlying <paramref name="writer"/> should be closed automatically when this sink is disposed in <see cref="Dispose"/>.</param>
|
||||||
|
public WriterSink(TextWriter writer, bool autoClose = false) {
|
||||||
|
this.writer = writer;
|
||||||
|
this.autoClose = autoClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs the given message, which has already been formatted using <see cref="Sink.Formatter"/> or <see cref="Logger.DefaultFormatter"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger that the message was passed to</param>
|
||||||
|
/// <param name="level">The importance level of this message</param>
|
||||||
|
/// <param name="s">The message to log</param>
|
||||||
|
protected override void Log(Logger logger, LogLevel level, string s) {
|
||||||
|
lock (this.writer)
|
||||||
|
this.writer.WriteLine(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Dispose() {
|
||||||
|
if (this.autoClose) {
|
||||||
|
lock (this.writer)
|
||||||
|
this.writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ namespace Sample {
|
||||||
var sinks = new List<Sink> {
|
var sinks = new List<Sink> {
|
||||||
new FileSink("Log.txt", true),
|
new FileSink("Log.txt", true),
|
||||||
// We only want to log messages with a higher importance in the console
|
// We only want to log messages with a higher importance in the console
|
||||||
new ConsoleSink {MinimumLevel = LogLevel.Info},
|
new ConsoleSink() {MinimumLevel = LogLevel.Info},
|
||||||
// we allow a total of 5 files in our directory sink before old ones start being deleted
|
// we allow a total of 5 files in our directory sink before old ones start being deleted
|
||||||
new DirectorySink("AllLogs", 5)
|
new DirectorySink("AllLogs", 5)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue