Commit Description:
Merge in m5-tiles-and-trees! ?
Commit Description:
Merge in m5-tiles-and-trees! ?
References:
Show/Diff file:
Action:
isometric-park-fna/Logging.cs
337 lines | 12.5 KiB | text/x-csharp | CSharpLexer
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
using JM.LinqFaster;
/* Tiny log library inspired by Python's logging and Glögi.
*/
namespace isometricparkfna
{
public enum LogLevel
{
Critical,
Error,
Warning,
Success,
Info,
Debug,
Trace,
Spy
}
public struct LogEntry
{
public DateTime timestamp;
public string message;
public LogLevel level;
public ITuple data;
}
public class Logging
{
#if DEBUG
public static LogLevel minimumConsoleLevel = LogLevel.Debug;
#else
public static LogLevel minimumConsoleLevel = LogLevel.Success;
#endif
public static List<LogEntry> entries = new List<LogEntry>();
public static string logFileName = string.Format("log_{0:yyyyMMdd_HHmm}.txt", DateTime.Now);
public static StreamWriter logFile = File.CreateText(logFileName);
private static Dictionary<LogLevel, (ConsoleColor, ConsoleColor)> mappings = new Dictionary<LogLevel, (ConsoleColor, ConsoleColor)>
{
{LogLevel.Critical, (ConsoleColor.White, ConsoleColor.Red)},
{LogLevel.Error, (ConsoleColor.Black, ConsoleColor.Red)},
{LogLevel.Warning, (ConsoleColor.Black, ConsoleColor.Yellow)},
{LogLevel.Success, (ConsoleColor.White, ConsoleColor.Green)},
{LogLevel.Info, (ConsoleColor.White, ConsoleColor.Blue)},
{LogLevel.Debug, (ConsoleColor.Blue, ConsoleColor.Black)},
{LogLevel.Trace, (ConsoleColor.Magenta, ConsoleColor.Black)},
{LogLevel.Spy, (ConsoleColor.Black, ConsoleColor.White)},
};
private static void Log_(LogLevel level, string message,
int lineNumber, string caller, string path, ConsoleColor message_foreground = ConsoleColor.White)
{
var timestamp = DateTime.Now;
if ((level <= minimumConsoleLevel)
|| level == LogLevel.Spy)
{
var start_foreground = Console.ForegroundColor;
var start_background = Console.BackgroundColor;
var (new_foreground, new_background) = Logging.mappings[level];
Console.ForegroundColor = new_foreground;
Console.BackgroundColor = new_background;
//29/Apr/2021 22:43:30
Console.Out.Write(string.Format("[{0}] {1}", timestamp.ToString("s"), level.ToString()));
Console.BackgroundColor = start_background;
Console.ForegroundColor = message_foreground;
Console.Out.Write(" " + message);
Console.ForegroundColor = start_foreground;
Console.Out.WriteLine(string.Format(" [{1}:{2}]", message, path, lineNumber));
}
logFile.WriteLine(string.Format("[{0}] {1} {2} [{3}:{4}]", timestamp.ToString("s"), level.ToString(), message, path, lineNumber));
Logging.entries.Add(new LogEntry { timestamp = timestamp,
level = level,
message = message
});
}
private static void Log_<T>(LogLevel level, string message, T data,
int lineNumber, string caller, string path)
where T : ITuple
{
// Logging.entries.Add(data);
// var d = data.GetType().GetProperties().ToDictionary(Info => Info.Name, Info => Info.GetValue(data));
// var data_strings = data.GetType().GetProperties().Select(Info => Info.Name + "=" + Info.GetValue(data).ToString());
// var data_string = string.Join(", ", data_strings);
// var str = String.Format("{0} {1}", message, data_string);
Logging.Log_(level, message, lineNumber, caller, path);
}
private static void Log_(LogLevel level, string message,
int lineNumber, string caller, string path, params object[] objects)
{
String.Format(message, objects);
Logging.Log_(level, message, lineNumber, caller, path);
}
public static void Log(LogLevel level, string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(level, message, lineNumber, caller, path);
}
/*
public static void Log<T>(LogLevel level, string message, T data,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
//Constrain to Tuples and tuple-likes:
where T : ITuple, IStructuralEquatable, IStructuralComparable
{
Logging.Log_(level, message, data, lineNumber, caller, path);
}*/
public static void Log<T>(LogLevel level, string message, T data,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
//Constrain to Tuples and tuple-likes:
where T : class
{
var properties = new List<string>();
foreach (var property in typeof(T).GetProperties())
{
properties.Add(property.ToString() + "=" + property.GetValue(data));
}
var message_data = message + " {" + String.Join(", ", properties) + "}";
Logging.Log_(level, message_data, lineNumber, caller, path);
}
public static void Log(LogLevel level, string message,
object[] format,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(level, message, lineNumber, caller, path, format);
}
public static void Critical(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Critical, message, lineNumber, caller, path);
}
public static void Error(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Error, message, lineNumber, caller, path);
}
public static void Warning(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Warning, message, lineNumber, caller, path);
}
public static void Success(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Success, message, lineNumber, caller, path);
}
public static void Info(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Info, message, lineNumber, caller, path);
}
public static void Debug(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Debug, message, lineNumber, caller, path);
}
public static void Trace(string message,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "")
{
Logging.Log_(LogLevel.Trace, message, lineNumber, caller, path);
}
public static void Spy(object value,
string name,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = ""
)
{
string message = string.Format("{0} ({1}) = {2}",
value.GetType().ToString(), name, value.ToString());
Logging.Log_(LogLevel.Spy, message, lineNumber, caller, path);
}
public static void Spy<T>(T value,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = ""
) where T : class
{
// var properties = typeof(T).GetProperties();
// string message = string.Format("{0} = {1}",
// value.ToString(), .ToString() );
// var message = String.Join(", ", (object[])properties);
//
var properties = new List<string>();
foreach (var property in typeof(T).GetProperties())
{
properties.Add(property.ToString() + "=" + property.GetValue(value));
}
var message = "{" + String.Join(", ", properties) + "}";
Logging.Log_(LogLevel.Spy, message, lineNumber, caller, path);
}
public static void Spy<T>(T? value,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = ""
// , T _ = default
) where T : struct
{
if (value == null)
{
Logging.Log_(LogLevel.Spy, "Value is null!", lineNumber, caller, path, ConsoleColor.Red);
return;
}
var properties = new List<string>();
foreach (var field in typeof(T).GetFields())
{
try {
properties.Add(field.ToString() + "="
+ field.GetValue(value).ToString());
}
catch (NullReferenceException)
{
properties.Add(field.ToString() + "= <null>" );
}
}
var message = "{" + String.Join(", ", properties) + "}";
Logging.Log_(LogLevel.Spy, message, lineNumber, caller, path);
}
public static void Spy<T>(T value,
[CallerLineNumber] int lineNumber = 0,
[CallerMemberName] string caller = null,
[CallerFilePath] string path = "",
T _ = default) where T : struct
{
//C/o Jannes on StackOverflow for the extra parameter with a default trick
//https://stackoverflow.com/questions/2974519/generic-constraints-where-t-struct-and-where-t-class#comment111131939_36775837
var properties = new List<string>();
foreach (var field in typeof(T).GetFields())
{
try {
properties.Add(field.ToString() + "="
+ field.GetValue(value).ToString());
}
catch (NullReferenceException)
{
properties.Add(field.ToString() + "= <null>" );
}
}
var message = "{" + String.Join(", ", properties) + "}";
Logging.Log_(LogLevel.Spy, message, lineNumber, caller, path);
}
}
}