Пост

Сервис регистрации ошибок 1С (пример создания)

Разработаем вместе простой сервис регистрации ошибок для 1С на самой 1С =)


Введение

Сегодня продолжим рассматривать новый механизм платформы по отображения ошибок в 1С.

Ранее я показывал, как это в базе 1С выглядит со стороны пользователя, администратора и разработчика. А сегодня поговорим о сервисе регистрации ошибок.

Данная статья - текстовый вариант свежего видеоролика по теме.

Что это такое? Это некий опубликованный http-сервис, на который автоматически будут отправляться возникающие у пользователей ошибки. Сервис будет их принимать, обрабатывать и хранить. А ответственные за разбор ошибок люди будут далее просматривать накопленные данные.

На чём мы это будем делать? Естественно, на 1С! И начнём прямо сейчас.

Для начала создадим новую базу для разработки. Назовём её “Сервис регистрации ошибок”. Запускать её будем с версией 8.3.17. Так же сразу для удобства я сделаю себе хранилище разработки. И теперь можно разрабатывать.

Разработка HTTP-сервиса

Первое, что нам нужно в базе - создать новый HTTP-сервис. Назовём его “Основной Сервис”. Укажем корневой URL. Пусть будет “main”.

Скрин

Теперь нам нужно добавить новый шаблон URL. Назовём его ПолучитьИнформацию. И в шаблоне укажем “/getInfo”. Добавим в шаблон новый метод POST-метод с таким же названием и сразу создадим для него обработчик.

Скрин

Но для работы сервиса нам нужен ещё один метод. Создадим новый шаблон URL и назовём его “ОтправитьОтчет”. Шаблон у него будет “/pushReport”. Аналогично прошлому шаблону, создадим POST-метод с обработчиком.

Скрин

Публикация сервиса

В данном видео мы не будем рассматривать процесс установки сервера, публикации базы и так далее. По этой теме есть множество информации и публикация нашего сервиса ничем не отличается от других. По разворачиванию сервера могу посоветовать видео на канале Ильи Низамова. Лично я делал по этому видео: https://nizamov.school/server-1s-apache-ustanovka-apache/

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

Смотрим на метод getInfo()

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

Скрин

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

Скрин

Мы сейчас находимся в отладке на методе “ПолучитьИнформацию” (“getInfo”). Давайте посмотрим, что нам пришло в запросе. Для этого выполним метод Запрос.ПолучитьТелоКакСтроку().

Скрин

Что мы видим? Этим запросом 1С говорит нам информацию о себе. Какая конфигурация, какая платформа и версия приложения. И далее 1С ожидает ответа от этого первого метода. Нужно ли действительно отправлять на сервис регистрации текущую ошибку? Давайте теперь сделаем так, чтобы наш метод отвечал “да”.

Разработка метода getInfo()

Я подготовил простую функцию, которая поможет нам в этом. Она нужна для преобразования значений 1С в JSON.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Возвращает значение в виде JSON-строки.
// Преобразованы в JSON-строку (сериализованы) могут быть только те объекты,
// для которых в описании указано, что они сериализуются.
//
// Параметры:
//   Значение - Произвольный. Значение, которое необходимо сериализовать в JSON-строку.
//
// Возвращаемое значение:
//   Строка - JSON-строка представления значения в сериализованном виде.
//
Функция ЗначениеВСтрокуJSON(Значение) Экспорт
	
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, Значение);
	
	Возврат ЗаписьJSON.Закрыть();
	
КонецФункции

Теперь создадим структуру ДанныеОтвета. В неё будем помещать передаваемые в качестве ответа данные. Комментарии к свойствам я буду брать из ИТС.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Функция ПолучитьИнформацию(Запрос)
	
	ДанныеОтвета = Новый Структура;
	
	//данная ошибка должна быть отправлена в сервис регистрации
	ДанныеОтвета.Вставить("needSendReport", Истина); 
	
	//Текст, который будет показан пользователю в качестве дополнительной информации об ошибке (подробнее см. здесь). 
	//https://its.1c.ru/db/v8317doc#bookmark:dev:TI000002261
	//Текст желательно возвращать на том языке, который будет понятен пользователю. 
	//Информацию о локализации можно получить из запроса, который поступает в метод getInfo.
	//Если желательно, чтобы пользователь отправил отчет о конкретной ошибке в сервис регистрации ошибок, 
	//то с помощью данного свойства можно показать пользователю рекомендацию, мотивирующую на отправку отчета об ошибке.
	ДанныеОтвета.Вставить("userMessage", "Чем быстрее разработчик узнает об ошибке, тем скорее она будет исправлена =)");
	
	//тип дампа, который нужно приложить к отчету об ошибке (аналогичен значению атрибута type элемента dump файла logcfg.xml)
	ДанныеОтвета.Вставить("dumpType", 1);
	
	
	ДанныеОтветаСтрокой = ЗначениеВСтрокуJSON(ДанныеОтвета);
	
	Ответ = Новый HTTPСервисОтвет(200);
	
	Ответ.УстановитьТелоИзСтроки(ДанныеОтветаСтрокой);
	
	Возврат Ответ;
	
