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

Поиск:

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


^аВаТаР^ сообщение>>
****


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

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



Цитата(Lazin @  23.11.2007,  18:53 Найти цитируемый пост)

Мне кажется эта структура сильно избыточна, если знаешь имя ф-ии, то имя файла и номер строки знать не обязательно. 

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

Цитата(_Tanatos_ @  23.11.2007,  18:17 Найти цитируемый пост)
typedef void (__closure *TtLibOnLogAdd)(CtLibLogEngine& LogEngine);

если хочешь портируемый код, то надо избавиться от не портируемого __closure. 
Цитата(_Tanatos_ @  23.11.2007,  18:17 Найти цитируемый пост)
    char*           m_Msg;      // Текст сообщения
    char*           m_Data;     // Дополнительные данные

Кто выделяет и освобождает память для этих полей? 

Цитата(_Tanatos_ @  23.11.2007,  18:17 Найти цитируемый пост)
    char            m_Type;     // Тип сообщенияы

только 256 типов сообщений? а не мало?


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Lazin
Дата 23.11.2007, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Mayk @  23.11.2007,  15:52 Найти цитируемый пост)
не согласен. имя файла и номер строки очень удобны. в любом уважающим себя редакторе есть ф-ция перехода на заданную строку. Перейти на определение ф-ции значительно сложнее. К тому же иногда хотелось бы посмортреть до каких строк работает прога, а до каких она не доходит. 

Ну номер строки еще ладно, но имя файла и имя ф-ии нужно указывать только при их изменении.
Цитата(Mayk @  23.11.2007,  15:52 Найти цитируемый пост)
если хочешь портируемый код, то надо избавиться от не портируемого __closure. 

так он же написал, что использует Borland? а есть ли какая-нибудь портируемая вльтернатива __closure ?
Цитата(Mayk @  23.11.2007,  15:52 Найти цитируемый пост)
Кто выделяет и освобождает память для этих полей? 

присоединяюсь

можно еще добавить поле - "категория", например все сообщения имеющие отношение к работе с базой данных должны иметь одну категорию, все, что имеют отношение к взаимодействию между процессами, другую, плюс должна быть возможность комбинировать категории. Это поможет в итоге отфильтровать лог, при поиске конкретной проблемы.
PM MAIL Skype GTalk   Вверх
_Tanatos_
Дата 23.11.2007, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

только 256 типов сообщений? а не мало?

А надо больше? Сколько не прикидывал, пока больше 10 не набиралось smile. Тип означает: Info, Warning, Error и аналогичное деление.
Думаю использовать более 10 уровней детализации не имеет смысла ибо ни один программист не сможет в них свободно ориентироваться.

На данный момент планирую, что память внутри обработки журнала не будет ни выделяться, ни освобождаться, а следовательно всем будет заниматься тот кто вызывает функцию. Эти данные актуальны только на этапе обработки сообщения и никоим образом не могут быть использованы после. А значит указатель будет ссылаться на достоверные данные. Позже скину пример использования.

Цитата

если хочешь портируемый код, то надо избавиться от не портируемого __closure. 

А чем заменить? Если просто убрать, то указатель будет на отдельную функцию, а мне надо на функцию класса.

Цитата

Мне кажется эта структура сильно избыточна, если знаешь имя ф-ии, то имя файла и номер строки знать не обязательно. 

В данном случае больше не меньше. Реальный вызов гораздо более компактный. И потом я планирую сделать браузер для логов, который позволит просматривать исходники ... если будет время добавлю поддержку компиляторов, чтобы файлы открывались именно в них (но это не скоро).
PM MAIL   Вверх
Mayk
Дата 23.11.2007, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

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



Цитата(Lazin @  23.11.2007,  20:33 Найти цитируемый пост)

так он же написал, что использует Borland?

Цитата(_Tanatos_ @  23.11.2007,  18:17 Найти цитируемый пост)
Макрос __FUNC__ пока не буду использовать, так как нет гарантий, что при смене компилятора работоспособность кода сохранится.

При использование __closure есть  работоспосбность кода при смене компилятора не сохранится вообще.

Цитата(_Tanatos_ @  23.11.2007,  20:38 Найти цитируемый пост)

А чем заменить? Если просто убрать, то указатель будет на отдельную функцию, а мне надо на функцию класса.

