using GlitchyEngine.Core;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static GlitchyEngine.Log;
namespace GlitchyEngine;
///
/// Provides methods to log messages to the Engine Console.
///
public class Log
{
///
/// The severity of the log message.
///
[EngineClass("GlitchLog.LogLevel")]
internal enum LogLevel : byte
{
Trace = 0,
Debug,
Info,
Warning,
Error,
Critical,
Off
}
///
/// Logs a trace message.
///
/// The message to log.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Trace(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Trace, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Logs an info message.
///
/// The message to log.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Info(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Info, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Logs a warning message.
///
/// The message to log.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Warning(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Warning, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Logs an error message.
///
/// The message to log.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Error(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Error, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Logs a critical error message.
///
/// The message to log.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Critical(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Critical, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Serializes the given object (using ) and logs it as a trace message.
///
/// The object to serialize.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Trace(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Trace, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Serializes the given object (using ) and logs it as an info message.
///
/// The object to serialize.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Info(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Info, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Serializes the given object (using ) and logs it as a warning message.
///
/// The object to serialize.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Warning(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Warning, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Serializes the given object (using ) and logs it as an error message.
///
/// The object to serialize.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Error(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Error, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0);
}
///
/// Serializes the given object (using ) and logs it as a critical error message.
///
/// The object to serialize.
/// File path of the caller.
/// Line number of the caller.
/// Name of the calling member.
public static void Critical(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "")
{
ScriptGlue.Log_LogMessage(LogLevel.Critical, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0);
}
[DebuggerDisplay("{ToString(),raw}")]
[StructLayout(LayoutKind.Sequential, Pack = 0)]
[EngineClass("GlitchyEngine.Scripting.ScriptGlue.GlueStackFrameInfo")]
internal struct StackFrameInfo
{
public Native.StringView FileName;
public Native.StringView MethodSignature;
public int LineNumber;
public int ColumnNumber;
}
static string GetFullSignature(MethodBase method)
{
var typeName = method.DeclaringType?.FullName ?? "";
var parameters = string.Join(", ",
method.GetParameters().Select(p => $"{p.ParameterType.Name}"));
return $"{typeName}.{method.Name}({parameters})";
}
///
/// Logs the give exception.
///
/// The exception to log.
public static void Exception(Exception exception)
{
StackTrace st = new StackTrace(exception, true);
StackFrame[] frames = st.GetFrames();
StackFrameInfo[] stackFrameInfos = new StackFrameInfo[frames.Length];
// We only need StackFrameInfo for exception logging, so it's okay to manually handle the marshalling here.
foreach (StackFrame stackFrame in frames)
{
MethodBase? method = stackFrame.GetMethod();
string methodSignature = method != null ? GetFullSignature(method) : "";
stackFrameInfos[frames.IndexOf(stackFrame)] = new StackFrameInfo
{
FileName = Native.StringView.FromManagedString(stackFrame.GetFileName()),
MethodSignature = Native.StringView.FromManagedString(methodSignature),
LineNumber = stackFrame.GetFileLineNumber(),
ColumnNumber = stackFrame.GetFileColumnNumber()
};
}
unsafe
{
fixed (StackFrameInfo* stackFrames = stackFrameInfos)
{
ScriptGlue.Log_LogException(ScriptGlue.CurrentEntityId, exception.GetType().FullName, exception.Message, stackFrames, stackFrameInfos.Length);
}
}
foreach (StackFrameInfo stackFrameInfo in stackFrameInfos)
{
Native.StringView.FreeNativeMemory(stackFrameInfo.FileName);
}
}
}