diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-04-30 23:21:12 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-04-30 23:26:21 +0300 |
commit | 0ffb0a1a0a13d07c4448f7752232d8854b790623 (patch) | |
tree | 9d1e173375d53e05c52568dc69633ed98697190d /bbot/diagnostics.hxx | |
parent | 1364413cee696ff60f4dd1e3ac1eb281ac7a4e8f (diff) |
Add hxx extension for headers and lib prefix for library dirs
Diffstat (limited to 'bbot/diagnostics.hxx')
-rw-r--r-- | bbot/diagnostics.hxx | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/bbot/diagnostics.hxx b/bbot/diagnostics.hxx new file mode 100644 index 0000000..07052a0 --- /dev/null +++ b/bbot/diagnostics.hxx @@ -0,0 +1,166 @@ +// file : bbot/diagnostics.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : TBC; see accompanying LICENSE file + +#ifndef BBOT_DIAGNOSTICS_HXX +#define BBOT_DIAGNOSTICS_HXX + +#include <butl/diagnostics> + +#include <bbot/types.hxx> // Note: not <bbot/utility>. + +namespace bbot +{ + using butl::diag_record; + + // Throw this exception to terminate the process. The handler should + // assume that the diagnostics has already been issued. + // + class failed: public std::exception {}; + + // Verbosity level. Update documentation for --verbose if changing. + // + // 0 - disabled + // 1 - high-level information messages + // 2 - essential underlying commands that are being executed + // 3 - all underlying commands that are being executed + // 4 - information that could be helpful to the user + // 5 - information that could be helpful to the developer + // 6 - even more detailed information + // + // While uint8 is more than enough, use uint16 for the ease of printing. + // + extern uint16_t verb; + + template <typename F> inline void l1 (const F& f) {if (verb >= 1) f ();} + template <typename F> inline void l2 (const F& f) {if (verb >= 2) f ();} + template <typename F> inline void l3 (const F& f) {if (verb >= 3) f ();} + template <typename F> inline void l4 (const F& f) {if (verb >= 4) f ();} + template <typename F> inline void l5 (const F& f) {if (verb >= 5) f ();} + template <typename F> inline void l6 (const F& f) {if (verb >= 6) f ();} + + // Diagnostic facility, base infrastructure. + // + using butl::diag_stream; + using butl::diag_epilogue; + + // Diagnostic facility, project specifics. + // + struct simple_prologue_base + { + explicit + simple_prologue_base (const char* type, const char* name) + : type_ (type), name_ (name) {} + + void + operator() (const diag_record& r) const; + + private: + const char* type_; + const char* name_; + }; + + struct basic_mark_base + { + using simple_prologue = butl::diag_prologue<simple_prologue_base>; + + explicit + basic_mark_base (const char* type, + const char* indent = "\n ", + const char* name = nullptr, + const void* data = nullptr, + diag_epilogue* epilogue = nullptr) + : type_ (type), name_ (name), data_ (data), + indent_ (indent), epilogue_ (epilogue) {} + + simple_prologue + operator() () const + { + return simple_prologue (indent_, epilogue_, type_, name_); + } + + public: + const char* type_; + const char* name_; + const void* data_; + + const char* indent_; + diag_epilogue* const epilogue_; + }; + using basic_mark = butl::diag_mark<basic_mark_base>; + + extern basic_mark error; + extern basic_mark warn; + extern basic_mark info; + extern basic_mark text; + + // trace + // + extern const char* trace_type; + extern const char* trace_indent; + + struct trace_mark_base: basic_mark_base + { + explicit + trace_mark_base (const char* name, const void* data = nullptr); + }; + using trace_mark = butl::diag_mark<trace_mark_base>; + + // using tracer = trace_mark; + class tracer: public trace_mark + { + public: using trace_mark::trace_mark; + }; + + // fail + // + struct fail_mark_base: basic_mark_base + { + explicit + fail_mark_base (const char* type, + const char* indent = "\n ", + const void* data = nullptr) + : basic_mark_base (type, + indent, + nullptr, + data, + [](const diag_record& r) + { + r.flush (); + throw failed (); + }) {} + }; + + using fail_mark = butl::diag_mark<fail_mark_base>; + + struct fail_end_base + { + [[noreturn]] void + operator() (const diag_record& r) const + { + // If we just throw then the record's destructor will see an active + // exception and will not flush the record. + // + r.flush (); + throw failed (); + } + }; + using fail_end = butl::diag_noreturn_end<fail_end_base>; + + extern fail_mark fail; + extern const fail_end endf; + + // Map to systemd severity prefixes (see sd-daemon(3) for details). Note + // that here we assume we will never have location (like file name which + // would end up being before the prefix). + // + // If with_critical is true, then distinguish between fail (critical error, + // daemon terminates) and error (non-fatal error, daemon continues to run). + // Note that this means we should be careful not to use fail to report + // normal errors and vice-versa. + // + void + systemd_diagnostics (bool with_critical); +} + +#endif // BBOT_DIAGNOSTICS_HXX |