Вложенное / Отформатированное ведение журнала - PullRequest
0 голосов
/ 01 февраля 2012

Может быть, это тривиальный вопрос, и многие / большинство / все хорошие фреймворки могут это сделать, но я ищу класс / фреймворк логгера (настолько простой, насколько это возможно), который облегчает иметьвложенный вывод журналирования, что-то вроде

[time] A::doSomething start
[time]   doing this
[time]   doing that
[time]   calling B
[time]   B::somethingElse start
[time]     do
[time]     re
[time]     mi
[time]     c::foo start
[time]       ...
[time]     c::foo end
[time]   B::somethingElse end
[time] A::doSomething end

Наиболее близким, с чем я столкнулся при поиске межсетей, являются вложенные диагностические контексты в log4j .Но а) это для java и б) я не уверен, если это обеспечивает то, что я ищу ...

И есть это "При выходе из контекста, вызовите NDC.pop" в документации,Я хотел бы иметь больше магии на основе стека, если это возможно.

Существуют ли какие-либо проекты, которые могут сделать то, что я ищу?

TIA

1 Ответ

0 голосов
/ 01 февраля 2012

Я не знаю ни одного фреймворка для ведения журнала, но я играл на достаточно симпатичном принтере, так что я знаю, что это не очень сложно.

Предположим, существует класс Logger, который поддерживает push иpop операций:

class LogNester: private boost::noncopyable {
public:
  LogNester(Logger& l): logger(l) { logger.push(); }
  ~LogNester() { logger.pop(); }

private:
  Logger& logger;
};

Использование:

void foo() {
  LogNester _(GlobalLogger);

  // do something
}

Важный момент one : вам необходимо имя переменной, LogNester(GlobalLogger) будет выдвигать и выдвигать только это утверждение (upps), тогда как именованная переменная будет жить до конца области действия.

Если вам надоело каждый раз придумывать новые имена (что я могу понять), вы всегда можете прибегнуть к макросу:

#define NESTLOG() LogNester BOOST_PP_CAT(log, __LINE__)(GlobalLogger);

Тем не менее, он не совсем ... автоматизирован, так как вам нужно определить LogNester объект при входе для каждого метода.Теоретически, вы должны быть в состоянии волшебно получить глубину, если не возражаете немного замедлить: использование информации о вызовах стека.С gcc это делается с помощью утилиты backtrace:

#include <execinfo.h> // GNU/Linux specific header

inline unsigned depth() {
  void* Stack[64];
  return backtrace(Stack, sizeof(Stack));
}

Затем улучшите макрос ведения журнала:

#define LOG(Message_) \
  do { \
    GlobalLogger.log(__FILE__, __LINE__, __FUNCTION__, depth(), Message_); \
  } while(0)

Конечно, это очень зависит от того, являются ли вызовы встроеннымиили нет.

Я лично обнаружил, что __FILE__, __LINE__ и __FUNCTION__ было достаточно для моих нужд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...