Введение
Появившаяся необходимость выгрузки ошибок из 1С в Sentry была обусловлена потребностью удобного мониторинга ошибок и пользовательского опыта вне 1С. Такая потребность возникла у одного крупного клиента компании "Эм Си Арт", для которого нужно было придумать решение. Сложилась следующая ситуация: в службу технической поддержки регулярно поступали обращения с жалобами на скорость работы 1С, а в силу отсутствия мониторинга пользовательского опыта расследование инцидентов было затруднено, также нельзя было отследить динамику улучшения/ухудшения работы системы. Для решения описанных проблем был выбран Sentry.
В вопросе реализации выгрузки ошибок статья не несет глобальной новизны (все статьи по данной тематике перечислены в списке источников), но представленное решение имеет свое исполнение. Схожая и полезная статья[1] на эту тему написана Владиславом Журавским, за что автору огромная благодарность. Помимо мониторинга ошибок, Sentry предоставляет возможность расчета такого показателя, как Apdex, суть которого будет описана далее. Было решено воспользоваться, в том числе, и данным функционалом Sentry, что уже более ново в контексте интеграции 1С и Sentry (во всяком случае, по данной теме сходу материалов найти не удалось).
Рассматриваемое решение может быть неидеальным, но оно работоспособно и дает определенный функционал. В статье подробно пояснены не все тонкости разработки решения, а только наиболее важные (по мнению автора).
Что такое Sentry
Sentry - инструмент для сбора и анализа ошибок. Есть возможность указания большого количества дополнительной информации для каждой ошибки: пользователь, окружение, клиент и сервер и многое другое. Процесс создания проекта в Sentry рассматриваться не будет, как и процесс получения DSN токена, эта информация есть в статье [1].

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

