Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Технология ведения лога (диагностика) 
:(
    Опции темы
Lazin
Дата 29.11.2007, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Я не очень понимаю что нужно получить в итоге, наверное лучше сначала составить какой нибудь список требований к библиотеке т.е. что нам от нее надо....
использование элипсисов я считаю тупиковым, так как в данном случае теряется гибкость и расширяемость, если я сделаю свой класс, как мне расширить класс, что-бы он выводил в лог объекты моего класса. Для этого придется наследовать, от класса - логгера, и переопределять ф-ю. Лучше сделать это так, как это сделано в библиотеках iostream или boost::serializaion etc. 
должно выглядеть примерно так:
Код

int a = 10;
g_logger << "value a = " << a << my_logger::end;//выводим данные, потом выводим специальное значение, которое информирует объект о том что мы закончили формировать сообщение
//в лог должно после этого добавиться "**** value a = 10"
------
my_logger& operator << (my_logger& l, TPoint& p)//оператор вывода в лог объектов класса TPoint
{
 l << p.x << p.y;
 return *this;
}
------
TPoint p(10,20);
g_logger << "Point p = " << p << my_logger::end;

Можно использовать интерфейс как в iostream для изменения параметров (там это называется манипуляторами)
Код

g_logger << my_logger::step_into;//говорим логгеру, что нужно увеличить вложенность(новая функция)
g_logger << my_logger::return;//говорим логгеру, что нужно уменьшить степень вложенности

с таким интерфейсом проще написать макросы
Код

#define TRACE_MESSAGE(p1,p2,p3) \
            g_logger << (p1) << (p2) << (p3) << my_logger::end;

и так можно написать для любого кол. параметров

Это сообщение отредактировал(а) Lazin - 29.11.2007, 15:53
PM MAIL Skype GTalk   Вверх
_Tanatos_
Дата 29.11.2007, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.11.2007

Репутация: нет
Всего: нет



Переработал класс CtLibLogHelper
Код

class CtLibLogHelper
{
private:
    int             m_ProcID;       // Идентификатор процесса
    int             m_UnitID;       // Идентификатор модуля
    const char*     m_Function;     // Имя класса и функции
    const char*     m_File;         // Имя файла
    bool            m_Complete;     // Признак успешного завершения работы
    bool            m_LevelUp;      // Признак инициализации с увеличением уровня

    char*           m_ExMessage;    // Сооьщение
    char*           m_ExData;       // Данные
protected:
public:
   ~CtLibLogHelper();

    // Инициализация класса
    // Если LevelUp=true то первая запись будет заголовком, остальные вложенными
    // Если LevelUp=false то все записи будут в пределах одного уровня
    CtLibLogHelper(const char* File, const char* Function, bool LevelUp=true, int UnitID=0, int ProcID=0);

    // Сохраняет фрагмент сообщения
    void AddMessage(const char* Message, ...);
    void AddData(const char* Data, ...);
    // Записывает подготовленное сообщение
    // Если Complete=true, то выставляется соответствующий флаг, на false не реагирует никак
    void Post(signed char Type, int Line, bool Complete = false);
    // Принудительное освобождение памяти занятой при формировании сообщения (всегда вызывается из Post)
    void Reset();
};


Примеры использования:
Код


void SubFunc()
{
// Инициируем класс, сохраняем имя файла, функции, признак вложенности отключаем!!!, код модуля и процесса/потока
    CtLibLogHelper LogHelper(__FILE__, __FUNC__, false);

// Формируем сообщение
    LogHelper.AddMessage("...Test...");
// Записываем подготовленное сообщение (никаких вложенностей, см. конструктор)
    LogHelper.Post(lltInfo, __LINE__);
}

// Функция которая ведет вложженную запись
void Simmple()
{
// Инициируем класс, сохраняем имя файла, функции, признак вложенности, код модуля и процесса/потока
    CtLibLogHelper LogHelper(__FILE__, __FUNC__);

// Формируем заголовок
    LogHelper.AddMessage("Begin");
// Записываем подготовленное сообщение (последующие сообщения будут вложенными)
    LogHelper.Post(lltBegin, __LINE__);

// Формируем новое сообщение
    LogHelper.AddMessage("Connect...");
    LogHelper.AddData("Address: %s\n", "address");
    LogHelper.AddData("Login: %s\n", "log");
    LogHelper.AddData("Password: %s\n", "pass123");
// Записываем подготовленное сообщение
    LogHelper.Post(lltInfo, __LINE__);

// Вызываем функцию
    SubFunc();

// Формируем завершающее сообщение
    LogHelper.AddMessage("...Ok!");
// Записываем подготовленное сообщение, устанавливаем флаг успешного завершения!!!!
    LogHelper.Post(lltInfo, __LINE__, true);
}

В результате получаем следующий лог:
Код

Begin
  Connect...                                Address: address|Login: log|Password: pass123
  ...Test...
  ...Ok!


Если последний вызов
    LogHelper.Post(lltInfo, __LINE__, true);
заменить на обычный
    LogHelper.Post(lltInfo, __LINE__);
получим:
[/code]
В результате получаем следующий лог:
Код

Begin
  Connect...                                Address: address|Login: log|Password: pass123
  ...Test...
  ...return (stack unwinding)

Последняя строка сформируется автоматически.

При использовании макросов можно будет формировать как однострочные записи в журнал, так и многострочные с форматированием.
Единственное неудобство будет состоять в том, что надо будет отслеживать использование различных макросов для первой строки (где нужно объявление) и для остальных. Пока не знаю как это обойти. Есть идеи?
PM MAIL   Вверх
_Tanatos_
Дата 29.11.2007, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.11.2007

Репутация: нет
Всего: нет



Цитата(Lazin @  29.11.2007,  15:48 Найти цитируемый пост)
Я не очень понимаю что нужно получить в итоге, наверное лучше сначала составить какой нибудь список требований к библиотеке т.е. что нам от нее надо.... 


Эта ветка для этого и создана smile.
Конечно в идеале сначала составить что-то вроде ТЗ, а потом уже писать.
Но! я давненько не программировал, так что пользуясь случаем восстанавливаю навыки.

Цитата(Lazin @  29.11.2007,  15:48 Найти цитируемый пост)
использование элипсисов я считаю тупиковым, так как в данном случае теряется гибкость и расширяемость, если я сделаю свой класс, как мне расширить класс, что-бы он выводил в лог объекты моего класса. 

С таким аргументом не поспоришь smile
Да и возможность записать все в одну строку прильщает.
Непонятно только как добавлять вспомогательную информацию и  как разделять сообщение и данные?

Склоняюсь к использованию дополнительного класса CtLibLogHelper для управления вложенностью и запретить прямой доступ извне. Это позволит гарантировать, что иерархия будет корректной всегда. Иначе можно сделать 10 увеличений вложенности а потом по исключению (или недосмотру) словить неправильную иерархию. А сам класс CtLibLogEngine тогда будет использоваться для записи сообщений в текущий уровень.

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

Какие еще есть пожелания?

Это сообщение отредактировал(а) _Tanatos_ - 29.11.2007, 16:46
PM MAIL   Вверх
JackYF
Дата 29.11.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Не насилуйте va_args, юзайте boost::format...


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Lazin
Дата 29.11.2007, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



как вариант, определить оператор << в классе LogHelper, будет более логично...
тем более LogHelper отвечает за контроль иерархии записей
PM MAIL Skype GTalk   Вверх
_Tanatos_
Дата 29.11.2007, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 20.11.2007

Репутация: нет
Всего: нет



А как такой вариант?
Код

LogHelper.Log(Type, Error, __LINE__) << "Message with error" << loData << "Data" << loPost;
LogHelper.Log(Type, __LINE__) << "Message with complete" << loData << "Data" << loComplete;

Опробовал вполне работоспособный вариант.

С макросом вообще сказка получается:
Код

LOG_Info << "Message" << loData << "Data" << loPost;
LOG_Error(12)  << "Message with error" << loData << "Data" << loPost;
LOG_Complete << "Message with complete" << loData << "Data" << loComplete;


Остается правда вопрос! Как с помощью макроса при финальной компиляции исключить из кода запись в журнал?

Это сообщение отредактировал(а) _Tanatos_ - 29.11.2007, 21:07
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0975 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.