Goal: capture a stack trace plus useful contextual variables when an exception originates deep inside a third‑party library — without editing that library. Approaches differ per runtime; use wrappers, runtime hooks, or external instrumentation.Python- Strategy: wrap calls and capture exception info; use traceback + inspect to walk frames and read locals; use faulthandler for crashes; use sys.settrace or pdb post-mortem for live inspection.- Example:python
import traceback, inspect, sys
try:
library.do_work()
except Exception:
tb = sys.exc_info()[2]
for frame, lineno in traceback.walk_tb(tb):
print(frame.f_code.co_name, frame.f_lineno)
print(frame.f_locals) # contextual variables
raise
- Trade-offs: reading frame.f_locals works but can impact GC/perf; sys.settrace offers richer context but high overhead.Java- Strategy: use a global uncaught-exception handler for threads, or attach a javaagent (ByteBuddy/ASM) to instrument methods at load time to capture locals and create richer error reports; use JVM tooling (jstack, jmap) or BTrace for live probes without code change.- Example (uncaught handler):java
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
e.printStackTrace(); // stack trace
// attach contextual info from your app (request id, user id) stored in ThreadLocal
System.err.println("RequestId: " + RequestContext.getId());
});
- Trade-offs: bytecode agents can capture method args/locals but require more setup; handlers only expose what you can access (ThreadLocal/app context).Node.js- Strategy: wrap async entry points, use process.on('uncaughtException') / unhandledRejection for last-resort traces; use the V8 Inspector / Debugger Protocol to capture scope locals programmatically or use APMs (Elastic/AWS/NewRelic).- Example:javascript
process.on('uncaughtException', (err) => {
console.error(err.stack);
console.error('Context:', global.requestContext); // capture context you maintain
process.exit(1);
});
- Trade-offs: V8 doesn't expose locals from stack traces easily without debugging APIs; best practice is to propagate context (e.g., async_hooks or CLS) so you can log it when exceptions occur.General best practices- Maintain and propagate contextual metadata (request id, user id) in ThreadLocal/Context/async_hooks so any top-level handler can log it.- Prefer lightweight try/catch at boundary layers where you control code.- For production, consider bytecode/agent instrumentation or APMs to capture deeper info without changing library code, mindful of performance and security.