Рисунок 2. Пример списка событий для расчета Apdex в Sentry
На данном рисунке проиллюстрирован список событий для расчета Apdex. APDEX (Application Performance Index) — это индекс производительности, который отражает, насколько пользователи удовлетворены скоростью работы информационной системы[2]. Есть возможность внутри каждого события увидеть список событий данного типа (с возможностью раскрыть информацию о конкретном событии), а также ознакомиться с графиками Apdex и длительности события в различные временные промежутки. Это продемонстрировано на рис. 3.
Рисунок 3. Пример списка событий конкретного вида для расчета Apdex в Sentry
На данном рисунке можно увидеть некоторую техническую информацию в разрезе процентного соотношения от общего количества таких событий. Например, окружение (прод, стейдж или тест), операционную систему и имя компьютера.
Рисунок 4. Пример данных конкретного события для расчета Apdex в Sentry
На рисунке выше продемонстрированы данные, полученные для конкретного события. Указаны даты начала и окончания события в Unix формате в стандарте UTC в миллисекундах, длительность в миллисекундах, пользователь, база, версии платформы и конфигурации и т.д. Т.к. в примере использованы данные для события открытия формы списка справочника сотрудников, то у пользователя (пользователя Sentry) есть подробная информация о том, когда и у кого была открыта упомянутая форма, как быстро открылось окно и другая полезная информация.
Реализация интеграции на стороне 1С
Как и для большинства доработок в 1С, было принято решение воспользоваться дополнительным расширением. Главным преимуществом применения доп. расширений при доработках в 1С является отсутствие необходимости снимать основную конфигурацию с поддержки. Кроме того расширение крайне просто установить в нужную базу или несколько баз. В расширение были добавлены некоторые объекты и есть несколько заимствованных из основной конфигурации.
Были добавлены 3 общих модуля: sentry_Синхронизация, sentry_RestApi, sentry_ОбщегоНазначенияСервер. Подсистема sentry_Интеграция. Роль sentry_ОсновнаяРоль для настройки прав доступа к расширению. Общая картинка для упомянутой подсистемы. Справочник НастройкиСинхронизацииСsentry для настройки интеграции. И 3 системных перечисления: sentry_РежимыРаботы, sentry_УровниЖурналаРегистрации, sentry_Окружение. Заимствованные объекты: справочник КлючевыеОперации и РС (регистр сведений) ЗамерыВремени.
Для справочника НастройкиСинхронизацииСsentry были добавлены следующие реквизиты:
- Сервер (Строка) - хранит адрес Sentry для обмена данными;
- Токен (Строка) - хранит токен Sentry для обмена данными;
- НомерПроекта (Строка) - хранит идентификатор проекта Sentry для обмена данными;
- ЗащищенноеСоединение (Булево) - признак защищенного соединения;
- Порт (Строка) - номер порта при обмене данными;
- ОбменЗапущен (Булево) - признак того, что обмен с Sentry запущен;
- ИдентификаторФоновогоЗадания (УникальныйИдентификатор) - идентификатор текущего выполняемого фонового задания для данной настройки интеграции;
- РежимРаботы (ПеречислениеСсылка.sentry_РежимыРаботы) - хранит режим работы для данной настройки. Доступны значения: ПолнаяВыгрузка, ВыгрузкаЗаПериод, ВыгружатьТолькоНовыеПослеЗапускаОбмена;
- НачалоПериодаЖурналРегистрации (Дата) - дата начала выгрузки данных об ошибках при режиме работы ВыгрузкаЗаПериод;
- ОкончаниеПериодаЖурналРегистрации (Дата) - дата окончания выгрузки данных об ошибках при режиме работы ВыгрузкаЗаПериод;
- ВыгружатьЖурналРегистрации (Булево) - признак того, необходимо выгружать ошибки;
- ВыгружатьЗамерыВремени (Булево) - признак того, необходимо выгружать замеры времени;
- НачалоПериодаЗамерыВремени (Дата) - дата начала выгрузки данных о замерах времени при режиме работы ВыгрузкаЗаПериод;
- ОкончаниеПериодаЗамерыВремени (Дата) - дата окончания выгрузки данных о замерах времени при режиме работы ВыгрузкаЗаПериод;
- Окружение (ПеречислениеСсылка.sentry_Окружение) - информация об окружении, доступные значения: Прод, Стейдж, Тест.
Дополнительно была добавлена табличная часть с единственным реквизитом УровеньЖурналаРегистрации (ПеречислениеСсылка.sentry_УровниЖурналаРегистрации) с возможными значениями: Ошибка, Предупреждение, Информация, Примечание. Табличная часть необходима для возможности указания пользователем типа информации выгружаемой из журнала регистрации.
Важный момент про Сервер, Токен и НомерПроекта будет раскрыт далее. Для данного справочника были созданы 3 формы: ФормаЭлемента, ФормаСписка, ФормаВыполнениеСинхронизации. На рис. 5 продемонстрирована форма элемента справочника.
Рисунок 5. Форма настройки в 1С интеграции с Sentry
Назначение полей формы можно понять из описания реквизитов выше. На форме присутствуют кнопки запуска и выключения обмена, а также кнопка проверки соединения с Sentry. Элементы формы отображаются в зависимости от необходимости их отображения. Эта логика отражена в модуле формы.
Модуль формы
ФормаЭлемента справочника
НастройкиСинхронизацииСsentry
#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьОтображениеЭлементовФормы(Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
УжеЕстьТакаяНастройка = ПроверитьНастройкуНаДубль(Объект.Ссылка, Объект.Сервер, Объект.Токен, Объект.НомерПроекта);
Если УжеЕстьТакаяНастройка Тогда
ОбщегоНазначенияКлиент.СообщитьПользователю("Настройка с такими параметрами уже существует. Создать еще одну нельзя.");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
ОбновитьФормуСписка();
ОбновитьОтображениеЭлементовФормы();
КонецПроцедуры
#КонецОбласти
#Область КомандыФормы
&НаКлиенте
Процедура УдалитьНастройку(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияВопросаОбУдалении", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Настройка обмена будет удалена. Продолжить?",РежимДиалогаВопрос.ДаНет, 0);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСоединение(Команда)
Ошибка = Ложь;
Если НЕ ЗначениеЗаполнено(Объект.Сервер) Тогда
Ошибка = Истина;
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не заполнен адрес sentry.");
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Объект.Токен) Тогда
Ошибка = Истина;
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не заполнен токен.");
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Объект.Токен) Тогда
Ошибка = Истина;
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не заполнен номер проекта.");
КонецЕсли;
Если НЕ Ошибка Тогда
Если СоединениеУстановленоУспешно() Тогда
ОбщегоНазначенияКлиент.СообщитьПользователю("Соединение с ресурсом " + Объект.Сервер + " установлено успешно.");
Иначе
ОбщегоНазначенияКлиент.СообщитьПользователю("Соединение с ресурсом " + Объект.Сервер + " не установлено.");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВыключитьОбмен(Команда)
ВыключитьОбменНаСервере();
ОбновитьФормуСписка();
ОбновитьОтображениеЭлементовФормы();
КонецПроцедуры
&НаКлиенте
Процедура ЗапуститьОбмен(Команда)
Если sentry_ОбщегоНазначенияСервер.РасширениеВБезопасномРежиме() Тогда
ПоказатьПредупреждение(, "Расширение модуля в безопасном режиме. Продолжение невозможно", 10);
Возврат;
КонецЕсли;
Если ЗапуститьОбменНаСервере() Тогда
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("НастройкаОбмена", Объект.Ссылка);
ПараметрыФормы.Вставить("Родитель", Объект.Ссылка);
ОбновитьФормуСписка();
ОбновитьОтображениеЭлементовФормы();
Оповещение = Новый ОписаниеОповещения("ОбновитьФормуИФормуСписка", ЭтотОбъект);
ОткрытьФорму("Справочник.НастройкиСинхронизацииСsentry.Форма.ФормаВыполнениеСинхронизации", ПараметрыФормы, , Объект,,, Оповещение);
Иначе
ОбновитьФормуСписка();
ОбновитьОтображениеЭлементовФормы();
КонецЕсли;
КонецПроцедуры
#КОнецОбласти
#Область УдалениеНастройки
// Продолжение УдалитьНастройку.
//
&НаКлиенте
Процедура ПослеЗакрытияВопросаОбУдалении(Результат, Параметры) Экспорт
Если Результат = КодВозвратаДиалога.Нет Тогда
Возврат;
Иначе
УдалитьНастройкуСервер(Объект.Ссылка);
ЭтаФорма.Закрыть();
ОбновитьФормуСписка();
КонецЕсли;
КонецПроцедуры
// Удалаяет элемент справочника НастройкиСинхронизации.НастройкиСинхронизацииСsentry.
//
// Параметры:
// НастройкаОбмена - СправочникСсылка.НастройкиСинхронизацииСsentry - содержит ссылку на настройку обмена.
//
&НаСервереБезКонтекста
Процедура УдалитьНастройкуСервер(НастройкаОбмена)
УстановитьПривилегированныйРежим(Истина);
НастройкаОбмена.ПолучитьОбъект().Удалить();
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
#КонецОбласти
#Область ВключениеВыключениеОбмена
// Инициализирует выполнение обмена.
//
&НаСервере
Функция ЗапуститьОбменНаСервере()
Если НЕ Объект.ВыгружатьЖурналРегистрации И НЕ Объект.ВыгружатьЗамерыВремени Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не выбраны данные для выгрузки.");
Возврат Ложь;
КонецЕсли;
Если НЕ Объект.РежимРаботы = Перечисления.sentry_РежимыРаботы.ВыгружатьТолькоНовыеПослеЗапускаОбмена Тогда
Если Объект.РежимРаботы = Перечисления.sentry_РежимыРаботы.ВыгрузкаЗаПериод
И (((НЕ ЗначениеЗаполнено(Объект.НачалоПериодаЖурналРегистрации) ИЛИ НЕ ЗначениеЗаполнено(Объект.ОкончаниеПериодаЖурналРегистрации))
И Объект.ВыгружатьЖурналРегистрации)
ИЛИ ((НЕ ЗначениеЗаполнено(Объект.НачалоПериодаЗамерыВремени) ИЛИ НЕ ЗначениеЗаполнено(Объект.ОкончаниеПериодаЗамерыВремени))
И Объект.ВыгружатьЗамерыВремени)) Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не заполнены периоды выгрузки.");
Возврат Ложь;
КонецЕсли;
Объект.ОбменЗапущен = Истина;
ЭтотОбъект.Записать();
Возврат Истина;
Иначе
НайденноеФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Объект.ИдентификаторФоновогоЗадания);
Если НайденноеФоновоеЗадание = Неопределено
ИЛИ НЕ НайденноеФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
Объект.ОбменЗапущен = Истина;
ЭтотОбъект.Записать();
Объект.ИдентификаторФоновогоЗадания = ЗапуститьВРежимеРеальногоВремениВФоне();
КонецЕсли;
ЭтотОбъект.Записать();
КонецЕсли;
Возврат Ложь;
КонецФункции
// Производит запуск обмена в режиме рального времени и возращает идентификатор фонового задания.
//
// Возвращаемое значение:
// УникальныйИдентификатор - если статус задания = "Выполняется", то содержит идентификатор запущенного фонового задания.
//
&НаСервере
Функция ЗапуститьВРежимеРеальногоВремениВФоне()
ПараметрыСинхронизации = Новый Структура;
ПараметрыСинхронизации.Вставить("НастройкаОбмена" , Объект.Ссылка);
УстановитьПривилегированныйРежим(Истина);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Выполнение синхронизации с sentry'");
ПараметрыВыполнения.ОжидатьЗавершение = 0.1;
ФоновоеЗадание = ДлительныеОперации.ВыполнитьВФоне("sentry_Синхронизация.ВыполнитьОбменДаннымиВРежимеРеальногоВремениПоФоновомуЗаданию",
ПараметрыСинхронизации, ПараметрыВыполнения);
Возврат ФоновоеЗадание.ИдентификаторЗадания;
КонецФункции
// Изменяет реквизиты ОбменЗапущен и ИдентификаторФоновогоЗадания.
//
&НаСервере
Процедура ВыключитьОбменНаСервере()
Объект.ОбменЗапущен = Ложь;
Объект.ИдентификаторФоновогоЗадания = Неопределено;
ЭтотОбъект.Записать();
КонецПроцедуры
#КонецОбласти
#Область ОбновлениеФормИЭлементовФормы
// Обновляет формы элемента и списка справочника НастройкиСинхронизацииСsentry.
//
&НаКлиенте
Процедура ОбновитьФормуИФормуСписка(Результат, ДополнительныеПараметры) Экспорт
ОбновитьФормуСписка();
ОбновитьОтображениеЭлементовФормы();
КонецПроцедуры
// Обновляет форму списка справочника НастройкиСинхронизацииСsentry.
//
&НаКлиенте
Процедура ОбновитьФормуСписка()
ФормаСписка = ПолучитьФорму("Справочник.НастройкиСинхронизацииСsentry.Форма.ФормаСписка");
ФормаСписка.Элементы.Список.Обновить();
КонецПроцедуры
// Обновляет видимость элемнтов формы.
//
// Параметры:
// Открытие - Булево - признак того, что форма была только что открыта.
//
Процедура ОбновитьОтображениеЭлементовФормы(Открытие=Ложь)
Если Объект.Ссылка.Пустая() И Открытие Тогда
Элементы.ГруппаОбменЗапущен.Видимость = Ложь;
Элементы.ВыключитьОбмен.Видимость = Ложь;
Иначе
DSN = "https://" + Объект.Токен + "@" + Объект.Сервер + "/" + объект.НомерПроекта;
Если Объект.ОбменЗапущен Тогда
Элементы.ГруппаОбменЗапущен.Видимость = Истина;
Элементы.ОбменЗапущен.Видимость = Истина;
Элементы.ОбменЗапущенНадпись.Видимость = Истина;
Элементы.ОбменНеЗапущен.Видимость = Ложь;
Элементы.ОбменНеЗапущенНадпись.Видимость = Ложь;
Элементы.ЗапуститьОбменВРеальномВремени.Видимость = Ложь;
Элементы.ВыключитьОбмен.Видимость = Истина;
Иначе
Элементы.ГруппаОбменЗапущен.Видимость = Истина;
Элементы.ОбменЗапущен.Видимость = Ложь;
Элементы.ОбменЗапущенНадпись.Видимость = Ложь;
Элементы.ОбменНеЗапущен.Видимость = Истина;
Элементы.ОбменНеЗапущенНадпись.Видимость = Истина;
Элементы.ЗапуститьОбменВРеальномВремени.Видимость = Истина;
Элементы.ВыключитьОбмен.Видимость = Ложь;
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(Объект.Токен) И ЗначениеЗаполнено(Объект.Сервер) И ЗначениеЗаполнено(Объект.НомерПроекта) Тогда
Элементы.ПроверитьСоединение.Доступность = Истина;
Элементы.ПроверитьСоединение.ОтображениеПодсказки = ОтображениеПодсказки.Нет;
Элементы.ЗапуститьОбменВРеальномВремени.Доступность = Истина;
Иначе
Элементы.ПроверитьСоединение.Доступность = Ложь;
Элементы.ПроверитьСоединение.ОтображениеПодсказки = ОтображениеПодсказки.Кнопка;
Элементы.ЗапуститьОбменВРеальномВремени.Доступность = Ложь;
КонецЕсли;
Если Объект.РежимРаботы = Перечисления.sentry_РежимыРаботы.ВыгрузкаЗаПериод Тогда
Если Объект.ВыгружатьЖурналРегистрации Тогда
Элементы.ГруппаПериодЖурналРегистрации.Видимость = Истина;
Иначе
Элементы.ГруппаПериодЖурналРегистрации.Видимость = Ложь;
КонецЕсли;
Если Объект.ВыгружатьЗамерыВремени Тогда
Элементы.ГруппаПериодЗамерыВремени.Видимость = Истина;
Иначе
Элементы.ГруппаПериодЗамерыВремени.Видимость = Ложь;
КонецЕсли;
Иначе
Элементы.ГруппаПериодЖурналРегистрации.Видимость = Ложь;
Элементы.ГруппаПериодЗамерыВремени.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовФормы
&НаКлиенте
Процедура DSNПриИзменении(Элемент)
ПозицияПоследнегоСлеша = СтрНайти(Элемент.ТекстРедактирования, "/", НаправлениеПоиска.СКонца,,1);
ПозицияСобаки = СтрНайти(Элемент.ТекстРедактирования, "@");
Объект.Токен = Сред(Элемент.ТекстРедактирования, 9, ПозицияСобаки - 9);
Объект.Сервер = Сред(Элемент.ТекстРедактирования, ПозицияСобаки + 1, ПозицияПоследнегоСлеша - (ПозицияСобаки + 1));
Объект.НомерПроекта = Сред(Элемент.ТекстРедактирования, ПозицияПоследнегоСлеша + 1);
Объект.ЗащищенноеСоединение = Истина;
Объект.Порт = 443;
ОбновитьОтображениеЭлементовФормы();
КонецПроцедуры
&НаКлиенте
Процедура РежимРаботыПриИзменении(Элемент)
ОбновитьОтображениеЭлементовФормы();
КонецПроцедуры
&НаКлиенте
Процедура ВыгружаемыеУровниЖурналаРегистрацииПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
Если Объект.ВыгружаемыеУровниЖурналаРегистрации.Количество() > 1 Тогда
ДобавленнаяСтрокаТЧ = Объект.ВыгружаемыеУровниЖурналаРегистрации[Объект.ВыгружаемыеУровниЖурналаРегистрации.Количество()-1];
ЗначениеДобавленнойСтрокиТЧ = ДобавленнаяСтрокаТЧ.УровеньЖурналаРегистрации;
Дубли = Объект.ВыгружаемыеУровниЖурналаРегистрации.НайтиСтроки(Новый Структура("УровеньЖурналаРегистрации", ЗначениеДобавленнойСтрокиТЧ));
Если Дубли.Количество() > 1 Тогда
Сообщить("Этот уровень журнала регистрации уже добавлен.");
Объект.ВыгружаемыеУровниЖурналаРегистрации.Удалить(ДобавленнаяСтрокаТЧ);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область Прочее
// Проверяет, есть ли еще элементы справочника НастройкиСинхронизацииСsentry
// с такими же значениями реквизитов Сервер, НомерПроекта, Токен.
//
// Параметры:
// Ссылка - СправочникСсылка.НастройкиСинхронизацииСsentry - содержит ссылку на настройку.
// Сервер - Строка - содержит адрес sentry.
// Токен - Строка - содержит токен для sentry.
// НомерПроекта - Строка - содержит номер проекта sentry.
//
// Возвращаемое значение:
// Булево - если Истина, значит элемент с такими реквизитами уже существует.
//
Функция ПроверитьНастройкуНаДубль(Ссылка, Сервер, Токен, НомерПроекта)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НастройкиСинхронизацииСsentry.Ссылка КАК Ссылка
|ИЗ
| Справочник.НастройкиСинхронизацииСsentry КАК НастройкиСинхронизацииСsentry
|ГДЕ
| НастройкиСинхронизацииСsentry.Ссылка <> &Ссылка
| И НастройкиСинхронизацииСsentry.Токен = &Токен
| И НастройкиСинхронизацииСsentry.НомерПроекта = &НомерПроекта
| И НастройкиСинхронизацииСsentry.Сервер = &Сервер";
Запрос.УстановитьПараметр("Сервер", Сервер);
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("Токен", Токен);
Запрос.УстановитьПараметр("НомерПроекта", НомерПроекта);
УстановитьПривилегированныйРежим(Истина);
РезультатЗапроса = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если РезультатЗапроса.Пустой() Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
// Проверяет успешность установления соединения с ресурсом. Также сообщает пользователю
// о наличии некоторых ошибок.
//
// Возвращаемое значение:
// Булево - если соединение было установлено, возвращает Истина, иначе Ложь.
//
&НаСервере
Функция СоединениеУстановленоУспешно()
СистемнаяИнформация = Новый("СистемнаяИнформация");
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Дата", ТекущаяДатаСеанса());
СтруктураДанных.Вставить("Транзакция", "");
СтруктураДанных.Вставить("РабочийСервер", sentry_ОбщегоНазначенияСервер.ПолучитьСерверИнформационнойБазы());
СтруктураДанных.Вставить("Комментарий", "");
СтруктураДанных.Вставить("ПредставлениеМетаданных", "");
СтруктураДанных.Вставить("ПредставлениеСобытия", "Проверка установки соединения");
СтруктураДанных.Вставить("Компьютер", "");
СтруктураДанных.Вставить("ИмяПриложения", "");
СтруктураДанных.Вставить("ПредставлениеПриложения", "");
СтруктураДанных.Вставить("ПредставлениеДанных", "");
СтруктураДанных.Вставить("сеанс", "");
СтруктураДанных.Вставить("ВерсияПриложения", СистемнаяИнформация.ВерсияПриложения);
СтруктураДанных.Вставить("соединение", "");
СтруктураДанных.Вставить("ИмяПользователя", Строка(Пользователи.ТекущийПользователь()));
СтруктураТестовойОшибки = sentry_ОбщегоНазначенияСервер.СформироватьТелоСообщенияSentry(СтруктураДанных, "Информация", sentry_ОбщегоНазначенияСервер.ПолучитьОкружение(Объект.Окружение));
ДанныеСSentry = sentry_RestApi.ОтправкаДанных(sentry_Синхронизация.СформироватьСтруктуруНастроек(Объект.Ссылка), СтруктураТестовойОшибки, Истина);
Если ЗначениеЗаполнено(ДанныеСSentry) Тогда
КодСостояния = ДанныеСSentry.Получить("КодСостояния");
Если НЕ ЗначениеЗаполнено(КодСостояния) Тогда
Возврат Ложь;
Иначе
Если КодСостояния = 200 Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
#КонецОбласти
Необходимо упомянуть важные аспекты работы модуля выше. Добавлена проверка создания дублирующих настроек интеграции (функция ПроверитьНастройкуНаДубль), т.е. нет возможности создать несколько подключений к одному и тому же проекту одного и того же Sentry. Есть возможность проверки установки соединения с Sentry путем отправки тестовой ошибки. Формирование и процесс отправки данных об ошибке будет описан позже. Элементы формы, которые не нужны при текущих настройках скрываются и вновь отображаются при соответствующих настройках, все это описано в процедуре ОбновитьОтображениеЭлементовФормы. У пользователя есть возможность указывать различные уровни журнала регистрации, т.е. без дублей, что отражено в обработчике события формы ВыгружаемыеУровниЖурналаРегистрацииПередОкончаниемРедактирования. Также все изменения формы в результате своих действий пользователь будет видеть сразу и форму не надо обновлять или использовать кнопку записи.
Стоит более подробно описать работу с DSN токеном. Он состоит из 3-х частей: токена, адреса Sentry и идентификатор проекта(в представленном коде переменная названа НомерПроекта).
Шаблон DSN токена: https://<токен>@<адрес Sentry>/<идентификатор проекта>.
Пример DSN токена: https://4df6cc9d87bgw6363353c051e23d@sentry.mycompany.ru/46.
По коду модуля формы видно, что при окончании редактирования DSN токена пользователем он разделяется на указанные выше части и записывается в соответствующие реквизиты.
Выгрузка данных в Sentry во всех трех режимах происходит с помощью фонового задания, т.е. пользователю не нужно ждать, пока все данные выгрузятся в Sentry, он может и дальше работать с 1С. Для режимов ПолнаяВыгрузка и ВыгрузкаЗаПериод используется форма ФормаВыполнениеСинхронизации, чтобы выводить пользователю информацию о ходе выгрузки данных. Сейчас выводятся только 2 сообщения: о начале и об окончании выгрузки данных. При необходимости логирование можно дополнить. Для режима работы ВыгружатьТолькоНовыеПослеЗапускаОбмена эта форма не используется, т.к. без выключения обмена пользователем этот процесс нельзя считать конечным, также не имеет смысла на глазах у пользователя логировать процессы неизвестной длительности. На рис. 6 представлена форма ФормаВыполнениеСинхронизации справочника НастройкиСинхронизацииСsentry.