Цитата(Lazin @  23.11.2007,  20:33 Найти цитируемый пост)
а есть ли какая-нибудь портируемая вльтернатива __closure ?

boost::bind + boost::function, например. 

Цитата(_Tanatos_ @  23.11.2007,  20:38 Найти цитируемый пост)

Думаю использовать более 10 уровней детализации не имеет смысла ибо ни один программист не сможет в них свободно ориентироваться.

А если мне хочется нумеровать сообщения, начиная с 0x10000000[например сообщения из .exe], а в другом месте с 0x200000[например, сообщения из .dll]? или использование юзеровских типов не предусмотрено? а почему тогда не использовать enum? 

Цитата(Lazin @  23.11.2007,  20:33 Найти цитируемый пост)

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

ОпределенноХорошаяМысль.


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
_Tanatos_
Дата 23.11.2007, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

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


Принимается, добавлю. ТОлько распишите поподробней что имеется в виду под "возможность комбинировать"? Как себе представляете этот процесс. Какого типа хотелось бы видеть категорию?

Цитата

А чем заменить? Если просто убрать, то указатель будет на отдельную функцию, а мне надо на функцию класса.
а есть ли какая-нибудь портируемая вльтернатива __closure ?
boost::bind + boost::function, например.


Посмотрю - как разберусь исправлю. Спасибо за информацию!

Цитата

А если мне хочется нумеровать сообщения, начиная с 0x10000000[например сообщения из .exe], а в другом месте с 0x200000[например, сообщения из .dll]? или использование юзеровских типов не предусмотрено? а почему тогда не использовать enum?


Нет проблем, пользуйте m_Proc или m_Unit.
Кстати спрашивали насчет потоков ... под них так же планируется использовать m_Proc - ИМХО предостаточно.
Смысла писать туда реальный идентификатор потока не вижу, так как он от раза к разу меняется, можно его скинуть как данные при старте потока или процесса. А с логе использовать внутренние идентификаторы.

Цитата

а почему тогда не использовать enum? 

А зачем? Предполагаю использовать отрицательные значения для нескольких предопределенных значений, остальное на усмотрение программиста, так как никакой нагрузки смысловой (в пределах кода журнала) эти данные не несут - а значит и ограничивать нет смысла.
Пусть каждый сам разобьет на то количество уровней которое ему нужно, а для варианта по умолчанию уже есть enum но его можно или использовать или нет.
PM MAIL   Вверх
SaDFromSpb
Дата 23.11.2007, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(_Tanatos_ @  23.11.2007,  19:14 Найти цитируемый пост)
Предполагаю использовать отрицательные значения для нескольких предопределенных значений

Тогда, на всякий случай определи его как signed char, так как стандарт этого не гарантирует по умолчанию.

И давай скорее пример использования, а то так разбираться лениво  smile ...



--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
_Tanatos_
Дата 26.11.2007, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



На суд уважаемых форумчан выдвигается несколько вариантов решения с вложенностью, а именно

Вариант №1: (мне нравится больше всего) вложенность управляется при помощи параметра m_Level. Его изменение производится исключительно классом TtLibLogEngine. Командой для изменения служат зарезервированные значения типа сообщения m_Type:
-1 - Увеличиваем вложенность
-2 - Уменьшаем вложенность
Плюс данного решения в том, что нет необходимости вводить дополнительные переменные, функции и т.д., минус нельзя одновременно зафиксировать запись пользовательского типа с вложенностью.
Пример использования:
Код

...
    // Фрагмент из библтотеки
    lltBegin        = -1,
    lltComplete     = -2,
...
    // Фрагмент из кода программы, использующую библиотеку
void SomeFunction()
{
    // Первая строчка функции (при использовании макроса будет еще короче, но макросы на потом)
    g_LogEngine.RegisterMsg(0, 0, lltBegin, 0, "Начинаем важное дело ...", "None", "::SomeFunction", __FILE__, __LINE__);
    ...
    // Последняя строчка функции.
    g_LogEngine.RegisterMsg(0, 0, lltComplete, 0, "... Выполнено!", "None", "::SomeFunction", __FILE__, __LINE__);
}


Вариант №2: идентичен предыдущему варианту, но для управления вложенностью выделяется отдельные функции (можно конечно сделать и отдельный параметр, но уж больно много параметров). 
Пример использования:
Код

