add: [log] exception handling for log printing

This commit is contained in:
mutouyun 2022-08-07 17:51:30 +08:00
parent 3522061321
commit 56ee0e12df
4 changed files with 39 additions and 25 deletions

View File

@ -6,14 +6,14 @@
namespace {
void BM_imp_log_no_output(benchmark::State& state) {
imp::log::gripper log {{}, __func__};
imp::log::gripper log {__func__, {}};
for (auto _ : state) {
log.debug("hello log.");
}
}
void BM_imp_log_gripper(benchmark::State& state) {
imp::log::gripper log {{}, __func__};
imp::log::gripper log {__func__, {}};
for (auto _ : state) {
log.info("hello log.");
}

View File

@ -9,6 +9,7 @@
#include <string>
#include <type_traits>
#include <chrono>
#include <exception>
#include "fmt/format.h"
#include "fmt/chrono.h"
@ -53,22 +54,22 @@ template <typename T>
constexpr bool has_fn_output_v = has_fn_output<T>::type::value;
struct vtable_t {
void (*output)(void *, log::level, std::string &&);
void (*output)(void *, log::level, std::string &&) noexcept;
};
template <typename T>
class traits {
template <typename U>
static auto make_fn_output() noexcept
-> std::enable_if_t<has_fn_output_v<U>, void (*)(void *, log::level, std::string &&)> {
return [](void *p, log::level l, std::string &&s) {
-> std::enable_if_t<has_fn_output_v<U>, void (*)(void *, log::level, std::string &&) noexcept> {
return [](void *p, log::level l, std::string &&s) noexcept {
static_cast<U *>(p)->output(l, std::move(s));
};
}
template <typename U>
static auto make_fn_output() noexcept
-> std::enable_if_t<!has_fn_output_v<U>, void (*)(void *, log::level, std::string &&)> {
return [](void *, log::level, std::string &&) {};
-> std::enable_if_t<!has_fn_output_v<U>, void (*)(void *, log::level, std::string &&) noexcept> {
return [](void *, log::level, std::string &&) noexcept {};
}
public:
@ -98,12 +99,12 @@ public:
explicit operator bool() const noexcept;
void output(log::level, std::string &&);
void output(log::level, std::string &&) noexcept;
};
class LIBIMP_EXPORT std_t {
public:
void output(log::level, std::string &&);
void output(log::level, std::string &&) noexcept;
};
LIBIMP_EXPORT extern std_t std_out;
@ -114,51 +115,58 @@ class gripper {
level level_limit_;
template <typename Fmt, typename... A>
gripper &output(log::level l, Fmt &&ft, A &&... args) {
gripper &output(log::level l, Fmt &&ft, A &&... args) noexcept {
if (!printer_ || (enum_cast(l) < enum_cast(level_limit_))) {
return *this;
}
constexpr static char types[] = {
'T', 'D', 'I', 'W', 'E', 'F'
};
try {
auto tp = std::chrono::system_clock::now();
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(tp).time_since_epoch().count() % 1000;
auto px = fmt("[{}][{:%Y-%m-%d %H:%M:%S}.{:03}][{}] ", types[enum_cast(l)], tp, ms, func_);
printer_.output(l, std::move(px += fmt(std::forward<Fmt>(ft), std::forward<A>(args)...)));
} catch (std::exception const &e) {
/// @brief [TBD] std::string constructor may throw an exception
printer_.output(level::failed, e.what());
}
return *this;
}
public:
gripper(printer printer, char const *func, level level_limit = level::info) noexcept
gripper(char const *func, printer printer = std_out, level level_limit = level::info) noexcept
: printer_ (printer)
, func_ (func)
, level_limit_(level_limit) {}
template <typename Fmt, typename... A>
gripper &trace(Fmt &&ft, A &&... args) {
gripper &trace(Fmt &&ft, A &&... args) noexcept {
return output(log::level::trace, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
template <typename Fmt, typename... A>
gripper &debug(Fmt &&ft, A &&... args) {
gripper &debug(Fmt &&ft, A &&... args) noexcept {
return output(log::level::debug, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
template <typename Fmt, typename... A>
gripper &info(Fmt &&ft, A &&... args) {
gripper &info(Fmt &&ft, A &&... args) noexcept {
return output(log::level::info, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
template <typename Fmt, typename... A>
gripper &warning(Fmt &&ft, A &&... args) {
gripper &warning(Fmt &&ft, A &&... args) noexcept {
return output(log::level::warning, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
template <typename Fmt, typename... A>
gripper &error(Fmt &&ft, A &&... args) {
gripper &error(Fmt &&ft, A &&... args) noexcept {
return output(log::level::error, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
template <typename Fmt, typename... A>
gripper &failed(Fmt &&ft, A &&... args) {
gripper &failed(Fmt &&ft, A &&... args) noexcept {
return output(log::level::failed, std::forward<Fmt>(ft), std::forward<A>(args)...);
}
};
} // namespace log
LIBIMP_NAMESPACE_END_
#define LIBIMP_LOG_(...) LIBIMP_NAMESPACE_::log::gripper log {__func__, __VA_ARGS__}

View File

@ -11,14 +11,14 @@ printer::operator bool() const noexcept {
return (objp_ != nullptr) && (vtable_ != nullptr);
}
void printer::output(log::level l, std::string &&s) {
void printer::output(log::level l, std::string &&s) noexcept {
if (!*this) return;
vtable_->output(objp_, l, std::move(s));
}
std_t std_out;
void std_t::output(log::level l, std::string &&s) {
void std_t::output(log::level l, std::string &&s) noexcept {
switch (l) {
case level::trace:
case level::debug:

View File

@ -68,6 +68,12 @@ TEST(log, log_printer) {
}
TEST(log, gripper) {
imp::log::gripper log {imp::log::std_out, __func__};
{
imp::log::gripper log {__func__};
log.info("hello");
}
{
LIBIMP_LOG_();
log.info("hello 2");
}
}