commit 573e50b867d3a1488e43d73cfa0b698febe698d8 Author: Harald Wolff-Thobaben Date: Wed Nov 18 00:22:24 2020 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cd51a9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Autosave files +*~ + +# build +[Oo]bj/ +[Bb]in/ +packages/ +TestResults/ + +# globs +Makefile.in +*.DS_Store +*.sln.cache +*.suo +*.cache +*.pidb +*.userprefs +*.usertasks +config.log +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.user +*.tar.gz +tarballs/ +test-results/ +Thumbs.db +.vs/ + +# Mac bundle stuff +*.dmg +*.app + +# resharper +*_Resharper.* +*.Resharper + +# dotCover +*.dotCover diff --git a/ConsoleLogger.cs b/ConsoleLogger.cs new file mode 100644 index 0000000..b27eb4f --- /dev/null +++ b/ConsoleLogger.cs @@ -0,0 +1,17 @@ +using System; +namespace ln.logging +{ + public class ConsoleLogger : LoggingBackend + { + public ConsoleLogger() + { + } + + protected override void MessageReceived(LogLevel logLevel, string[] lines) + { + foreach (string line in lines){ + Logger.SysOut.WriteLine(line); + } + } + } +} diff --git a/FileLogger.cs b/FileLogger.cs new file mode 100644 index 0000000..dd92128 --- /dev/null +++ b/FileLogger.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; + +namespace ln.logging +{ + public class FileLogger : LoggingBackend, IDisposable + { + FileStream fileStream; + TextWriter writer; + + public FileLogger(string filename) + { + openLogFile(filename); + } + + private void openLogFile(string filename) + { + if (File.Exists(filename)) + { + String oldfn = String.Format("{0}.old", filename); + if (File.Exists(oldfn)) + File.Delete(oldfn); + File.Move(filename, oldfn); + } + fileStream = new FileStream(filename, FileMode.Create); + writer = new StreamWriter(fileStream); + } + + public void Close() + { + if (writer != null) + { + writer.Close(); + fileStream.Close(); + } + } + + public void Dispose() + { + if (writer != null) + { + writer.Close(); + writer.Dispose(); + writer = null; + } + if (fileStream != null) + { + fileStream.Close(); + fileStream.Dispose(); + fileStream = null; + } + } + + protected override void MessageReceived(LogLevel logLevel, string[] lines) + { + if (writer == null) + { + throw new ObjectDisposedException("FileLogger has already been disposed"); + } + + lock (writer) + { + foreach (String line in lines) + { + writer.WriteLine(line); + writer.Flush(); + } + } + } + + + } +} diff --git a/ILoggingBackend.cs b/ILoggingBackend.cs new file mode 100644 index 0000000..9be2ae3 --- /dev/null +++ b/ILoggingBackend.cs @@ -0,0 +1,12 @@ +using System; +using System.Security.Cryptography.X509Certificates; +namespace ln.logging +{ + public interface ILoggingBackend + { + LogLevel MinLogLevel { get; set; } + LogLevel MaxLogLevel { get; set; } + + void Message(LogLevel logLevel,String[] lines); + } +} diff --git a/LogLevel.cs b/LogLevel.cs new file mode 100644 index 0000000..29a0ae9 --- /dev/null +++ b/LogLevel.cs @@ -0,0 +1,15 @@ +using System; +namespace ln.logging +{ + public enum LogLevel + { + FATAL = 0, + ERROR = 5, + WARNING = 10, + INFO = 15, + DEBUG = 30, + DEBUGDETAIL = 40, + DEBUGFULL = 80, + MAX = 128 + } +} diff --git a/Logger.cs b/Logger.cs new file mode 100644 index 0000000..19664ab --- /dev/null +++ b/Logger.cs @@ -0,0 +1,109 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Reflection; +namespace ln.logging +{ + public class Logger + { + public static ConsoleLogger ConsoleLogger { get; } = new ConsoleLogger(); + public static Logger Default { get; set; } = new Logger(ConsoleLogger); + + public static TextWriter SysOut = Console.Out; + public static TextWriter SysError = Console.Error; + + + + public static void CaptureConsole(Logger logger) + { + LoggingWriter outWriter = new LoggingWriter(logger); + Console.SetOut(outWriter); + LoggingWriter errorWriter = new LoggingWriter(logger, LogLevel.ERROR); + Console.SetError(errorWriter); + } + + + public HashSet Backends { get; } = new HashSet(); + + public Logger(ILoggingBackend backend) + { + Backends.Add(backend); + } + + public void Log(LogLevel level,string message, params object[] args) + { + Log(level,String.Format(message, args)); + } + + public void Log(string message,params object[] args){ + Log(LogLevel.INFO,String.Format(message, args)); + } + + public void Log(string message) + { + Log(LogLevel.INFO, message); + } + public void Log(LogLevel level,string message) + { + string[] lines = message.Split('\n'); + + lines[0] = String.Format("{0} [{1}] [ {3,-10} ] {2}", + DateTime.Now.ToLocalTime(), + Process.GetCurrentProcess().Id, + lines[0], + level.ToString() + ); + + for (int n = 1; n < lines.Length; n++){ + lines[n] = " " + lines[n]; + } + + Send(level,lines); + } + + private void Send(LogLevel logLevel,String[] lines) + { + foreach (ILoggingBackend backend in Backends) + backend.Message(logLevel,lines); + } + + + + + + public void Log(Exception exception) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendFormat("Exception {0} [{1}]\n", exception.GetType().Name,exception.Message); + + StackTrace stackTrace = new StackTrace(exception, true); + + foreach (StackFrame stackFrame in stackTrace.GetFrames()) + { + MethodBase methodBase = stackFrame.GetMethod(); + MethodBody methodBody = methodBase.GetMethodBody(); + + stringBuilder.AppendFormat(" {0} in {1}:{2}\n", + methodBase.Name, + stackFrame.GetFileName(), + stackFrame.GetFileLineNumber() + ); + //if (methodBody != null) + //{ + // foreach (LocalVariableInfo lvi in methodBody.LocalVariables) + // { + // stringBuilder.AppendFormat(" {0}\n", lvi); + // } + //} + } + + Log(LogLevel.ERROR, stringBuilder.ToString()); + } + + + + + } +} diff --git a/Logging.cs b/Logging.cs new file mode 100644 index 0000000..10a67b5 --- /dev/null +++ b/Logging.cs @@ -0,0 +1,19 @@ +using System; +namespace ln.logging +{ + public static class Logging + { + public static void Log(string message, params object[] args) + { + Log(LogLevel.INFO, message, args); + } + public static void Log(LogLevel level,string message, params object[] args) + { + Logger.Default.Log(level,message, args); + } + + public static void Log(Exception e){ + Log(LogLevel.ERROR,"Exception: {0} / {1}\n{2}", e.GetType().Name, e.Message, e.StackTrace.ToString()); + } + } +} diff --git a/LoggingBackend.cs b/LoggingBackend.cs new file mode 100644 index 0000000..c79db45 --- /dev/null +++ b/LoggingBackend.cs @@ -0,0 +1,28 @@ +using System; +namespace ln.logging +{ + public abstract class LoggingBackend : ILoggingBackend + { + public LogLevel MinLogLevel { get; set; } = LogLevel.FATAL; + public LogLevel MaxLogLevel { get; set; } = LogLevel.MAX; + + public LoggingBackend() + { + } + + public void Message(LogLevel logLevel, string[] lines) + { + if ((logLevel >= MinLogLevel) && (logLevel <= MaxLogLevel)) + MessageReceived(logLevel, lines); + } + + protected abstract void MessageReceived(LogLevel logLevel, String[] lines); + + + public void Log(LogLevel logLevel,String message,params object[] p) + { + string[] lines = String.Format(message, p).Split('\n', '\r'); + Message(logLevel, lines); + } + } +} diff --git a/LoggingWriter.cs b/LoggingWriter.cs new file mode 100644 index 0000000..451b20b --- /dev/null +++ b/LoggingWriter.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace ln.logging +{ + class LoggingWriter : TextWriter + { + Logger logger; + LogLevel level; + + List linebuffer = new List(); + + public LoggingWriter(Logger logger, LogLevel level = LogLevel.INFO) + { + this.logger = logger; + this.level = level; + } + + public override void Write(char value) + { + if (value == '\n') + { + logger.Log(level, new String(linebuffer.ToArray())); + linebuffer.Clear(); + } + else + { + linebuffer.Add(value); + } + } + + public override void WriteLine(string format, params object[] args) + { + logger.Log(level, format, args); + } + + public override Encoding Encoding + { + get + { + return Encoding.UTF8; + } + } + } +} diff --git a/MemoryLogger.cs b/MemoryLogger.cs new file mode 100644 index 0000000..ede3621 --- /dev/null +++ b/MemoryLogger.cs @@ -0,0 +1,110 @@ +// /** +// * File: MemoryLogger.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using ln.logging; +using System.Linq; +namespace ln.logging +{ + public class MemoryLogger : ILoggingBackend + { + private LogEntry[] Entries = new LogEntry[256]; + private int CurrentLogPointer = 255; + + public MemoryLogger() + { + } + + public MemoryLogger(int bufferLength) + { + Entries = new LogEntry[bufferLength]; + CurrentLogPointer = Entries.Length - 1; + } + + public LogLevel MinLogLevel { get; set; } = LogLevel.FATAL; + public LogLevel MaxLogLevel { get; set; } = LogLevel.INFO; + + public void Message(LogLevel logLevel, string[] lines) + { + lock (this) + { + Entries[CurrentLogPointer].LogLevel = logLevel; + Entries[CurrentLogPointer].Lines = String.Join("\n", lines); + CurrentLogPointer = NextLogPointer; + } + } + + public LogEntry[] GetLogEntries() + { + lock (this) + { + LogEntry[] prepare = new LogEntry[Entries.Length]; + if (CurrentLogPointer == (Entries.Length - 1)) + { + Array.Copy(Entries, prepare, Entries.Length); + } + else + { + Array.Copy(Entries, PreviousLogPointer, prepare, 0, Entries.Length - PreviousLogPointer); + Array.Copy(Entries, 0, prepare, Entries.Length - PreviousLogPointer, PreviousLogPointer); + } + + return prepare.Where((x) => x.Lines != null).ToArray(); + } + } + public LogEntry[] GetLogEntries(LogLevel maxLogLevel) + { + lock (this) + { + LogEntry[] prepare = new LogEntry[Entries.Length]; + if (CurrentLogPointer == (Entries.Length - 1)) + { + Array.Copy(Entries, prepare, Entries.Length); + } + else + { + Array.Copy(Entries, PreviousLogPointer, prepare, 0, Entries.Length - PreviousLogPointer); + Array.Copy(Entries, 0, prepare, Entries.Length - PreviousLogPointer, PreviousLogPointer); + } + + return prepare.Where((x) => (x.Lines != null) && (maxLogLevel >= x.LogLevel)).ToArray(); + } + } + + private int NextLogPointer + { + get + { + int current = CurrentLogPointer; + current--; + if (current < 0) + current = Entries.Length - 1; + return current; + } + } + private int PreviousLogPointer + { + get + { + int current = CurrentLogPointer; + current++; + if (current >= Entries.Length) + current = 0; + return current; + } + } + + + public struct LogEntry + { + public LogLevel LogLevel; + public string Lines; + } + } +} diff --git a/ln.logging.csproj b/ln.logging.csproj new file mode 100644 index 0000000..5f98043 --- /dev/null +++ b/ln.logging.csproj @@ -0,0 +1,10 @@ + + + + netcoreapp2.1 + + + + + +