Логирование в 1С удобно делать через собственный регистр сведений: в нём хранятся только нужные события (этапы обмена, шаги сложного алгоритма, ошибки), с привязкой к объекту и признаком ошибки. Такой журнал быстро фильтруется, по нему строятся отчёты и рассылки, а старые записи чистятся регламентным заданием. Штатный журнал регистрации при этом не отменяется — он остаётся источником для ошибок внутри транзакций.
Свой журнал я делаю, когда ошибка воспроизводится редко и поймать её отладчиком нельзя, когда нужно показывать пользователям историю обмена по документу или когда поддержке нужен ежедневный отчёт «что упало ночью».
Журнал регистрации или свой регистр: что выбрать
| Критерий | Журнал регистрации | Свой регистр сведений |
|---|---|---|
| Доработка конфигурации | Не нужна | Нужен регистр и общий модуль (можно в расширении) |
| Что попадает | Все события платформы и ваши ЗаписьЖурналаРегистрации | Только то, что вы записали |
| Отбор по объекту | Есть, но неудобен для массового анализа | Обычный отбор, запрос, отчёт на СКД |
| Откат при ошибке транзакции | Записи сохраняются | Записи откатываются вместе с транзакцией |
| Доступ пользователям | Обычно только администраторам | Можно дать через роли |
| Очистка | Настройками журнала для всей базы | Своим заданием по своим правилам |
Вывод простой: для разового расследования хватит ЗаписьЖурналаРегистрации со своим именем события. Для постоянного контроля обменов и бизнес-алгоритмов нужен свой журнал.
Структура регистра сведений для логов
Регистр делаю непериодическим, с независимым режимом записи. Период нельзя использовать как ключ: две записи в одну секунду по одному объекту перезапишут друг друга.
| Поле | Вид | Тип | Назначение |
|---|---|---|---|
| ИдентификаторЗаписи | Измерение | УникальныйИдентификатор | Уникальность каждой записи |
| Дата | Ресурс | Дата (дата и время) | Время события |
| Момент | Ресурс | Число (15,0) | Миллисекунды для точной сортировки |
| Событие | Ресурс | ПеречислениеСсылка.СобытияЖурнала | Какой алгоритм или обмен |
| Объект | Ресурс | Составной / Строка | Ссылка на объект или внешний идентификатор |
| Описание | Ресурс | Строка (неограниченная) | Что произошло |
| Ошибка | Ресурс | Булево | Признак ошибки |
| ОписаниеОшибки | Ресурс | Строка (неограниченная) | Подробности |
| Пользователь | Ресурс | Строка | Имя пользователя сеанса |
Для поля Событие чаще беру перечисление: список алгоритмов фиксирован и попадает в код через Перечисления.СобытияЖурнала.ОбменССайтом. Если события должны добавлять без программиста — справочник.
Для Дата, Событие и Объект включите индексирование: именно по ним будут отборы.
Процедура записи в журнал
Код записи — в серверном общем модуле, а не в модуле менеджера регистра: так его проще вызывать и переносить в расширение.
// Добавляет запись в журнал событий интеграций и алгоритмов.
//
// Параметры:
// Событие - ПеречислениеСсылка.СобытияЖурнала - источник записи.
// Объект - ЛюбаяСсылка, Строка - объект, к которому относится событие.
// Описание - Строка - что произошло.
// ЭтоОшибка - Булево - признак ошибки.
// ОписаниеОшибки - Строка - подробности ошибки.
//
Процедура ДобавитьЗапись(Событие, Объект, Описание, ЭтоОшибка = Ложь, ОписаниеОшибки = "") Экспорт
МенеджерЗаписи = РегистрыСведений.ЖурналСобытий.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторЗаписи = Новый УникальныйИдентификатор;
МенеджерЗаписи.Дата = ТекущаяДатаСеанса();
МенеджерЗаписи.Момент = ТекущаяУниверсальнаяДатаВМиллисекундах();
МенеджерЗаписи.Событие = Событие;
МенеджерЗаписи.Объект = Объект;
МенеджерЗаписи.Описание = Описание;
МенеджерЗаписи.Ошибка = ЭтоОшибка;
МенеджерЗаписи.ОписаниеОшибки = ОписаниеОшибки;
МенеджерЗаписи.Пользователь = ИмяПользователя();
Попытка
МенеджерЗаписи.Записать();
Исключение
// Лог не должен ронять основной алгоритм.
ЗаписьЖурналаРегистрации("ЖурналСобытий.ОшибкаЗаписи", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Если ЭтоОшибка И ТранзакцияАктивна() Тогда
// Запись в регистр откатится вместе с транзакцией, журнал регистрации — нет.
ЗаписьЖурналаРегистрации("ЖурналСобытий." + Строка(Событие), УровеньЖурналаРегистрации.Ошибка, ,
Объект, Описание + Символы.ПС + ОписаниеОшибки);
КонецЕсли;
КонецПроцедурыДва момента, на которых обычно спотыкаются:
- Привилегированный режим. Если у пользователя нет прав на регистр, запись упадёт. Сделайте общий модуль привилегированным или дайте роль на добавление записей.
- Транзакции. Всё, что записано в регистр внутри транзакции, исчезнет при её откате — вместе с самой полезной информацией об ошибке. Поэтому выше ошибка дублируется в журнал регистрации.
Как расставлять записи в алгоритме
Логируйте этапы, а не каждую строку. Хорошая гранулярность — начало, ключевые шаги, результат и ошибки.
Процедура ВыгрузитьЗаказНаСайт(Заказ) Экспорт
Событие = Перечисления.СобытияЖурнала.ОбменССайтом;
ЖурналСобытий.ДобавитьЗапись(Событие, Заказ, "Начало выгрузки");
Попытка
Пакет = СформироватьПакетЗаказа(Заказ);
ЖурналСобытий.ДобавитьЗапись(Событие, Заказ, СтрШаблон("Пакет сформирован, строк: %1", Пакет.Товары.Количество()));
ОтветСервиса = ОтправитьПакет(Пакет);
ЖурналСобытий.ДобавитьЗапись(Событие, Заказ, СтрШаблон("Ответ сервиса: %1", ОтветСервиса.КодСостояния));
Исключение
ЖурналСобытий.ДобавитьЗапись(Событие, Заказ, "Выгрузка прервана", Истина,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыПосле ВызватьИсключение ошибка не теряется для вызывающего кода, а в журнале остаётся шаг, на котором всё сломалось.

Отчёт по ошибкам и рассылка
Раз данные лежат в регистре, отчёт на СКД собирается за несколько минут: отбор по периоду, событию и признаку ошибки, группировка по событию и объекту. В конфигурациях на БСП его можно поставить в рассылку отчётов — ответственный каждое утро получает список упавших обменов. Если БСП нет, достаточно регламентного задания, которое выбирает ошибки за сутки и отправляет письмо.
ВЫБРАТЬ
Журнал.Событие КАК Событие,
Журнал.Объект КАК Объект,
Журнал.Дата КАК Дата,
Журнал.ОписаниеОшибки КАК ОписаниеОшибки
ИЗ
РегистрСведений.ЖурналСобытий КАК Журнал
ГДЕ
Журнал.Ошибка
И Журнал.Дата >= &НачалоПериода
УПОРЯДОЧИТЬ ПО
Журнал.МоментОчистка старых записей
Без очистки лог за год вырастет до размеров основных данных. Регламентное задание раз в сутки:
Процедура ОчиститьЖурналСобытий() Экспорт
ГраницаХранения = ТекущаяДатаСеанса() - 90 * 86400;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| Журнал.ИдентификаторЗаписи КАК ИдентификаторЗаписи
|ИЗ
| РегистрСведений.ЖурналСобытий КАК Журнал
|ГДЕ
| Журнал.Дата < &ГраницаХранения";
Запрос.УстановитьПараметр("ГраницаХранения", ГраницаХранения);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НаборЗаписей = РегистрыСведений.ЖурналСобытий.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ИдентификаторЗаписи.Установить(Выборка.ИдентификаторЗаписи);
НаборЗаписей.Записать();
КонецЦикла;
КонецПроцедурыПорция в 10 000 записей за запуск не держит долгих блокировок. Срок хранения лучше вынести в константу.
Итог
- Свой журнал на регистре сведений — точечное логирование нужных событий с удобными отборами и отчётами.
- Ключ — уникальный идентификатор, а не период: иначе записи в одну секунду затирают друг друга.
- Ошибки внутри транзакций дублируйте в журнал регистрации — регистр откатится.
- Логируйте этапы, а не каждую строку, и чистите журнал регламентным заданием.
Если обменов много и разбирать их ошибки некому, это стоит закрыть в рамках сопровождения 1С; сам журнал и отчёт по нему — небольшая доработка 1С.




