Esate.ru

Ведение лога

Часто приходится вести отладочную информацию, чаще всего, в простых случаях это делается в консоль. Но гораздо чаще необходимо вести лог и в консоль, и в файл.
Поведаю Вам о простом классике логирования, который симулирует стандартные cout, cerr, используя шаблонную функцию-оператор <<. Расскажу о некоторых специфичных моментах с которыми столкнулся.


Log.h
/*http://esate.ru, Flashhell*/

#ifndef LOG_H
#define LOG_H

#include <fstream>
#include <iostream>

namespace support
{

class Log
{
public:
  Log();
  ~Log();

  template <class T>
  Log& operator<<(const T& p)
  {
   #ifdef _DEBUG
    std::cerr<<p;
   #endif
   log_file<<p;
   log_file.flush();
   return *this;
  }

private: 
  std::ofstream log_file;
};

extern Log LogOut;

}// end namespace
#endif


Как видно из шаблонной функции(operator<<;) она просто, принимает шаблонный параметр и в случаи дебажной сборки отправляет его на стандартный вывод std::cerr. Думаю в релизе консоли уже не будет. std::cerr я использовал потому, что он не буферизирован, это дает надежду, что выведется все что можно перед закрытием приложения. Также параметр сразу записывает в файл log_file. Файлу сразу же делаем flush(), чтоб все что есть в буфере было записано. Оператор возвращает ссылку на объект, что позволяет использовать его неоднократно, как cout: cout<<"вывод"<<"еще вывод".

/*http://esate.ru, Flashhell*/

extern Log LogOut;
Описываем объект LogOut extern-ом, а сам глобальный объект будет определятся в .cpp. Это сделано по примеру объектов cout, cerr, для того, чтобы был один глобальный объект и к нему можно легко обращаться из любого места где подключен заголовочный файл Log.h. Объект будет жив до конца работы программы.
[/code]
Log.cpp
/*http://esate.ru, Flashhell*/

#include "Log.h"

namespace support
{

Log LogOut;

Log::Log()
:log_file("Log.txt")
{
}

Log::~Log()
{
  log_file.close();
}

}//end namespace


Здесь все просто в конструкторе открываем файл, со стандартным именем. А в деструкторе его закрываем.


Использование:
/*http://esate.ru, Flashhell*/

#include "Log.h"

int main(int argc, char** argv)
{
  support::LogOut<<"Hello log! "<<"\n";
  support::LogOut<<2389<<" ";
  support::LogOut<<2389.23<<"\n";
  return 0;
}


К минусам, этого подхода можно отнести, невозможность использовать манипуляторы потока, такие, как std::endl. А также, то что запись происходит в основном, единственном потоке, что может негативно сказаться, в случаи реалтайм приложения, которое постоянно введет лог. Знаю об этом не понаслышке, так как у меня ноутбук с экономичный по энергопотреблению жестким диском, который вечно паркуют головки.>( И поэтому некоторые написанные мной игры вечно лагают зависают, на небольшие промежутки времени(пока шпиндель снова раскрутится). К счастью на компьютерах, или ноутбуках не с такими как у меня HDD, эти лаги могут напрочь отсутствовать.

Надеюсь кому нибудь пригодится. Об ошибках пишите в личку.

0       1535        10.02.2013

Блоги Esate.ru

Регистрация

Регистрируясь, вы принимаете правила сайта. Если вы не получили код подтв. регистрации - не забудьте проверить папку спам.
Логин*
Email*
Пароль*
Подтверждение пароля*
 
Логин*
Код*
 

Восстановление пароля

Пожалуйста, заполните поля, после чего вы получите код подтверждения на ваш E-mail. Если код не пришел в течении нескольких минут - проверьте папку спам.
Логин

или Email
 
Логин*
Код подтверждения*
Новый пароль*
Подтверждение пароля*
 

Авторизация

Пожалуйста, авторизуйтесь, для входа на сайт с помощью соц. сети:
  • Используйте вашу учетную запись на Facebook.com для входа на сайт.
  • Используйте вашу учетную запись VKontakte для входа на сайт.
  • Используйте вашу учетную запись Google для входа на сайт.

или с помощью аккаунта на сайте:

Логин
Пароль