Better exception logging

This commit is contained in:
Marc Hernandez 2025-11-07 15:23:28 -08:00
parent cb2b79be86
commit baa65531a2
5 changed files with 171 additions and 52 deletions

View File

@ -11,15 +11,14 @@
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>14.0</LangVersion> <LangVersion>14.0</LangVersion>
<Copyright>Copyright 2003..2025 Marc Hernandez</Copyright>
<Description>A base set of </Description>
<!-- <!--
I Want to turn this on, but cant yet. Implementing nullability 1 file at a gime I Want to turn this on, but cant yet. Implementing nullability 1 file at a gime
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
--> -->
</PropertyGroup>
<PropertyGroup>
<NoWarn>$(NoWarn);SYSLIB0050;CS8981; CS8632</NoWarn> <NoWarn>$(NoWarn);SYSLIB0050;CS8981; CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
@ -30,16 +29,13 @@
<PackageReference Include="Microsoft.Diagnostics.NETCore.Client" Version="0.2.621003" /> <PackageReference Include="Microsoft.Diagnostics.NETCore.Client" Version="0.2.621003" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.24" /> <PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.24" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
<Folder Include="reflect\" /> <Folder Include="reflect\" />
<Folder Include="fsm\" /> <Folder Include="fsm\" />
</ItemGroup>
<ItemGroup>
<None Remove="fsm\" /> <None Remove="fsm\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -72,6 +72,9 @@ public struct SourceLoc
public string Log => ToLogString(); public string Log => ToLogString();
public string File => _dbgFile;
public string Method => _dbgName;
static public SourceLoc Record( static public SourceLoc Record(
string reason = "", string reason = "",
[CallerMemberName] string dbgName = "", [CallerMemberName] string dbgName = "",
@ -199,12 +202,12 @@ static public class log
public string Exp; public string Exp;
public string Cat; public string Cat;
public object? Obj; public SourceLoc? Loc;
static ImmutableDictionary<int, string> s_shortname = ImmutableDictionary<int, string>.Empty; static ImmutableDictionary<int, string> s_shortname = ImmutableDictionary<int, string>.Empty;
public LogEvent( LogType logType, string msg, string dbgPath, int dbgLine, string dbgMethod, string cat, string exp, object? obj ) public LogEvent( LogType logType, string msg, string dbgPath, int dbgLine, string dbgMethod, string cat, string exp, SourceLoc? loc )
{ {
//Cache the automatic category names //Cache the automatic category names
@ -241,13 +244,13 @@ static public class log
Member = dbgMethod; Member = dbgMethod;
Cat = cat; Cat = cat;
Exp = exp; Exp = exp;
Obj = obj; Loc = loc;
} }
} }
static LogEvent CreateLogEvent( LogType logType, string msg, string cat, object? obj, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", string exp = "" ) static LogEvent CreateLogEvent( LogType logType, string msg, string cat, SourceLoc? loc, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", string exp = "" )
{ {
var logEvent = new LogEvent( logType, msg, dbgPath, dbgLine, dbgMethod, cat, exp, obj ); var logEvent = new LogEvent( logType, msg, dbgPath, dbgLine, dbgMethod, cat, exp, loc );
return logEvent; return logEvent;
} }
@ -286,7 +289,7 @@ static public class log
=> new SourceLoc( "", dbgName, dbgPath, dbgLine ); => new SourceLoc( "", dbgName, dbgPath, dbgLine );
static public string whatFile( string path ) static public string whatFile( string path, bool incExtension = false )
{ {
var file = ""; var file = "";
@ -304,11 +307,20 @@ static public class log
pathPieces = path.Split( '/' ); pathPieces = path.Split( '/' );
} }
var lastDir = pathPieces[pathPieces.Length - 1]; var lastPathPiece = pathPieces[pathPieces.Length - 1];
ImmutableInterlocked.AddOrUpdate( ref s_files, pathHash, lastDir, ( key, value ) => { return lastDir; } ); ImmutableInterlocked.AddOrUpdate( ref s_files, pathHash, lastPathPiece, ( key, value ) => { return lastPathPiece; } );
file = lastDir; if( !incExtension )
{
var periodIndex = lastPathPiece.IndexOf( '.' );
if( periodIndex > 0 )
{
lastPathPiece = lastPathPiece.Substring( 0, periodIndex );
}
}
file = lastPathPiece;
} }
return file; return file;
@ -341,7 +353,7 @@ static public class log
} }
/* /*
static public void info( string msg, string cat = "", object? obj = null, static public void info( string msg, string cat = "",SourceLoc? loc = null,
[CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
*/ */
@ -383,6 +395,7 @@ static public class log
return v; return v;
} }
[StackTraceHidden]
static public void call( Action func, [CallerMemberName] string dbgName = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerArgumentExpression( "func" )] string dbgExp = "" ) static public void call( Action func, [CallerMemberName] string dbgName = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerArgumentExpression( "func" )] string dbgExp = "" )
{ {
log.info( $"{dbgExp}", "", null, dbgPath, dbgLine, dbgName, dbgExp ); log.info( $"{dbgExp}", "", null, dbgPath, dbgLine, dbgName, dbgExp );
@ -390,57 +403,84 @@ static public class log
log.info( $"| Done", "", null, dbgPath, dbgLine, dbgName, dbgExp ); log.info( $"| Done", "", null, dbgPath, dbgLine, dbgName, dbgExp );
} }
static public void fatal( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Fatal, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj );
}
[StackTraceHidden] [StackTraceHidden]
static public void error( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) static public void info( string msg, string cat = "",SourceLoc? loc = null,
{
logBase( $"{dbgMethod}: {msg}", LogType.Error, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj );
}
[StackTraceHidden]
static public void warn( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Warn, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj );
}
static public void high( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.High, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj );
}
static public void info( string msg, string cat = "", object? obj = null,
[CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{ {
logBase( msg, LogType.Info, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj ); logBase( msg, LogType.Info, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
} }
static public void debug( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) [StackTraceHidden]
static public void debug( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{ {
logBase( msg, LogType.Debug, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj ); logBase( msg, LogType.Debug, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
} }
static public void trace( string msg, string cat = "", object? obj = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) [StackTraceHidden]
static public void trace( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{ {
logBase( msg, LogType.Trace, dbgPath, dbgLine, dbgMethod, cat, dbgExp, obj ); logBase( msg, LogType.Trace, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void warn( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Warn, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void high( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.High, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void error( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( $"{dbgMethod}: {msg}", LogType.Error, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
} }
[StackTraceHidden]
// VERY SPECIALIZED ONLY USE IF YOU KNOW WHAT YOU ARE DOING
static public void row_internal( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Raw, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
[StackTraceHidden]
static public void exception( Exception ex, string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( $"*******************************************************************************",
LogType.Raw, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
logBase( $"{dbgMethod}: {msg} | Caught At:", LogType.Error, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
logBase( $"{dbgPath}({dbgLine}): {dbgMethod}: ---------------",
LogType.Raw, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
LogStackTrace( ex );
}
[StackTraceHidden]
static public void fatal( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" )
{
logBase( msg, LogType.Fatal, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc );
}
//new LogEvent( LogType.Raw, $"", "", 0, "", "lib.time", "", null )
#endregion #endregion
#region Helpers #region Helpers
static public void logProps( object obj, string header, LogType type = LogType.Debug, string cat = "", string prefix = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "obj" )] string dbgExpObj = "" ) static public void logProps( object obj, string header, LogType type = LogType.Debug, string cat = "", string prefix = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "obj" )] string dbgExpObj = "", SourceLoc? loc = null )
{ {
var list = refl.GetAllProperties( obj.GetType() ); var list = refl.GetAllProperties( obj.GetType() );
lock( s_lock ) lock( s_lock )
{ {
var evt = new LogEvent( type, header, dbgPath, dbgLine, dbgMethod, cat, dbgExpObj, obj ); var evt = new LogEvent( type, header, dbgPath, dbgLine, dbgMethod, cat, dbgExpObj, loc );
{ {
// Use Add instead of Enqueue // Use Add instead of Enqueue
s_events.Add( evt ); s_events.Add( evt );
@ -455,7 +495,7 @@ static public class log
} }
catch( Exception ex ) catch( Exception ex )
{ {
logBase( $"Exception processing {pi.Name} {ex.Message}", LogType.Error, dbgPath, dbgLine, dbgMethod, cat, dbgExpObj, obj ); logBase( $"Exception processing {pi.Name} {ex.Message}", LogType.Error, dbgPath, dbgLine, dbgMethod, cat, dbgExpObj, loc );
} }
} }
@ -475,6 +515,26 @@ static public class log
log.warn( $"Got {notExpectedValue} instead of {value}{falseString}" ); log.warn( $"Got {notExpectedValue} instead of {value}{falseString}" );
} }
} }
static void LogStackTrace( Exception ex, string prefixMsg = "" )
{
var stackTrace = new StackTrace( ex, true );
var formattedTrace = "Stack Trace:\n";
if( ex.InnerException != null )
{
var prefix = $"{prefixMsg}Inner->";
LogStackTrace( ex.InnerException, prefix );
}
log.error( $"{prefixMsg} Exception: {ex.Message}" );
foreach( var fr in stackTrace.GetFrames() )
{
logBase( $"{fr.Log}", LogType.Raw );
}
}
#endregion #endregion
@ -494,14 +554,14 @@ static public class log
} }
static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", object? obj = null ) static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null )
{ {
LogEvent evt = new LogEvent( type, msg, dbgPath, dbgLine, dbgMethod, cat, exp, obj ); LogEvent evt = new LogEvent( type, msg, dbgPath, dbgLine, dbgMethod, cat, exp, loc );
return evt; return evt;
} }
[StackTraceHidden] [StackTraceHidden]
static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", object? obj = null ) static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null )
{ {
var evt = logCreateEvent( msg, type, dbgPath, dbgLine, dbgMethod, cat, exp ); var evt = logCreateEvent( msg, type, dbgPath, dbgLine, dbgMethod, cat, exp );

16
task/Task.cs Normal file
View File

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
namespace lib;
static public class Task
{
}

28
util/Debug.cs Normal file
View File

@ -0,0 +1,28 @@
using System.Diagnostics;
static public class DebugEx
{
extension(StackFrame sf)
{
public string Method => sf.GetMethod().Name;
public string File => sf.GetFileName();
public int Line => sf.GetFileLineNumber();
public int Column => sf.GetFileColumnNumber();
public string Log => $"{sf.File}({sf.Line}, {sf.Column}): {sf.Method}";
}
}

19
util/RandomEx.cs Normal file
View File

@ -0,0 +1,19 @@
public static class RandomEx
{
/*
// NextBytes work fine
public static void FillBytes( this Random rnd, ref byte[] buffer )
{
rnd.NextBytes()
for( int i = 0; i < buffer.Length; ++i )
{
}
*/
}