From 9fcc7811726f19c5d4368d208ed605d0ee51a3f0 Mon Sep 17 00:00:00 2001 From: Julian Brost Date: Tue, 20 Oct 2020 11:22:20 +0200 Subject: [PATCH] Restructure stack and context trace selection in DiagnosticInformation and document behavior The logic for selecting the traces to print stays the same, but there are fewer nested ifs now. This changes the format of the returned string a bit by adding a heading for both traces. --- lib/base/exception.cpp | 45 ++++++++++++++++++++++-------------------- lib/base/exception.hpp | 19 ++++++++++++++++++ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/lib/base/exception.cpp b/lib/base/exception.cpp index 5ab24cec0..c6e485483 100644 --- a/lib/base/exception.cpp +++ b/lib/base/exception.cpp @@ -223,34 +223,37 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, boo const auto *pex = dynamic_cast(&ex); if (!uex && !pex && verbose) { + // Print the first of the following stack traces (if any exists) + // 1. stack trace from boost exception error information const boost::stacktrace::stacktrace *st = boost::get_error_info(ex); + // 2. stack trace explicitly passed as a parameter + if (!st) { + st = stack; + } + // 3. stack trace saved when the last exception was thrown + if (!st) { + st = GetLastExceptionStack(); + } - if (st) { - result << *st; - } else { - result << std::endl; - - if (!stack) - stack = GetLastExceptionStack(); - - if (stack) - result << *stack; - + if (st && !st->empty()) { + result << "\nStacktrace:\n" << *st; } } + // Print the first of the following context traces (if any exists) + // 1. context trace from boost exception error information const ContextTrace *ct = boost::get_error_info(ex); + // 2. context trace explicitly passed as a parameter + if (!ct) { + ct = context; + } + // 3. context trace saved when the last exception was thrown + if (!ct) { + ct = GetLastExceptionContext(); + } - if (ct) { - result << *ct; - } else { - result << std::endl; - - if (!context) - context = GetLastExceptionContext(); - - if (context) - result << *context; + if (ct && ct->GetLength() > 0) { + result << "\nContext:\n" << *ct; } return result.str(); diff --git a/lib/base/exception.hpp b/lib/base/exception.hpp index 10e2b4d0b..279b1d036 100644 --- a/lib/base/exception.hpp +++ b/lib/base/exception.hpp @@ -93,6 +93,25 @@ typedef boost::error_info ContextTraceErrorInfo; std::string to_string(const ContextTraceErrorInfo& e); +/** + * Generate diagnostic information about an exception + * + * The following information is gathered in the result: + * - Exception error message + * - Debug information about the Icinga config if the exception is a ValidationError + * - Stack trace + * - Context trace + * + * Each, stack trace and the context trace, are printed if the they were saved in the boost exception error + * information, are explicitly passed as a parameter, or were stored when the last exception was thrown. If multiple + * of these exist, the first one is used. + * + * @param ex exception to print diagnostic information about + * @param verbose if verbose is set, a stack trace is added + * @param stack optionally supply a stack trace + * @param context optionally supply a context trace + * @return string containing the aforementioned information + */ String DiagnosticInformation(const std::exception& ex, bool verbose = true, boost::stacktrace::stacktrace *stack = nullptr, ContextTrace *context = nullptr); String DiagnosticInformation(const boost::exception_ptr& eptr, bool verbose = true);