From 573e50b867d3a1488e43d73cfa0b698febe698d8 Mon Sep 17 00:00:00 2001 From: Harald Wolff-Thobaben Date: Wed, 18 Nov 2020 00:22:24 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 41 +++++++++++++++++ ConsoleLogger.cs | 17 +++++++ FileLogger.cs | 73 ++++++++++++++++++++++++++++++ ILoggingBackend.cs | 12 +++++ LogLevel.cs | 15 +++++++ Logger.cs | 109 ++++++++++++++++++++++++++++++++++++++++++++ Logging.cs | 19 ++++++++ LoggingBackend.cs | 28 ++++++++++++ LoggingWriter.cs | 47 +++++++++++++++++++ MemoryLogger.cs | 110 +++++++++++++++++++++++++++++++++++++++++++++ ln.logging.csproj | 10 +++++ 11 files changed, 481 insertions(+) create mode 100644 .gitignore create mode 100644 ConsoleLogger.cs create mode 100644 FileLogger.cs create mode 100644 ILoggingBackend.cs create mode 100644 LogLevel.cs create mode 100644 Logger.cs create mode 100644 Logging.cs create mode 100644 LoggingBackend.cs create mode 100644 LoggingWriter.cs create mode 100644 MemoryLogger.cs create mode 100644 ln.logging.csproj 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 + + + + + +