LINUX.ORG.RU

Макроопределения и отладочный вывод в C++. Когда очень хочется

 , ,


0

3

Страуструп в своей книге «С++ принципы и практика» откровенно не рекомендует использовать макроопределения из-за возможных сложностей в отладке и пр, но много лет практики на С берут свое и очень хочется сделать что-то типа

#ifndef DEBUG
#define DEBUG
    printf(...);
#endif
Но я бы не хотела включать таким образом отладочный вывод во всех методах, значит придется делать для каждого метода свой DEBUG, а потом инициализировать их перед сборкой проекта...

Хотелось бы узнать как «правильно» выводить отладочную информацию без ущерба читаемости и производительности. Гуглила логгеры и нашла просто монстров на гитхабе и в каких-то обзорах. Хотелось бы услышать мнение и инструменты кто чем пользуется


Не видел ни одного годного(printf не есть такой) фреймворка для логгирования без использования макросов.

Мне нравится вот такой вот синтаксис:

LOG_DEBUG("Message:" << data << " more details: " << other_data);

При таком подходе, при отключенном уровне логгирования можно не платить за формирование отладочного сообщения.

pon4ik ★★★★★ ()

Надо выпить рюмку водки и начать использовать boost.log.

DELIRIUM ☆☆☆☆☆ ()

Я пользуюсь spdlog в некоторых проектах, можно глянуть его. Не выглядит очень монструозным.

А самый, на мой взгляд, элегантный дефайн для логгинга — это

#define log(X) if (!condition(X)) {} else std::clog

Если condition(X) умеет быть constexpr, то компилятор полностью выкинет логгирование. Если я не ошибаюсь, такой подход используется в glog.

vzzo ★★★ ()

А есть ли смысл выключать логгирование ?

x905 ★★★★★ ()
Ответ на: комментарий от x905

еще как есть, обрабатывается несколько тыс соединений в секунду. можно перенаправить в /dev/null, но это тоже, как оказалось, заметно сказывается на производительности. сервер работает в 1 поток и только на 1 ядре, а нагрузка будет еще возрастать

nyka ()

не парься и используй макросы. везде так делают.

Iron_Bug ★★★★ ()

Я пишу свой класс, у которого все методы, кроме, разве что, конструктора и деструктора, статические. В нём уже, в зависимости от потребностей, делаю запись в файл, вывод в stderr, блокировки на случай многопоточного приложения и прочие нужные вещи. Для удобства ещё добавляю пару макросов. Разумеется, включение/выключение отладочного вывода производится в рантайме, что имеет как свои плюсы, так и минусы. Выглядит это примерно вот так:

#ifndef LOG_H
#define LOG_H

#define DEBUG(X) Log::writeMsg(Log::Level::Debug,   X)
#define  INFO(X) Log::writeMsg(Log::Level::Info,    X)
#define  NOTE(X) Log::writeMsg(Log::Level::Note,    X)
#define  WARN(X) Log::writeMsg(Log::Level::Warning, X)
#define ERROR(X) Log::writeMsg(Log::Level::Error,   X)
#define FATAL(X) Log::writeMsg(Log::Level::Fatal,   X)



class Log
  {
	public:
		enum class Level
		  { Fatal, Error, Warning, Note, Info, Debug };
		  
	private:
		static Level m_level;
		
	protected:
	  
	public:
		Log() {};
		~Log() {};
		
		/*** Set ***/
		static void setLevel(Log::Level level)
		  { Log::m_level = level; }
		
		/*** Get ***/
		static Level level()
		  { return Log::m_level; }
		
		/*** Other ***/
		static void writeMsg(Level level, char *str);
		// Другие перегрузки для разных типов
  };

#endif // LOG_H

XMs ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.