Интересно, какой метод трассировки для вас самый лучший.
В настоящее время я определяю уровень трассировки для каждого исходного макроса ведьмы непосредственно перед включением заголовка трассы, который использует определенный макрос.
Например:
trace.h:
#if DEBUG == 0
#define debug(...)
#define trace(...)
#elif DEBUG==1
#define debug(...)
#define trace(...) printf(__VA_ARGS__)
#elif DEBUG==2
#define debug(...) printf(__VA_ARGS__)
#define trace(...) printf(__VA_ARGS__)
#else
#error Bad DEBUG value
#endif
Для всех sources.c (trace_value варьируется)
#define DEBUG trace_value
#include "trace.h"
void func(){
debug("func()");
trace("func() ok");
reurn;
}
Тем не менее, проект растет, и я хочу использовать предварительно скомпилированный заголовок. Было бы здорово включить заголовок трассировки в мой предварительно скомпилированный заголовок. Поэтому мне интересно, каковы ваши методы трассировки? Спасибо.
РЕДАКТИРОВАТЬ:
Я забыл написать важную вещь, мне интересна техника ведения журналов для приложений, критичных к задержкам.
Ведение журнала — сложная проблема, и то, что она делает / как вы ее используете, сильно зависит от потребностей вашего приложения.
В небольших приложениях я обычно использую либо вставленные ссылки std :: ostream, либо специальный код для регистрации. Я также держусь подальше от API-интерфейсов печати в формате C (и определяю свой собственный operator<<
для вещей, которые мне нужно отследить).
В больших приложениях, если у вас есть сложные потребности в трассировке (чередование файлов журналов между выполнениями, журналы по категориям и возможность настройки извне приложения, автоматическое форматирование журналов, ведение журнала с высокой пропускной способностью / производительностью и т. Д.), Используйте внешнюю библиотеку (например, log4cpp).
Я также склонен использовать / определять макросы, только после того, как мой код может быть написан без них.
Пример реализации с внедренным потоком журналирования:
#include<iosfwd>
class http_server {
public:
http_server(std::string server, std::uint16_t listening_port,
std::ostream& log = cnull); // cnull is as defined at
// http://stackoverflow.com/a/6240980/186997
private:
std::ostream& log_;
};
Основной (консольный) код:
int main(...) {
http_server("localhost", 8080, std::clog);
}
Код юнит-теста:
std::ostringstream server_log;
http_server("localhost", 8080, server_log);
// assert on the contents of server_log
По сути, я считаю, что если мне нужно трассировать, это часть интерфейса API, а не запоздалая мысль, что-то, что я бы отключил с помощью макросов, или что-то для жесткого кода.
Если мне нужно отформатированное ведение журнала, я бы подумал о том, чтобы специализировать std :: ostream или (вероятнее всего) обернуть его в специализированный класс форматирования и внедрить его.
Макросы для трассировки кода обычно зарезервированы для кода, критичного к производительности (когда вы не можете позволить себе что-то называть, если он ничего не делает).