Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

Commit

Permalink
[debug] tracing priority corresponding to syslog priority
Browse files Browse the repository at this point in the history
Environment variable QTAROUND_DEBUG defines minimal priority for tracing,
default is Priority::Warning

Signed-off-by: Denis Zalevskiy <denis.zalevskiy@jolla.com>
  • Loading branch information
Denis Zalevskiy committed May 21, 2015
1 parent 1b1093c commit 2a69d3f
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 34 deletions.
74 changes: 61 additions & 13 deletions include/qtaround/debug.hpp
Expand Up @@ -4,29 +4,54 @@
* @file debug.hpp
* @brief Debug tracing support
* @author Denis Zalevskiy <denis.zalevskiy@jolla.com>
* @copyright (C) 2014 Jolla Ltd.
* @copyright (C) 2014-2015 Jolla Ltd.
* @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*/

#include <qtaround/util.hpp>

#include <QVariant>
#include <QDebug>
#include <QTextStream>

#include <memory>

namespace qtaround { namespace debug {

enum class Level { Debug = 1, Info, Warning, Error, Critical };

QDebug stream();

template <typename T, typename ... Args>
QDebug & operator << (QDebug &d, std::function<T(Args...)> const &)
{
d << "std::function<...>";
return d;
}

namespace qtaround { namespace debug {

enum class Level { First_ = 1, Debug = First_, Info, Warning, Error
, Critical, Last_ = Critical };
/// compatible with syslog priorities
enum class Priority { First_ = 0, Emerg = First_, Alert, Crit
, Err, Warning, Notice, Info
, Debug, Last_ = Debug };

void set_max_priority(Priority);
Priority get_priority(Level);
void init();

template <Priority P>
struct Traits {
Traits() { }
QDebug stream();
QMessageLogger logger;
};

extern template struct Traits<Priority::Debug>;
extern template struct Traits<Priority::Info>;
extern template struct Traits<Priority::Notice>;
extern template struct Traits<Priority::Warning>;
extern template struct Traits<Priority::Err>;
extern template struct Traits<Priority::Crit>;
extern template struct Traits<Priority::Alert>;
extern template struct Traits<Priority::Emerg>;

static inline void print(QDebug &&d)
{
QDebug dd(std::move(d));
Expand All @@ -39,14 +64,23 @@ void print(QDebug &&d, T &&v1, A&& ...args)
return print(std::move(d), std::forward<A>(args)...);
}

// template <Level L, typename ... A>
// void print_for(A&& ...args)
// {
// Traits<L> ctx;
// return print(ctx.stream(), std::forward<A>(args)...);
// }

template <typename ... A>
void print(A&& ...args)
{
return print(stream(), std::forward<A>(args)...);
Traits<Priority::Emerg> ctx;
return print(ctx.stream(), std::forward<A>(args)...);
}

void level(Level);
bool is_tracing_level(Level);
bool is_traceable(Priority);

template <typename ... A>
void print_ge(Level print_level, A&& ...args)
Expand All @@ -55,34 +89,48 @@ void print_ge(Level print_level, A&& ...args)
print(std::forward<A>(args)...);
}

template <typename ... A>
void print_ge(Priority prio, A&& ...args)
{
if (is_traceable(prio))
print(std::forward<A>(args)...);
}

template <Priority P, typename ... A>
void print_ge_for(A&& ...args)
{
if (is_traceable(P))
print(std::forward<A>(args)...);
}

template <typename ... A>
void debug(A&& ...args)
{
print_ge(Level::Debug, std::forward<A>(args)...);
print_ge_for<Priority::Debug, A...>(std::forward<A>(args)...);
}

template <typename ... A>
void info(A&& ...args)
{
print_ge(Level::Info, std::forward<A>(args)...);
print_ge(Priority::Info, std::forward<A>(args)...);
}

template <typename ... A>
void warning(A&& ...args)
{
print_ge(Level::Warning, std::forward<A>(args)...);
print_ge(Priority::Warning, std::forward<A>(args)...);
}

template <typename ... A>
void error(A&& ...args)
{
print_ge(Level::Error, std::forward<A>(args)...);
print_ge(Priority::Err, std::forward<A>(args)...);
}

template <typename ... A>
void critical(A&& ...args)
{
print_ge(Level::Critical, std::forward<A>(args)...);
print_ge(Priority::Crit, std::forward<A>(args)...);
}

}}
Expand Down
18 changes: 18 additions & 0 deletions include/qtaround/util.hpp
Expand Up @@ -124,6 +124,24 @@ QString get(QVariant const &from)
return from.toString();
}

template <typename T, typename I>
static bool can_convert
(I v, typename std::enable_if<std::is_enum<T>::value>::type* = 0)
{
return (v >= static_cast<I>(T::First_)
&& v <= static_cast<I>(T::Last_));
}