void SomeFunction()
{
    // Первая строчка функции (при использовании макроса будет еще короче, но макросы на потом)
    g_LogEngine.RegisterMsgBegin(0, 0, UserType, 0, "Начинаем важное дело ...", "None", "::SomeFunction", __FILE__, __LINE__);
    ...
    // Последняя строчка функции.
    g_LogEngine.RegisterMsgEnd(0, 0, UserType, 0, "... Выполнено!", "None", "::SomeFunction", __FILE__, __LINE__);
}


Вариант №3: Вынести управление в отдельную функцию, которая будет вызываться перед регистрацией сообщения и будет модифицировать одну последующую запись. ИМХО хуже из-за лишнего вызова, хотя можно сделать с модификатором inline.
Пример использования:
Код

void SomeFunction()
{
    // Первая строчка функции (при использовании макроса будет еще короче, но макросы на потом)
    g_LogEngine.Begin()
    g_LogEngine.RegisterMsg(0, 0, UserType, 0, "Начинаем важное дело ...", "None", "::SomeFunction", __FILE__, __LINE__);
    ...
    // Последняя строчка функции.
    g_LogEngine.End()
    g_LogEngine.RegisterMsg(0, 0, UserType, 0, "... Выполнено!", "None", "::SomeFunction", __FILE__, __LINE__);
}


--------------------

Предложение, насчет передачи имени класса и функции только один раз, отклюняю, так как:
1) Никто не мешает сделать это собственными силами. Объявляйте константы, ссылки или просто записывайте в лог один раз, а остальные записи оставляйте пустыми.
2) Как Вы себе представляете восстановление данных значений после выхода из вложенной функции???

--------------------

Цитата

Тогда, на всякий случай определи его как signed char

Принято.

Цитата

И давай скорее пример использования

