Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/ДиагностикаОшибок.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@

- `КраткоеПредставление` возвращает компактную строку с текущим кадром и эффективной ошибкой.
- `ПользовательскоеПредставление` дополнительно выводит подсказку и URL текущего кадра.
- `ДиагностическоеПредставление` формирует полный отчёт по цепочке со стеком и данными.
- `ДиагностическоеПредставление` формирует отчёт по цепочке со стеком и данными.

Диагностическое представление предназначено для логов и отладки. Оно может раскрывать
пользовательские данные, места возникновения и стек вызовов; не передавайте в данные ошибки
Expand Down
2 changes: 1 addition & 1 deletion docs/ПредставлениеОшибок.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ URL:

## Диагностическое представление

`ДиагностическоеПредставление()` возвращает полный технический отчёт для логов и отладки.
`ДиагностическоеПредставление()` возвращает технический отчёт для логов и отладки.
Внешний кадр выводится первым, все промежуточные причины объединяются в блок `Причина`,
раскрываются `Данные` и добавляется общий стек вызовов первого физического кадра:

Expand Down
2 changes: 1 addition & 1 deletion docs/РазборОшибки.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@
.ДиагностическоеПредставление()
```

Возвращает полный диагностический отчёт с данными, всей цепочкой причин и стеком вызовов.
Возвращает диагностический отчёт с данными, цепочкой причин и стеком вызовов.

#### Возвращаемое значение

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,48 @@

КонецФункции

// Проверяет, является ли кадр внешней обёрткой повторного выброса.
// Такая обёртка не содержит собственных метаданных и дословно повторяет описание причины.
//
// Параметры:
// Ошибка - ИнформацияОбОшибке - Проверяемый кадр.
//
// Возвращаемое значение:
// Булево - Истина, если кадр не добавляет нового описания к непосредственной причине.
Функция ЭтоПовторныйВыброс(Ошибка) Экспорт

Причина = Неопределено;
Возврат ПопытатьсяПрочитатьПричинуПовторногоВыброса(Ошибка, Причина);

КонецФункции

// Возвращает первый кадр, не дублирующий описание непосредственной причины.
//
// Параметры:
// Ошибка - ИнформацияОбОшибке - Внешний кадр просматриваемой цепочки.
// КоличествоПросмотренныхКадров - Число - Выходной параметр количества кадров в общем бюджете обхода.
//
// Возвращаемое значение:
// ИнформацияОбОшибке - Исходный кадр или причина после пропуска повторных выбросов.
Функция ПропуститьПовторныеВыбросы(Ошибка, КоличествоПросмотренныхКадров = 1) Экспорт

ТекущийКадр = Ошибка;
КоличествоПросмотренныхКадров = 1;

Пока КоличествоПросмотренныхКадров < МаксимальноеКоличествоКадров() Цикл
Причина = Неопределено;
Если Не ПопытатьсяПрочитатьПричинуПовторногоВыброса(ТекущийКадр, Причина) Тогда
Возврат ТекущийКадр;
КонецЕсли;

ТекущийКадр = Причина;
КоличествоПросмотренныхКадров = КоличествоПросмотренныхКадров + 1;
КонецЦикла;

Возврат ТекущийКадр;

КонецФункции

// Возвращает первую распознанную ошибку при обходе от внешнего кадра к причине.
//
// Параметры:
Expand Down Expand Up @@ -249,6 +291,19 @@

#Область СлужебныеПроцедурыИФункции

Функция ПопытатьсяПрочитатьПричинуПовторногоВыброса(Ошибка, Причина)

Причина = Неопределено;
Если Ошибка.Параметры <> Неопределено
Или Не ПопытатьсяПрочитатьПричину(Ошибка, Причина)
Или Причина = Неопределено Тогда
Возврат Ложь;
КонецЕсли;

Возврат Ошибка.Описание = Причина.Описание;

КонецФункции

Функция НайтиПервыйКадр(Ошибка, УсловиеПоиска, ВидПоиска)

ТекущийКадр = Ошибка;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@

КонецФункции

// Формирует полный диагностический отчёт по просмотренным физическим кадрам.
// Формирует диагностический отчёт по просмотренным физическим кадрам без дублирующих транспортных обёрток.
//
// Параметры:
// Снимки - Массив из СнимокКадраОшибки - Снимки от внешнего кадра к корневому.
Expand Down Expand Up @@ -338,8 +338,17 @@
Новый Массив
);
Контексты = Новый Массив;
Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки();

Для НомерСнимка = 0 По Снимки.ВГраница() Цикл
Снимок = Снимки[НомерСнимка];
Если Снимок.Вид() = ВидыКадровОшибок.ВнешняяОшибка()
И НомерСнимка < Снимки.ВГраница()
И Обходчик.ЭтоПовторныйВыброс(Снимок.ИсходнаяОшибка())
И Снимок.ИсходнаяОшибка().Причина = Снимки[НомерСнимка + 1].ИсходнаяОшибка() Тогда
Продолжить;
КонецЕсли;

Для Каждого Снимок Из Снимки Цикл
Подсказка = Снимок.Подсказка();
Если Не ПустаяСтрока(Подсказка) Тогда
Результат.Подсказки.Добавить(Подсказка);
Expand Down
29 changes: 22 additions & 7 deletions src/Классы/РазборОшибки.os
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@

КонецФункции

// Возвращает полный диагностический отчёт.
// Возвращает диагностический отчёт.
//
// Возвращаемое значение:
// Строка - Семантические группы ошибки, контекстов и причин со стеком и данными.
Expand Down Expand Up @@ -304,28 +304,42 @@
Возврат;
КонецЕсли;

_СнимокПредставления = Новый СнимокКадраОшибки(_ИсходнаяОшибка);
ОшибкаПредставления = _ИсходнаяОшибка;
КоличествоПросмотренныхКадров = 1;
_СнимокПредставления = Новый СнимокКадраОшибки(ОшибкаПредставления);

Если _СнимокПредставления.Вид() = ВидыКадровОшибок.ВнешняяОшибка() Тогда
Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки();
ОшибкаПредставления = Обходчик.ПропуститьПовторныеВыбросы(
_ИсходнаяОшибка,
КоличествоПросмотренныхКадров
);
Если ОшибкаПредставления <> _ИсходнаяОшибка Тогда
_СнимокПредставления = Новый СнимокКадраОшибки(ОшибкаПредставления);
КонецЕсли;
КонецЕсли;

Если _СнимокПредставления.Вид() = ВидыКадровОшибок.Ошибка() Тогда
_КодЭффективнойОшибки = _СнимокПредставления.КодОшибки();
_СообщениеЭффективнойОшибки = _СнимокПредставления.Сообщение();
Иначе
ЗаполнитьЭффективнуюОшибку(
_ИсходнаяОшибка,
ОшибкаПредставления,
_КодЭффективнойОшибки,
_СообщениеЭффективнойОшибки
_СообщениеЭффективнойОшибки,
КоличествоПросмотренныхКадров
);
КонецЕсли;

КонецПроцедуры

Процедура ЗаполнитьЭффективнуюОшибку(Ошибка, КодОшибки, Сообщение)
Процедура ЗаполнитьЭффективнуюОшибку(Ошибка, КодОшибки, Сообщение, КоличествоПросмотренныхКадров = 1)

ТекущийКадр = Ошибка;
Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки();
Читатель = СервисыБиблиотекиОшибок.ЧитательКадраОшибки();

Для НомерКадра = 2 По Обходчик.МаксимальноеКоличествоКадров() Цикл
Для НомерКадра = КоличествоПросмотренныхКадров + 1 По Обходчик.МаксимальноеКоличествоКадров() Цикл
Причина = Неопределено;
Если Не Обходчик.ПопытатьсяПрочитатьПричину(ТекущийКадр, Причина)
Или Причина = Неопределено Тогда
Expand Down Expand Up @@ -371,7 +385,8 @@

Процедура ПодготовитьСнимок(Кадр, Ошибки)

Если Кадр = _ИсходнаяОшибка И _СнимокПредставления <> Неопределено Тогда
Если _СнимокПредставления <> Неопределено
И _СнимокПредставления.ИсходнаяОшибка() = Кадр Тогда
Снимок = _СнимокПредставления;
Иначе
Снимок = Новый СнимокКадраОшибки(Кадр);
Expand Down
2 changes: 1 addition & 1 deletion src/Модули/ДиагностикаОшибок.os
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@

КонецФункции

// Возвращает полный диагностический отчёт со стеком и данными ошибки.
// Возвращает диагностический отчёт со стеком и данными.
//
// Параметры:
// Ошибка - ИнформацияОбОшибке - Внешний кадр разбираемой цепочки.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Перем _Данные;
Перем _Подсказка;
Перем _URL;
Перем _ИсходнаяОшибка;
Перем _МестоСоздания;
Перем _СтекВызовов;

Expand All @@ -21,13 +22,16 @@
_Данные = ЗначениеСвойства(Параметры, "Данные", Неопределено);
_Подсказка = ЗначениеСвойства(Параметры, "Подсказка", "");
_URL = ЗначениеСвойства(Параметры, "URL", "");
_ИсходнаяОшибка = Новый ИнформацияОбОшибке(_Сообщение, Новый Структура);

МестоСоздания = Новый Структура(
"ИмяМодуля, НомерСтроки, ИсходнаяСтрока",
ЗначениеСвойства(Параметры, "ИмяМодуля", ""),
ЗначениеСвойства(Параметры, "НомерСтроки", 0),
ЗначениеСвойства(Параметры, "ИсходнаяСтрока", "")
);
_МестоСоздания = Новый ФиксированнаяСтруктура(МестоСоздания);

_СтекВызовов = Новый Массив;
Для Каждого Элемент Из ЗначениеСвойства(Параметры, "Стек", Новый Массив) Цикл
_СтекВызовов.Добавить(Элемент);
Expand All @@ -39,6 +43,16 @@

#Область ПрограммныйИнтерфейс

// Возвращает исходный физический кадр.
//
// Возвращаемое значение:
// ИнформацияОбОшибке - Тестовый исходный кадр.
Функция ИсходнаяОшибка() Экспорт

Возврат _ИсходнаяОшибка;

КонецФункции

// Возвращает вид кадра.
//
// Возвращаемое значение:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@

КонецФункции

// Дважды повторно выбрасывает ошибку из разных мест исходного кода.
//
// Параметры:
// Ошибка - ИнформацияОбОшибке - Повторно выбрасываемая ошибка.
//
// Возвращаемое значение:
// Структура:
// * Ошибка - ИнформацияОбОшибке - Результат второго повторного выброса;
// * ВнутренняяОшибка - ИнформацияОбОшибке - Результат первого повторного выброса.
Функция ДваждыПовторноВыброшеннаяОшибка(Ошибка) Экспорт

ВнутренняяОшибка = ПовторныйВыбросНаПервомУровне(Ошибка);
Ошибка = ПовторныйВыбросНаВторомУровне(ВнутренняяОшибка);

Возврат Новый Структура("Ошибка, ВнутренняяОшибка", Ошибка, ВнутренняяОшибка);

КонецФункции

// Создаёт кадр с повреждённым конвертом без обязательного поля Данные.
//
// Параметры:
Expand Down Expand Up @@ -184,6 +202,26 @@

#Область СлужебныеПроцедурыИФункции

Функция ПовторныйВыбросНаПервомУровне(Ошибка)

Попытка
ВызватьИсключение Ошибка;
Исключение
Возврат ИнформацияОбОшибке();
КонецПопытки;

КонецФункции

Функция ПовторныйВыбросНаВторомУровне(Ошибка)

Попытка
ВызватьИсключение Ошибка;
Исключение
Возврат ИнформацияОбОшибке();
КонецПопытки;

КонецФункции

Функция ВнешняяОшибкаНаПервойСтроке()

Попытка
Expand Down
56 changes: 56 additions & 0 deletions tests/ТестыПредставленияОшибок.os
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,62 @@

#Область Тесты

&Тест
Процедура ТестДолжен_НеДублироватьПредставленияПослеДвухПовторныхВыбросов() Экспорт

// Подготовка
Ошибка = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения");
Цепочка = ПомощникТестированияОшибок.ДваждыПовторноВыброшеннаяОшибка(Ошибка);
Ошибка = Цепочка.Ошибка;
ВнутренняяОшибка = Цепочка.ВнутренняяОшибка;

// Действие
Разбор = ДиагностикаОшибок.Разобрать(Ошибка);
ПользовательскоеПредставление = Разбор.ПользовательскоеПредставление();
КраткоеПредставление = Разбор.КраткоеПредставление();
ДиагностическоеПредставление = Разбор.ДиагностическоеПредставление();
СтруктурированноеПредставление = Разбор.ВСтруктуру();

// Проверка
Ожидаем.Что(КраткоеПредставление).Равно("storage.read_failed: Ошибка чтения");
Ожидаем.Что(ПользовательскоеПредставление).Равно("storage.read_failed: Ошибка чтения");
Ожидаем.Что(Разбор.Снимки().Количество()).Равно(2);
Ожидаем.Что(Разбор.Снимки()[0].ИсходнаяОшибка()).Равно(Ошибка);
Ожидаем.Что(Разбор.Снимки()[1].ИсходнаяОшибка()).Равно(ВнутренняяОшибка);
Ожидаем.Что(СтруктурированноеПредставление.Цепочка.Количество()).Равно(2);
Ожидаем.Что(СтрЧислоВхождений(
ДиагностическоеПредставление,
"storage.read_failed: Ошибка чтения"
)).Равно(1);
Ожидаем.Что(ДиагностическоеПредставление).ЭтоНе().Содержит("Причина:");
Ожидаем.Что(ДиагностическоеПредставление).Содержит("Стек вызовов:");
Ожидаем.Что(ДиагностическоеПредставление).Содержит("ПовторныйВыбросНаВторомУровне");

КонецПроцедуры

&Тест
Процедура ТестДолжен_СохранитьВнешнийКадрССовпадающимОписаниемИСобственнымиПараметрами() Экспорт

// Подготовка
Причина = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения");
Ошибка = ПомощникТестированияОшибок.ВнешняяОшибка(Причина.Описание, Причина);

// Действие
КраткоеПредставление = ДиагностикаОшибок.КраткоеПредставление(Ошибка);
ДиагностическоеПредставление = ДиагностикаОшибок.ДиагностическоеПредставление(Ошибка);

// Проверка
Ожидаем.Что(КраткоеПредставление).Равно(
"storage.read_failed: storage.read_failed: Ошибка чтения -> Ошибка чтения"
);
Ожидаем.Что(СтрЧислоВхождений(
ДиагностическоеПредставление,
"storage.read_failed: Ошибка чтения"
)).Равно(2);
Ожидаем.Что(ДиагностическоеПредставление).Содержит("Причина:");

КонецПроцедуры

&Тест
Процедура ТестДолжен_ВернутьКраткоеПредставлениеТекущегоКадра() Экспорт

Expand Down
Loading
Loading