Решено Обработка ошибок, логгирование, трейсинг и юнит-тестинг

kolka

Member
16.02.2013
8
0
#1
Хочу поделиться библиотеками для обработки ошибок, логгирования, отслеживания выполнения кода и тестирования компонентов (unit testing). Навеяно жавой и обидой отсутствия подобного в LS.
Код на гитхабе:
Для просмотра контента необходимо: Войти или зарегистрироваться
Описание смотрите в README.

Есть дальнейшие идеи развития, но по времени самостоятельная реализация может сильно затянуться в связи с загрузкой. Если есть желающие - присоединяйтесь!

В списке идей:
- отвязать управление логгированием от кода, т.е. переключение в режим debug для выбранного модуля делать без изменения кода (через UI, notes.ini или т.п)
- сделать логгирование в файл в стандартном формате, понимаемом существующими анализаторами логов
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#2
напишу сюда...
Есть код, кот. содержит обработчики, есть класс, в кот. определены действия на Delete...
в это ф-ции вызывается метод с "пропуском" ошибки
Код:
Function IsArrayInitialized(arr) As Boolean
    Dim routineName As String
    routineName="IsArrayInitialized"
    On Error GoTo ErrH
    'your code here
    Dim intTemp As Integer
    On Error GoTo Continue
    intTemp = UBound(arr)
    IsArrayInitialized = True
    If false Then
Continue:
        Resume Quit
    End If
Quit:
    Exit Function
ErrH:
    'Error Err,
    RaiseError
    Resume Quit
End Function
по понятным причинам, при возникновении ошибки - я получу "не ту" что являлась источником
т.е. класс дестроится, при ошибке в коде, и в ходе этой процедуры перебивается ошибка вызвавшая процесс
что можно сделать? - прописать явно номер ошибки в обработчик?
 

kolka

Member
16.02.2013
8
0
#3
По порядку,
1. Это лишнее:
Код:
    Dim routineName As String
    routineName="IsArrayInitialized"
Заменяется GetThreadInfo( LSI_THREAD_PROC )
Код:
GetThreadInfo(1)
2. Проверку массива на пустоту можно так сделать:
Код:
Function isArrayInitialized( arr As Variant ) As Boolean
    isArrayInitialized = False
    On Error GoTo catch
 
    Dim intTemp As Integer
    intTemp = UBound( arr )
    isArrayInitialized = True
 
    GoTo finally
catch:
    Resume finally
finally:
End Function
И я бы сюда никакой другой функциональности не добавлял.
3. Если есть необходимость использования подобной функции в обработчике другой ошибки, т.е. основная ошибка была получена ДО вызова проверки массива на инициализацию, то в вызывающем методе в самом начале сохраняются данные об ошибке (Error, Err, Erl), а потом проводится дальнейшая обработка. Пример можно найти в LS DL в classOverloadFactory:
Код:
Function classOverloadFactory( argClassName As String ) As Variant
    On Error Resume Next
 
    Dim sError As String
    sError = Error
    Dim iErr As Integer
    iErr = Err
 
    Set classOverloadFactory = Nothing
    If IsElement( gl_overloadClassNames( argClassName ) ) Then
        Set classOverloadFactory = classInstanceFactory( gl_overloadLibraryNames( argClassName ), gl_overloadClassNames( argClassName ) )
        Execute {use "} & gl_overloadLibraryNames( argClassName ) & {"
Call } & gl_overloadLibraryNames( argClassName ) & {_init()}
    End If
 
    If Not ( Err = iErr And Error = sError ) Then
        If Not ( "" = sError And 0 = iErr ) Then
            Error iErr, sError
        End If
    End If
End Function
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#4
Заменяется GetThreadInfo( LSI_THREAD_PROC )
не заменяется! это поддержка отображения "нужного имени" при изменениях (и внесено в шаблон формирования ф-ций, в ДД)
оставлено именно для такой фичи
в обработчике ошибок уже есть GetThread...
Если есть необходимость
об этом и пост...
как описал - происходит в деструкторе класса, кот. может быть вызван и при ошибке в коде
собственно - это попытка сохранить произведенные действия (до ошибки) и иметь более-менее целостное состояние "связанных" документов
а расстраивает убиение реальной ошибки (в логах-то трейс осядет, но юзеру высветит фигню)
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#5
то в вызывающем методе в самом начале сохраняются данные об ошибке (Error, Err, Erl)
это все понятно, только хочется иметь это на базе обработчика, т.е. библиотеку обработки ошибок допилить к-л образом...
свой велик есть (для обработки ошибок, но без указанной фичи), а в тырнетах вменяемого не находил
 

kolka

Member
16.02.2013
8
0
#6
Я правильно понимаю сценарий?
Код:
    Dim arr as Variant

    On Error GoTo catch
 
    'основная ошибка где-то тут
 
    GoTo finally
catch:
    Dim msg As String
    msg = "Array initialized: " & isArrayInitialized( arr ) 'вот тут стек убивается
    throwExceptionDetailed msg
finally:
Задачка. Надо подумать. Хотя, решение остается тем же:
Код:
    Dim arr as Variant

    On Error GoTo catch
 
    'основная ошибка где-то тут
 
    GoTo finally
catch:
    Dim sError As String
    sError = Error
    Dim iErr As Integer
    iErr = Err
 
    Dim msg As String
    msg = "Array initialized: " & isArrayInitialized( arr ) 'вот тут стек убивается
 
    On Error Resume Next
    If Not ( Err = iErr And Error = sError ) Then
        If Not ( "" = sError And 0 = iErr ) Then
            Error iErr, sError
        End If
    End If
 
    On Error Goto 0
    throwExceptionDetailed msg
finally:
Написанное выше не тестировал...
Вопрос как засунуть в обработчик. Напрашивается внутреннее хванилище для запоминания ошибки. Но тогда потребуется дополнительно метод для сброса запомненной ошибки. Как ни крути неудобно.
Выходом вижу только расширение с добавлением двух методов:
Код:
Sub saveExceptionState()
Sub throwSavedException( msg As String )
Вариант?

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#7
@kolka похожий сценарий...
беда в "разнесении" кода, будет вопрос - где ставить saveExceptionState()