На этой неделе будет выложен исходник с использованием.
Пока пишу библиотеку в перерывах (не многочисленных) между основной работой :(, так что сделано достаточно мало.
PM MAIL   Вверх
Lazin
Дата 26.11.2007, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(_Tanatos_ @  26.11.2007,  13:52 Найти цитируемый пост)
TtLibLogEngine. Командой для изменения служат зарезервированные значения типа сообщения m_Type:
-1 - Увеличиваем вложенность
-2 - Уменьшаем вложенность

Правильнее использовать rtti, создаешь в стеке объект, в конструкторе вызывается нужная функция(увеличивает вложенность), в деструкторе уменьшаем вложенность, а как передавать - детали. Нужно различать поток, из которого вызывается ф-я, и вычислять вложенность отдельно для каждого потока. Это можно сделать внутри TtLibLogEngine, при каждом вызове ф-ии получать ThreadId потока, и дальше вычислять для него степень вложенности.
Я зделал что то похожее, но у меня - просто надстройка над библиотекой ведения логов, которая немного форматирует текст.


Код

#ifndef LoggerH
#define LoggerH


#    include <windows.h>
#    include <map>
#    include "mydeb.h"

#    define myBASE_LOG_INDENT 1
#    define myMAX_DBG_LEVEL 7

///RAII класс для записи иерархии сообщений в лог
class Logger
{
protected:
    int        m_level;
    long    m_indent;
public:

    static int GetCurrentDbgLevel();

    Logger(const char* func_name, int lvl);

    ~Logger();

    void Write(const char* msg) const;
};

///Класс для записи заголовка лог-файла
class LogHeader
{
public:
    LogHeader(const char* msg);

    const LogHeader& operator () (const char* msg) const;

    const LogHeader& ModuleVersion (HINSTANCE inst) const;

    const LogHeader& ModuleVersion(const char* filename) const;
};

///    myMACRO
#    define LOG_FUNCTION_AT_LEVEL(l) Logger __my_log ( __FUNCSIG__, l);
#    define LOG_FUNCTION() Logger __my_log ( __FUNCSIG__, Logger::GetCurrentDbgLevel() );
#    define LOG_MESSAGE(s) __my_log.Write( (s) );

#endif




Код

#include "Logger.h"
#include <string>
#include <exception>

///mylog----------------------------------------------------------------------------------
class myLog
{
    friend class Logger;
    friend class LogHeader;
private:
    std::map<DWORD, long> indent_level;
    CRITICAL_SECTION lock;
public:
    myLog();

    ~myLog();
private:
    DWORD InitializeCurrentThreadContext();

    long GetIndentLevel();

    void Enter();

    void Leave();
    
    void Write(int level, const char* msg) const;

    void AddHeaderStr( const char* msg ) const;

    void AddVersionForInst(HINSTANCE inst) const;

    void AddVersionForName(const char* fname) const;
};


static oikLog s_log;


oikLog :: myLog() : indent_level()
{
    InitializeCriticalSection(&lock);
    InitializeCurrentThreadContext();
}

myLog :: ~myLog()
{
    DeleteCriticalSection(&lock);
}

DWORD myLog :: InitializeCurrentThreadContext()
{
    EnterCriticalSection(&lock);
    DWORD id = GetCurrentThreadId();
    if ( indent_level.find(id) == indent_level.end() )
    {
        indent_level[id] = myBASE_LOG_INDENT;
    }
    LeaveCriticalSection(&lock);
    return id;
}

long oikLog :: GetIndentLevel()
{
    DWORD id = InitializeCurrentThreadContext();
    EnterCriticalSection(&lock);
    long indent = indent_level[id];
    LeaveCriticalSection(&lock);
    return indent;
}

void oikLog :: Enter()
{
    DWORD id = InitializeCurrentThreadContext();
    EnterCriticalSection(&lock);
    indent_level[id]++;
    LeaveCriticalSection(&lock);
}

void oikLog :: Leave()
{        
    DWORD id = InitializeCurrentThreadContext();
    EnterCriticalSection(&lock);
    indent_level[id]--;
    LeaveCriticalSection(&lock);
}

void oikLog :: Write(int level, const char* msg) const
{
    DebugMsg( level, (LPSTR)msg );//запись в лог
}

void oikLog :: AddHeaderStr( const char* msg ) const
{
    AddHdrString( (LPSTR)msg );//запись в лог
}

void oikLog :: AddVersionForInst(HINSTANCE inst) const
{
    AddVerInfoHdrFoInstance(inst);//запись в лог
}

void oikLog :: AddVersionForName(const char* fname) const
{
    AddVerInfoHdrFoFileName((LPSTR)fname);//запись в лог
}


///logger----------------------------------------------------------------------------------
int Logger :: GetCurrentDbgLevel()
{
    long indent = s_log.GetIndentLevel();
    return (indent > myMAX_DBG_LEVEL) ? (int)myMAX_DBG_LEVEL : (int)indent;
}

Logger :: Logger(const char* func_name, int lvl) : m_level( lvl ), m_indent( s_log.GetIndentLevel() )
{
    Write(func_name);
    Write("{");
    s_log.Enter();
    m_indent = s_log.GetIndentLevel();
}

Logger :: ~Logger()
{
    if (std::uncaught_exception())
        Write("#return: stack unwinding");
    else
        Write("#return");
    s_log.Leave();
    m_indent--;
    Write("}");
}

void Logger :: Write(const char* msg) const
{
    std::string m;
    m.assign(m_indent*4, ' ');
    m.append(msg);
    s_log.Write(m_level, m.c_str());
}



///logheader-------------------------------------------------------------------------------
LogHeader :: LogHeader(const char* msg)
{
    s_log.AddHeaderStr(msg);
}

const LogHeader& LogHeader :: operator () (const char* msg) const
{
    s_log.AddHeaderStr(msg);
    return *this;
}

const LogHeader& LogHeader :: ModuleVersion (HINSTANCE inst) const
{
    s_log.AddVersionForInst(inst);
    return *this;
}

const LogHeader& LogHeader :: ModuleVersion(const char* filename) const
{
    s_log.AddVersionForName(filename);
    return *this;
}



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


Новичок



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

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



Цитата

Цитата
TtLibLogEngine. Командой для изменения служат зарезервированные значения типа сообщения m_Type:
-1 - Увеличиваем вложенность
-2 - Уменьшаем вложенность

Правильнее использовать rtti, создаешь в стеке объект, в конструкторе вызывается нужная функция(увеличивает вложенность), в деструкторе уменьшаем вложенность, а как передавать - детали. Нужно различать поток, из которого вызывается ф-я, и вычислять вложенность отдельно для каждого потока. Это можно сделать внутри TtLibLogEngine, при каждом вызове ф-ии получать ThreadId потока, и дальше вычислять для него степень вложенности.


Так оно и будет. Будет дополнительный класс CtLibLogHelper, который будет в конструкторе регистрировать сообщение с увеличением вложенности, а в деструкторе собщение с уменьшением вложенности.

За пример спасибо. Изучаю.
PM MAIL   Вверх
_Tanatos_
Дата 26.11.2007, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Lazin @  26.11.2007,  14:23 Найти цитируемый пост)
static int GetCurrentDbgLevel();