КонецФункции

needSendReport - Булево.

Этот параметр говорит 1С, нужно ли дальше отправлять отчет об ошибке или сервис отказывается его принимать. В нашем случае всегда будет “Да”.

UserMessage - Строка

В этот параметр можно передать текст, который будет показан пользователю в качестве дополнительной информации. Мы сюда поместим мотивирующую строку

“Чем быстрее разработчик узнает об ошибке, тем скорее она будет исправлена =)”

Так же есть ещё свойство dumpType - это тип дампа, который необходимо приложить к отчету об ошибке. Его мы сейчас рассматривать не будем.

Когда данные готовы, мы можем отправить их в качестве ответа. Но для начала нужно преобразовать их в JSON. Для этого и понадобится та функция, которую я показывал ранее.

Метод getInfo готов.

Обновим базу и снова сымитируем ошибку.

Мы в отладке. Посмотрим, как выглядят данные, которые мы даём в качестве ответа.

Скрин

И её строковый вариант в формате JSON.

Скрин

Смотрим метод pushReport()

В окне об ошибке мы видим нашу мотивирующую строку. Это значит, что метод getInfo сработал корректно и 1С готова к отправке отчета об ошибке.

Скрин

Добавим в него комментарий пользователя и нажмём “Отправить”.

Скрин

Теперь мы в отладке на методе “ОтправитьОтчет” (“pushReport”). Посмотрим содержимое объекта “Запрос”. Сначала попробуем выполнить метод ПолучитьТелоКакСтроку().

Скрин

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

Скрин

Это и есть необходимый нам файл. И, фактически, наша цель достигнута - мы создали сервис, который получает отчёты об ошибках пользователей. Но пока что никак их не обрабатываем.

Разработка метода pushReport()

И так, мы на входе имеем двоичные данные с архивом, в котором содержится нужная нам информация. Очевидно, что нам нужно её извлечь, обработать и сохранить в базе. Но мы не будем делать это сразу. Потому что на это может потребоваться время. В которое 1С будет ожидать ответа от сервиса. Так что длительные операции мы будем выполнять после. А в самом методе http-сервиса будем просто складывать полученные данные в специальный регистр. Такая запись потребует минимум времени. Не нагружает сервис регистрации ошибок, и при этом гарантирует сохранность данных.

Для начала добавим регистр сведений. Каждый отчёт об ошибке будет сохранён в отдельную запись регистра. Добавим измерение. Значение в нём должно быть максимально уникальным, ведь запросы могут происходить часто. Поэтому сделаем его типом “УникальныйИдентификатор”. Можно, конечно, сделать строковый тип с длиной достаточной для идентификатора, но мы же делаем просто прототип и сейчас не будем заморачиваться в таких тонкостях.

Скрин

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

Скрин

Теперь создадим методы для работы с регистром. Перейдём в его модуль менеджера. Вставим для красоты “стандартный” БСПшный текст с директивами и областями.

И создадим экспортную процедуру ДобавитьЗапись(). Входными параметрами будут данные отчёта и идентификатор. При этом второй необязательный - если не передавать, то его значение будет автоматически генерироваться. Внутри метода будет создаваться и записываться новая запись регистра.

А так же процедуру по удалению записи регистра. Она нам понадобится позднее

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

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

Процедура ДобавитьЗапись(Содержимое, Идентификатор = Неопределено, Дата = Неопределено) Экспорт
	
	МенеджерЗаписи = РегистрыСведений.ПолученныеОтчетыОбОшибках.СоздатьМенеджерЗаписи();
	МенеджерЗаписи.Активность    = Истина;
	МенеджерЗаписи.Идентификатор = ?(Идентификатор = Неопределено, Новый УникальныйИдентификатор, Идентификатор);
	МенеджерЗаписи.Содержимое    = Содержимое;
	МенеджерЗаписи.Дата          = ?(Дата = Неопределено, ТекущаяДата(), Дата);
	МенеджерЗаписи.Записать(Истина);
	
