I agree with David, and I understand where you are coming from as dependencies on 3rd party are always risky "can't afford to lose it, can't afford to have it"
(I like to share code; I wrote this using Delphi 12, your implementation may differ)
There is nothing wrong with madExcept, but it's not the only one.
Have a look at another Paid tool EurekaLog:
Here is the relevant documentation:
https://www.eurekalog.com/help/eurekalog/index.php?how_to_convert_call_stack_to_text.php
Or a free version via GetIt Jedi, or get the code in GitHub. Here is how you manually get the call stack:
procedure LogException(const E: Exception);
var
msg: string;
StackTrace: string;
begin
StackTrace := '';
if not IsNullOrEmpty(E.StackTrace) then
StackTrace := E.StackTrace
else
begin
{$IFDEF EUREKALOG}
{ Eurecalog is a bit of a puzzle but one needs following using statement
for the code to compile:
IsEurekaLogInstalled() -> ExceptionLog7 or EBase
IsEurekaLogActive() -> ExceptionLog7 or EBase
GetTracer(int) -> ECallStack
CallStackToString(statce,header) -> ECallStack
TCompactStackFormatter -> ECallStack
TracerFramesEurekaLogV7 -> const with the value of 6 in EStackTracing
https://www.eurekalog.com/help/eurekalog/how_to_convert_call_stack_to_text.php
}
if IsEurekaLogInstalled() and IsEurekaLogActive() and IsNullOrEmpty(StackTrace) then
begin
var callStack := GetTracer(TracerFramesEurekaLogV7);
var formatter:= TCompactStackFormatter.Create;
try
CallStack.Build(CallStack.GetCurrentInstruction);
//use the stack and covert it to a simple string
StackTrace := CallStackToString(callStack,'Callastack:',formatter);
finally
FreeAndNil(callStack);
FreeAndNil(formatter);
end;
end;
{$ENDIF}
{$IFDEF JclDebugEnabled }
if IsNullOrEmpty(StackTrace) then
begin
var list := TStringList.Create;
try
JclLastExceptStackListToStrings(list,True, True, True, False);
StackTrace := list.Text;
finally
FreeAndNil(list);
end;
end;
{$ENDIF}
end;
msg := Format('%s: %s on %s', [E.ClassName, E.Message,StackTrace]);
Log(msg, etException);//Quick Logger https://blogs.embarcadero.com/quick-logger-is-a-powerful-enterprise-grade-asynchronous-logger-for-delphi/
end;
I define if I use JEDI or EurekaLog using a compiler directive in the source of a .dpr file, you could do it in the project options UI as well:
{$DEFINE JclDebugEnabled}
The same goes for EurekaLog; however, the EurekaLog wizard does it for you:
I did not write the code for re-use, but one could take the parts and make it more integration-friendly.
Here is a nice link to help those who like to understand jclDebug
https://blog.dummzeuch.de/2014/03/08/using-jcldebug/ as jclDebug needs to be enabled; from the link:
initialization
// Enable raw mode (default mode uses stack frames which aren't always generated by the compiler)
Include(JclStackTrackingOptions, stRawMode);
// Disable stack tracking in dynamically loaded modules (it makes stack tracking code a bit faster)
Include(JclStackTrackingOptions, stStaticModuleList);
// Initialize Exception tracking
JclStartExceptionTracking;
finalization
JclStopExceptionTracking;
end.