Журнал событий

Журнал событий предназначен для регистрации событий, которые может анализировать пользователь приложения, например, администратор. Журнал фиксирует ход работы с приложением и его данными как на уровне системных событий (реализованных в «1С:Шине»), так и на уровне прикладных событий, реализованных как в «1С:Шине», так и в приложении.

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

Особенности работы

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

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

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

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

Пример использования журнала событий

метод ПримерИспользования()
    исп Контекст = ЖурналСобытий.ЗарегистрироватьНачалоОперации("ДлительнаяОперация", УровеньСобытия.Информация)
    ...
    ЖурналСобытия.Зарегистрировать("Событие", УровеньСобытия.Предупреждение, {"Описание": "Значение"})
    ...
    // В проекте можно реализовать фабрику событий, которая будет наполнять события обязательными свойствами
    // А по месту мы расширим свойства нужными значениями
    пер НовоеСобытие = СоздатьСобытие("Событие").УстановитьСвойство("ЕщеСвойство", 10)
    ЖурналСобытий.Зарегистрировать(НовоеСобытие)
;
 
метод СоздатьСобытие(Имя: Строка)
    возврат новый ОписаниеСобытия("Событие", УровеньСобытия.Предупреждение)
        .УстановитьСвойство("Автор", МенеджерПользователей.ТекущийПользователь.ЗагрузитьОбъект().Имя)
        .УстановитьСвойство("Подсистема", "ПодсистемаДляПримера")
;

Операции, иерархия событий

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

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

Операции могут быть длительными или короткими. Журнал может работать только с операциями выполняемыми в рамках одного серверного вызова. Распределенные операции не поддерживаются — нельзя начать операцию и запустить фоновое задание в котором эта операция будет завершена.

«1С:Шина» поддерживает иерархию событий. Все события, кроме события начала серверного вызова и окончания серверного вызова регистрируются в контексте некоторой операции. Если разработчик не создавал никаких операций, то они будут зарегистрированы в контексте операции серверного вызова.

Пример иерархии событий, зарегистрированных через вложенные операции:

исп Контекст1 = ЖурналСобытий.ЗарегистрироватьНачалоОперации("Операция1", УровеньСобытия.Информация)
исп Контекст2 = ЖурналСобытий.ЗарегистрироватьНачалоОперации("Операция2", УровеньСобытия.Информация)
ЖурналСобытий.Зарегистрировать("Событие", УровеньСобытия.Информация);

В результате будут зарегистрированы события из которых можно построить иерархию, используя свойство Событие._Родитель):

  • Операция1
    • Операция2
      • Событие
    • КонецОперации2
  • КонецОперации1

Еще одна особенность операций — возможность автоматической регистрации ошибок и маркировки операций как неудачные.

исп Операция = ЖурналСобытий.ЗарегистрироватьНачалоОперации("Операция1", УровеньСобытия.Информация)
    ...
выбросить новый ИсключениеВыполенния("Пояснения")

В результате выполнения такого кода в журнал попадут:

  • Операция1
    • ИсключениеВыполнения с описанием "Пояснения"
  • Операция1 с признаком Событие._Успешно = Ложь

Исключения не глушатся и их нужно обрабатывать все равно.

попытка
    исп Операция = ЖурналСобытий.ЗарегистрироватьНачалоОперации("Операция1", УровеньСобытия.Информация)
    ...
    выбросить новый ИсключениеВыполенния("Пояснения")
поймать Искл: Исключение
    // Заглушили исключение, но в журнал оно все равно попадет, т.к. операция Операция1 была прервана по исключению
;

Пример поиска событий, произошедших в контексте операции:

// записываются события двух вложенных операций
пер Контекст = ЖурналСобытий.RegisterStartOperation("Операция1", УровеньСобытия.Информация)
пер Оп1Ид = Контекст.Id
пер Оп2Ид = ""
область
    исп Контекст2 = ЖурналСобытий.RegisterStartOperation("Операция2", УровеньСобытия.Информация)
    Контекст2.ЗарегистрироватьОшибку(новый ОписаниеСобытия("Событие1", УровеньСобытия.Информация))
    Контекст2.ЗарегистрироватьОшибку(новый ОписаниеСобытия("Событие2", УровеньСобытия.Информация))
    Оп2Ид = Контекст2.Id
;
Контекст.Закрыть()
 
// поиск событий, зарегистрированных в операции1 и операции2
пер Запрос = новый Запрос("Выбрать * Из ЖурналСобытий Где Cast(_Operations As String).Contains(\"" + Оп1Ид + "\")")
пер Количество = 0
исп Рез = Запрос.Выполнить()
пока Рез.Следующий()
    Количество += 1
;
// ожидается Количество == 4:
//     открытие Контекст2
//     2 события-ошибки
//     закрытие Контекст2

Системные события

Автоматически регистрируются следующие системные события:
  • TransactionResult.Commit — успешное завершение транзакции.
  • TransactionResult.Rollback — отмена транзакции.

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

Таблица журнала событий в языке запросов.