template <typename T, typename FnT, typename I>
static bool call_if_convertible
(I v, FnT fn, typename std::enable_if<std::is_enum<T>::value>::type* = 0)
{
bool res = can_convert<T>(v);
if (res)
fn(static_cast<T>(v));
return res;
}

}

template <typename ... A>
Expand Down
167 changes: 147 additions & 20 deletions src/debug.cpp
Expand Up @@ -13,46 +13,173 @@

namespace qtaround { namespace debug {


Priority get_priority(Level l)
{
static Priority l2p[] = { Priority::Debug, Priority::Info
, Priority::Warning, Priority::Err
, Priority::Crit };
int i = static_cast<int>(l) - static_cast<int>(Level::First_);
return l2p[i];
}

namespace {

int current_level = static_cast<int>(Level::Warning);
std::mutex mutex;
bool is_init = false;
int priority_from_env();

int current_priority = static_cast<int>(priority_from_env());

void set_priority(Priority p)
{
current_priority = static_cast<int>(p);
}

int get_priority(char const *name)
{
static std::map<std::string, Priority> data = {
{"Debug", Priority::Debug},
{"Info", Priority::Info},
{"Notice", Priority::Notice},
{"Warning", Priority::Warning},
{"Err", Priority::Err},
{"Crit", Priority::Crit},
{"Alert", Priority::Alert},
{"Emerg", Priority::Emerg},
};
auto res = -1;
if (name) {
auto it = data.find(name);
if (it != data.cend())
res = static_cast<int>(it->second);
}
return res;
}


void init()
void set_level(Level l)
{
if (!is_init) {
std::lock_guard<std::mutex> l(mutex);
if (is_init)
return;
auto c = ::getenv("CUTES_DEBUG");
set_priority(get_priority(l));
}

int env_get(char const *name, int def_val)
{
int res = def_val;
if (name) {
auto c = ::getenv(name);
if (c) {
std::string name(c);
current_level = name.size() ? std::stoi(name) : (int)Level::Critical;
char *end = nullptr;
auto conv = strtol(c, &end, 10);
if (c + strlen(c) == end)
res = conv;
}
}
return res;
}

char const* env_get(char const *name, char const* def_val)
{
auto res = def_val;
if (name) {
auto c = ::getenv(name);
if (c)
res = c;
}
return res;
}

int priority_from_env()
{
auto prio = env_get("QTAROUND_DEBUG", -1);
// allow out of range values
if (prio == -1) {
prio = get_priority(env_get("QTAROUND_DEBUG", nullptr));
if (prio == -1) {
auto level = env_get("CUTES_DEBUG", -1);
prio = static_cast<int>
((can_convert<Level>(level)
? get_priority(static_cast<Level>(level))
: Priority::Warning));
}
is_init = true;
}
return prio;
}

} // anon ns

// stub for backward compatibility
void init() { }

template struct Traits<Priority::Debug>;
template struct Traits<Priority::Info>;
template struct Traits<Priority::Notice>;
template struct Traits<Priority::Warning>;
template struct Traits<Priority::Err>;
template struct Traits<Priority::Crit>;
template struct Traits<Priority::Alert>;
template struct Traits<Priority::Emerg>;

template <>
QDebug Traits<Priority::Debug>::stream()
{
return logger.debug();
}

template <>
QDebug Traits<Priority::Info>::stream()
{
return logger.debug();
}

template <>
QDebug Traits<Priority::Notice>::stream()
{
return logger.debug();
}

template <>
QDebug Traits<Priority::Warning>::stream()
{
return logger.warning();
}

QDebug stream()
template <>
QDebug Traits<Priority::Err>::stream()
{
init();
return qDebug();
return logger.critical();
}

template <>
QDebug Traits<Priority::Crit>::stream()
{
return logger.critical();
}

template <>
QDebug Traits<Priority::Alert>::stream()
{
return logger.critical();
}

template <>
QDebug Traits<Priority::Emerg>::stream()
{
return logger.critical();
}

void level(Level level)
{
init();
current_level = static_cast<int>(level);
set_level(level);
}

bool is_traceable(Priority prio)
{
auto p = static_cast<int>(prio);
return (current_priority >= p);
}

bool is_tracing_level(Level level)
{
init();
auto l = static_cast<int>(level);
return current_level ? l >= current_level : false;
return is_traceable(get_priority(level));
}

}}
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Expand Up @@ -6,7 +6,7 @@ set(CMAKE_AUTOMOC TRUE)
find_package(Qt5Core REQUIRED)

testrunner_project(qtaround)
set(UNIT_TESTS os dbus misc mt)
set(UNIT_TESTS os dbus misc mt debug)

MACRO(UNIT_TEST _name)
set(_exe_name test_${_name})
Expand Down

0 comments on commit 2a69d3f

Please sign in to comment.