Параметризованные исключения. Лог со скрытыми именами функци
От: RaGod  
Дата: 07.09.06 07:14
Оценка:
Добрый день.
Хотелось бы услышать предложения и мнения форумчан по следующей теме.

Упрощенно идея в следующем : есть класс CSomeClass. В некоторых своих методах он кидает исключение.
Исключение представляется собой класс CSomeException.
class CSomeException
{
Public :
CString m_csMsg, m_csDescr, m_csSource;

CSomeException ( CString csMsg, CString csDescr, CString csSource )
{
M_csMsg = csMsg;
M_csDescr = csDescr;
M_csSource = csSource;
}
};


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

CString csErr;
csErr.Format( “Can’t parse file : %s, with option : %d”, csFile, iProm );
throw CSomeException( csErr, “Some description”, “CSomeClass::SomeMethod”)

Теперь задача усложнилась.
Необходимо :

1. Поддерживать многоязычные ошибки. Следовательно нельзя их забивать жестко в коде. Причем мы должны разделить текст ошибки, который выводиться пользователю и текс, который выводиться в лог. Т.е. например пользователю показывается ошибка на китайском, но в лог она пишется на инглиш.

Вопрос – как правильно эти ошибки параметризовать.

2. Необходимо в логе скрыть имя функции. Т.е. вместо этого писать ее id, а уже потом при анализе лога самим конвертировать этот id в имя функции.

Вопрос – как лучше всего задать соответствие между именем функции и ее id

Я сделал так :

1. Для поддержки многоязычности я использую ресурс StringTable. Теперь в конструктор CSomeException передается не строки, а id сообщения и id описания ошибки. Класс сам конвертит эти id в строки ошибки из соотв. языку StringTabl-а. Причем одна копия таких строк на языке пользователя, а вторая на англ. Языке для записи в лог.
В принципе все вроде хорошо, да только сообщения могут иметь параметры разных типов. Я добавил в констуктор CSomeException возможность принимать кроме идентификаторов ошибок еще неопредел. количество аргументов. и с помощью функции CString::FormatV заганять их в сообщения

Т.е. например пусть в StringTAble таблице для пользователей и для лога есть строки

IDS_SOME_MSG “Some msg with string param : %s, and int param : %s”
IDS_SOME_DESCR “Some descr”

Мы кидаем Exception примерно так
throw CSomeException( IDS_SOME_MSG, IDS_SOME_DESCR, “FuncName”, “String param”, 20 );


Конструктор класса исключения :
CSomeException( DWORD dwMsg, DWORD dwDescr, CString csFuncName, ….)
{
  CString csProm;
  Va_list arg;

  // Заполняем сообщения для пользователя
  Va_start( arg, csFuncName );
  csProm.LoadString( dwMsg );// считываем строку из STringTable для юзера
  m_csMsgUser.FormatV( csProm, arg );// форматируем строку переданными параметрами
  va_end( arg );
  ……….

  // Заполняем сообщения для лога
  Va_start( arg, csFuncName );
  csProm.LoadString( NULL, dwMsg );// считываем строку из STringTable Для лога
  m_csMsgLog.FormatV( csProm, arg );// форматируем строку переданными параметрами
  va_end( arg );
}


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

2. Что касается скрытия в логах имен функций. Я использую вместо имен идентификаторы.
Вопрос как наилучшим образом поставить в соотв-е функцию и ее идентификатор.
Для этого я создал отдельную resource-only dll. В которой также есть ресурс StringTable (в этом ресурсе строки идентифицируются своими айдишниками). Соотв. я добавляю строку с имененм функции в таблицу а в лог вывожу id этой строки

Например в ресурсе есть запись

IDS_SOME_FUNC “CSomeClass::SomeFunc”

В Resource.h определяется идентификатор
#define IDS_SOME_FUNC 1001

В свою программу я подключаю только Resource.h и оперирую идентификаторами (например IDS_SOME_FUNC) Вместо имени функции.

Для чтения лога используется отдельная прога. Она уже подключает саму ресурсную dll
И подставляет вместо идентификаторов значения строк (т.е. имена функций).

Т.о. коненчный вариант конструктора CSomeException :

CSomeException( DWORD dwMsgId, DWORD dwSourceId, DWORD dwFuncId, … )


Кидаем так :


throw CSomeException( IDS_MSG, IDS_DESCR, IDS_FUNC, stParam1, intParam2);


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

Буду очень признателен если кто-то поделиться своим способ обработки подобных ситуаций и даст совет.

Зарание спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.