Рисунок 6. Форма выполнения синхронизации с Sentry
Модуль формы
ФормаВыполнениеСинхронизации справочника
НастройкиСинхронизацииСsentry
#Область ОбработчикиСобытий
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
НастройкаОбмена = Параметры.НастройкаОбмена;
Родитель = Параметры.Родитель;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ЗапуститьВыполнениеОбмена", 0.1, Истина);
ПодключитьОбработчикОжидания("ОбновлениеИнформацииОбмена", 1);
КонецПроцедуры
#КонецОбласти
#Область Обмен
// Инициализирует выполнение обмена данными.
//
&НаКлиенте
Процедура ЗапуститьВыполнениеОбмена()
ДобавитьЕдиничнуюЗаписьВПротокол("Начало обмена");
ПараметрыОбмена = Новый Структура;
ПараметрыОбмена.Вставить("НастройкаОбмена" , НастройкаОбмена);
ДлительнаяОперация = ВыполнитьОбменСSentryНаСервере(ПараметрыОбмена);
ИдентификаторЗадания = ДлительнаяОперация.ИдентификаторЗадания;
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
ОписаниеОпове
Проверено на следующих конфигурациях и релизах:
- Зарплата и управление персоналом, редакция 3.1, релизы 3.1.30.108
Вступайте в нашу телеграмм-группу
Инфостарт
1С мониторинг ошибок показатели производительности пользовательский опыт интеграция Sentry