Выложи здесь реализацию данной функции?
Заранее благодарю!
PM MAIL   Вверх
Lazin
Дата 26.11.2007, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Lazin @  26.11.2007,  14:23 Найти цитируемый пост)
Код

///logger----------------------------------------------------------------------------------
int Logger :: GetCurrentDbgLevel()
{
    long indent = s_log.GetIndentLevel();
    return (indent > myMAX_DBG_LEVEL) ? (int)myMAX_DBG_LEVEL : (int)indent;
}

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

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


Новичок



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

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



Выкладываю предполагаемый вариант использования.
Обращаю внимание, что макросы пока не использую, дабы было понят но что есть что.
Не обращайте внимание на работу со строками, написал так для сокращения

Код

void CDocument::Save(const char* FileName)
{
      CtLibLogHelper LogHelper(ProcID, ThreadID, "CDocument::Save");
      LogHelper.Begin("Сохраняем документ...", "Имя файла: "+FileName, __FILE__, __LINE__);

      // Открываем файл
      LogHelper.Message(lltInfo, "Открываем файл", "", __FILE__, __LINE__);
      ...
      if(File == INVALID)
          LogHelper.Error(lltError, 134, "невозможно создать файл.", "", __FILE__, __LINE__);
      // Что-то пишем
      ...

      // Закрываем файл
      CloseHandle(File);
      LogHelper.Complete("... Готово!", "Записанно:"+Count+" строк", __FILE__, __LINE__);
}


В конструкторе класса CtLibLogHelper указываем идентификатор Процесса, потока и имя класса и функции - данные указываются один раз для одной функции. Соответственно все записи производятся через вспомогательный класс. Функция Error производит запись в журнал и сама генерирует исключение с указанным кодом (в данном случае 134).
PM MAIL   Вверх
Lazin
Дата 26.11.2007, 16:05 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(_Tanatos_ @  26.11.2007,  15:55 Найти цитируемый пост)
Функция Error производит запись в журнал и сама генерирует исключение с указанным кодом (в данном случае 134). 

Мне кажется это противоестественным. Пользователь класса вряд-ли будет расчитывать на то что писалка в лог кидает исключения. Не стоит смешивать подсистему обработки ошибок и подсистему записи в лог. Если к примеру ты захочешь убрать запись в лог, это приведет к изменению логики работы программы, а запись логов не должна на логику влиять.
PM MAIL Skype GTalk   Вверх
_Tanatos_
Дата 26.11.2007, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Lazin @ 26.11.2007,  16:05)
Цитата(_Tanatos_ @  26.11.2007,  15:55 Найти цитируемый пост)
Функция Error производит запись в журнал и сама генерирует исключение с указанным кодом (в данном случае 134). 

Мне кажется это противоестественным. Пользователь класса вряд-ли будет расчитывать на то что писалка в лог кидает исключения. Не стоит смешивать подсистему обработки ошибок и подсистему записи в лог. Если к примеру ты захочешь убрать запись в лог, это приведет к изменению логики работы программы, а запись логов не должна на логику влиять.

Согласен. Принято к изменению. 
PM MAIL   Вверх
_Tanatos_
Дата 26.11.2007, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(archimed7592 @ 21.11.2007,  12:01)
Цитата(Lazin @  21.11.2007,  11:54 Найти цитируемый пост)
 ~Logger()
 {
   s_log.write(current_node, "return");
 }

Я бы ещё добавил
Код
s_log.write(current_node, std::uncaught_exception() ? "return(stack unwinding)" : "return");

Попробовал - неработает!
после неудачи порылся в инете на предмет использования, вот такой пример не работает
Что делаю не так?


ИМХО лучше по старинке через флаг внутри класса и дополнительную функцию для его сброса.
Код

        if(m_Complete)
            g_LogEngine->RegisterMsg(...);
        else
            g_LogEngine->RegisterMsg(...);



PM MAIL   Вверх
Страницы: (5) Все 1 2 [3] 4 5 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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