КонецПроцедуры

Процедура УдалитьЗапись(Идентификатор) Экспорт
	
	МенеджерЗаписи = РегистрыСведений.ПолученныеОтчетыОбОшибках.СоздатьМенеджерЗаписи();
	МенеджерЗаписи.Идентификатор = Идентификатор;
	МенеджерЗаписи.Прочитать();
	МенеджерЗаписи.Удалить();
	
КонецПроцедуры

#КонецОбласти

#КонецЕсли

Вернёмся в метод http-сервиса. Сначала получим двоичные данные из входящего запроса. Это и есть наш файл. Запакуем его в хранилище значения и передадим в наш новый метод регистра сведений. Ответ менять не будем - просто вернём код 200 (успешное выполнение).

1
2
3
4
5
6
7
8
9
10
Функция ОтправитьОтчет(Запрос)
	
	ДанныеОтчета = Запрос.ПолучитьТелоКакДвоичныеДанные();
	ДанныеОтчета = Новый ХранилищеЗначения(ДанныеОтчета);
	
	РегистрыСведений.ПолученныеОтчетыОбОшибках.ДобавитьЗапись(ДанныеОтчета);
	
	Возврат Новый HTTPСервисОтвет(200);
	
КонецФункции

Теперь обновим базу и зайдём в неё. У нас появился регистр, записей в нём пока нет.

Скрин

В демо-базе выполним нашу обработку с генерацией ошибки. Нажмём “Отправить” и сразу видим надпись “Отчет отправлен”.

Скрин

Хорошо, перейдём в сервис регистрации. Вот наша запись регистра.

Скрин

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

В ресурсе “Содержимое” находится ХранилищеЗначения. Попробуем извлечь его методом Получить(). Видно, что данные там есть.

Скрин

Отпускаем отладку. Запись в регистр добавилась.

Скрин

А что сейчас в демо-базе? Кнопка “Отправить” теперь называется “Отправить (был отправлен)”.

Скрин

Если сейчас нажать на неё повторно, то она снова отправит тот же самый отчёт об ошибке. И мы видим, что в регистре уже три записи.

Скрин

Постобработка данных

Теперь у нас есть быстрый сервис, который просто пишет входящие данные в регистр. И нам нужно их как-то обрабатывать.

В нашем прототипе сервиса регистрации сделаем новый вид документов “ОтчетыОбОшибках”. В них будут превращаться двоичные данные из нашего буферного регистра. В качестве прототипа нам будет достаточно получать содержимое основного текстового файла из архива. Выделим для него реквизит ТекстОтчета с неограниченной строкой.

Скрин

И сразу поправим одну недоработку. Было бы удобно, если в буферный регистр будет писаться помимо самого файла ещё и дата, когда он был получен. Добавим в регистр дату и заполним.

Скрин

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

Скрин

А вот уже в модуле обработки будет содержаться логика превращения записи регистра в документ.

Логика выполнения такая:

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

Сама обработка записи будет заключаться в следующем. Сначала мы извлечём двоичные данные во временный файл. Затем откроем чтение Zip-файла и извлечём его содержимое в специально подготовленный временный каталог. Как только удалось это сделать, мы откроем в текстовом документе файл “report.json”. Этот файл содержит основные данные отчета об ошибке. Содержимое этого файла и есть наш отчёт.

Теперь, когда мы имеем нужные нам данные, создадим новый документ, заполним его ими и запишем в базу. А временные файлы удалим.

Если запись регистра успешно была обработана, то удалим её тоже. Она нам больше не нужна.

Под капотом код с прототипа:

Выполним обработку.

У нас создались три документа. В каждом хранится содержимое файла report.json. И теперь такую обработку можно поставить на регламентное выполнение и она будет превращать накопленные в регистре отчёты об ошибках в документы.

Скрин

Выводы

Мы разработали простой сервис регистрации ошибок и теперь понимаем, как работать с новым механизмом от 1С.

Данный прототип можно развивать до более сложного инструмента, который поможет в вашей компании обрабатывать ошибки в базах.

А далее мы рассмотрим более подробно извлечение содержимого из архива с отчётом об ошибке.

Авторский пост защищен лицензией CC BY 4.0 .