Метод устанавливает, какие события (по уровню важности) должны регистрироваться в журнале. На время исполнения устанавливается режим монопольного доступа к информационной базе.
Синтаксис
УстановитьИспользованиеЖурналаРегистрации(<Уровни>)Примеры платформы
Уровни = Новый Массив;
Уровни.Добавить(УровеньЖурналаРегистрации.Ошибка);
Уровни.Добавить(УровеньЖурналаРегистрации.Информация);
Уровни.Добавить(УровеньЖурналаРегистрации.Предупреждение);
УстановитьИспользованиеЖурналаРегистрации(Уровни);
УстановитьИспользованиеЖурналаРегистрации (Новый Массив);Полное описание, параметры и ограничения
Глобальный контекст.УстановитьИспользованиеЖурналаРегистрации (Global context.SetEventLogUsing)
Глобальный контекст (Global context)
УстановитьИспользованиеЖурналаРегистрации (SetEventLogUsing)
Доступен, начиная с версии 8.1.
Синтаксис:
УстановитьИспользованиеЖурналаРегистрации(<Уровни>)
Параметры:
<Уровни> (обязательный)
Тип: Массив.
Массив уровней важности регистрируемых событий.
Состоит из значений типа УровеньЖурналаРегистрации.
Пустой массив означает, что никакие события регистрировать не надо.
Помимо пустого массива, допускаются следующие наборы значений:
Ошибка;
Ошибка, Предупреждение;
Ошибка, Предупреждение, Информация;
Ошибка, Предупреждение, Информация, Примечание.
Порядок значений в массиве несущественен.
Описание:
Метод устанавливает, какие события (по уровню важности) должны регистрироваться в журнале.
На время исполнения устанавливается режим монопольного доступа к информационной базе.
Доступность:
Сервер, толстый клиент, внешнее соединение.
Примечание:
Выполняется только при отсутствии других соединений с информационной базой.
Требует наличия у пользователя административных прав. Отсутствие права приводит к возникновению исключения.
Пример:
// будут регистрироваться события уровней: Информация, Предупреждение, Ошибка,
// Примечания – регистрироваться не будут
Уровни = Новый Массив;
Уровни.Добавить(УровеньЖурналаРегистрации.Ошибка);
Уровни.Добавить(УровеньЖурналаРегистрации.Информация);
Уровни.Добавить(УровеньЖурналаРегистрации.Предупреждение);
УстановитьИспользованиеЖурналаРегистрации(Уровни);
// Полное отключение регистрации событий в журнале:
УстановитьИспользованиеЖурналаРегистрации (Новый Массив);
Использование в версии:
Доступен, начиная с версии 8.1.
Методическая информация
Практические примеры
Свой последовательный журнал: настройки, реальные события и архивное сокращение
Две реальные команды новой одноразовой File базы: проверить уровни, политику и разделение с восстановлением; затем сохранить архив и удалить старые записи всего собственного журнала.
Где и как запускать
Неглобальный серверный модуль новой пустой File CF 8.5.1.1343 в отдельной VM; толстая управляемая форма. Будущие изменения реального учебного журнала, не только памяти.
Подготовка
В отдельной НОВОЙ одноразовой Windows VM вручную создайте пустую файловую ИБ точно C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\IB. Не берите копию рабочей базы или чужую CF. UUID пути — учебный маркер, не защита от подмены базы, junction или злонамеренного кода.
Конфигуратор → Конфигурация → свойства: Имя=СтендЖРПоследовательный85; Версия=OwnEventLogSequential4-e6bf76c4-72d0-490f-819b-d0bb63112546; ОсновнойРежимЗапуска=УправляемоеПриложение; РежимСовместимости=НеИспользовать; вариант встроенного языка Русский. Не добавляйте документы, справочники, регистры, регламентные задания и расширения.
Общие → Роли → ЖР85Администратор: учебные права Администрирование, ЖурналРегистрации, АктивныеПользователи и доступ к своей форме. Администрирование → Пользователи: создайте только своего ЖР85Ученик с этой ролью. Код не создаёт пользователей и не меняет роли; он читает настоящую текущую идентичность и UUID единственного соединения.
Администрирование → Настройка журнала регистрации: подтвердите поле Разделять хранение журнала по периодам, которое установленная справка описывает для последовательного формата. Если вместо этого доступен только SQLite-журнал — остановитесь. Не преобразовывайте чужой или уже существующий журнал ради урока. Getter периода не объявлен детектором формата.
В этой будущей VM вручную создайте только новый пустой каталог C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\Archive. Все родительские каталоги должны существовать. Код не создаёт/удаляет каталоги, отказывается от любых существующих файлов и от добавления к старому архиву.
Общие → Общие модули → ЖРПоследовательный85: Сервер=Да; Глобальный, ВызовСервера, Привилегированный, КлиентУправляемоеПриложение, КлиентОбычноеПриложение, ВнешнееСоединение=Нет; ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать. Вставьте CODE целиком. ВызовСервера здесь не нужен: общий модуль вызывается только сервером собственной формы, а не напрямую клиентом.
Общие → Общие формы → УрокЖурнала85. Реквизиты: Остановка85 Булево исходно Ложь; Этап85 Число1.0 исходно0; ДатаСтарая85/Граница85 Дата с составом ДатаИВремя; МаскаУровней85 Число2.0; Период85 ПериодРазделенияХраненияДанныхЖурналаРегистрации; Использование85 Булево; Код85 Строка100; СтарыхПосле85/НовыхПосле85/СтарыхВАрхиве85/ВсегоВАрхиве85 Число15.0; Архив85/Протокол85 неограниченная Строка. Служебные состояние и исходные настройки скрыты, результат и многострочный протокол только для просмотра.
В форме добавьте команды Подготовить85 и Архивировать85, их Действия одноимённые процедуры FORM; кнопки панели привяжите именно к этим командам. Вставьте весь FORM. Сначала только Подготовить. После протокола успешного восстановления подождите несколько реальных секунд, затем отдельно нажмите Архивировать. Не вызывайте callback команды вручную и не переоткрывайте форму для обхода остановки.
Конфигурация → Открыть модуль управляемого приложения: вставьте APPLICATION. Настоящее ПриНачалеРаботыСистемы() открывает собственную форму. Обновите только эту новую пустую CF, закройте Конфигуратор и все другие соединения, запустите один толстый управляемый клиент 8.5.1.1343. Перечисление периода создаётся и обрабатывается сервером, его обмен с сервером документирован.
Первый этап сохраняет реальные уровни, состояние своего Policy и период. Наборы уровней проверяются как множества настоящих enum, не порядок массива. Коды0/1/3/7/15 — только компактные суммы1/2/4/8 для передачи исходного набора; в setter передаётся настоящий Массив, не эти числа. При трёх уровнях Info записывается, Note3 не должен; при четырёх Note4 должен. Policy один и тот же для Disabled/Enabled, комментарии разные.
Политика собственного события возвращается настоящим getter. ОписаниеИспользования фактически проверяется как Неопределено: это условие урока, не обещание для любого события. Отдельные новые descriptor для Ложь/Истина/исходного Bool не меняют сохранённый объект. Системные события Access, AccessDenied и транзакций не настраиваются.
Разделение меняется на Час или День, затем исходное значение восстанавливается и перечитывается. Не обещается появление нового часового файла без смены часа. Все настройки первого этапа восстановлены до возврата; перед сокращением второго этапа временные уровни снова восстанавливаются и проверяются.
Старые/новые даты берутся из настоящих строк журнала. ЗаписьЖурналаРегистрации не принимает дату события. Граница — реальная дата Keep, строго позже Info; все совпадения UUID/имени/комментария/уровня проверяются. Выгрузка идёт в серверную ТаблицаЗначений с пятью точными колонками, MaximumCount0 означает без лимита. Таблицы, массивы и descriptor через RPC не передаются.
СократитьЖурналРегистрации удаляет ВСЕ записи всего своего учебного журнала старше даты Keep, включая платформенные системные записи, а не только отбор Info. .lgf — имя легенды; дополнительные файлы данных получают документированный префикс. Архив читается через явное своё имя. В текущем журнале проверяются все даты не раньше границы, в архиве все даты раньше границы. Автоматические системные события не позволяют обещать фиксированное общее число записей.
Любая ошибка означает отказ и постоянный STOP этой формы, без повторения мутаций или восстановительных вызовов внутри catch. Если ошибка возникла до подтверждённого восстановления настроек, они могли остаться изменёнными. Не обещается автоматический rollback: сохраните исходную ошибку, остановите VM; отдельное ручное восстановление из зафиксированных исходных значений либо новый пустой стенд требует отдельного решения. Повторный запуск урока на использованном журнале запрещён.
Архив — сохранённые удалённые записи, а не их автоматический импорт обратно. СкопироватьЖурналРегистрации и ОчиститьЖурналРегистрации здесь не вызываются и не получают покрытие: отдельный новый SQLite producer ещё не доказан. Этот код проверяется статически; создание VM/CF/ИБ, запись журнала, настройки и архивирование здесь не выполнялись.
Функция ПроверитьСтенд85()
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\IB"";" Тогда
ВызватьИсключение "Разрешена только своя новая пустая File база в отдельной учебной VM";
КонецЕсли;
Если Метаданные.Документы.Количество() <> 0 Или Метаданные.Справочники.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0
Или Метаданные.РегламентныеЗадания.Количество() <> 0
Или Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("ЖРПоследовательный85") = Неопределено
Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("УрокЖурнала85") = Неопределено Тогда
ВызватьИсключение "Нужен пустой стенд с одним своим модулем и формой, без данных и заданий";
КонецЕсли;
МодульМД = Метаданные.ОбщиеМодули.Найти("ЖРПоследовательный85");
Если Не МодульМД.Сервер Или МодульМД.Глобальный Или МодульМД.ВызовСервера Или МодульМД.Привилегированный
Или МодульМД.КлиентУправляемоеПриложение Или МодульМД.КлиентОбычноеПриложение Или МодульМД.ВнешнееСоединение
Или МодульМД.ПовторноеИспользованиеВозвращаемыхЗначений <> Метаданные.СвойстваОбъектов.ПовторноеИспользованиеВозвращаемыхЗначений.НеИспользовать Тогда
ВызватьИсключение "Нужен неглобальный серверный модуль без прямого RPC, привилегий и кеширования";
КонецЕсли;
Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Расширения в этой собственной лаборатории запрещены";
КонецЕсли;
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если ТипЗнч(Текущий) <> Тип("ПользовательИнформационнойБазы") Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Нужен один настоящий учебный пользователь";
КонецЕсли;
Если Текущий.Имя <> "ЖР85Ученик" Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Не совпала фактическая идентичность собственного пользователя";
КонецЕсли;
Соединения = ПолучитьСоединенияИнформационнойБазы();
Если Соединения.Количество() <> 1 Тогда
ВызватьИсключение "Закройте Конфигуратор и все остальные соединения своего стенда";
КонецЕсли;
Соединение = Соединения[0];
Если Соединение.НомерСоединения <> НомерСоединенияИнформационнойБазы()
Или Соединение.Пользователь.УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Единственное соединение должно принадлежать своему текущему пользователю";
КонецЕсли;
Возврат Текущий;
КонецФункции
Функция ИмяСобытия85(Метка)
Метки = СтрРазделить("Info,Note3,Note4,Disabled,Enabled,Keep", ",");
Если Метки.Найти(Метка) = Неопределено Тогда
ВызватьИсключение "Неизвестная метка собственного учебного события";
КонецЕсли;
Возврат "Учебный.ЖР85.e6bf76c4." + ?(Метка = "Disabled" Или Метка = "Enabled", "Policy", Метка);
КонецФункции
Функция ИмяАрхива85()
Возврат "C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\Archive\own-journal-before-cutoff.lgf";
КонецФункции
Процедура ПроверитьПустойАрхив85()
Каталог = Новый Файл("C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\Archive");
Выход = Новый Файл(ИмяАрхива85());
Если Не Каталог.Существует() Или Каталог.ЭтоФайл() Или Выход.Существует()
Или НайтиФайлы(Каталог.ПолноеИмя, "*", Ложь).Количество() <> 0 Тогда
ВызватьИсключение "В своей VM вручную подготовьте только этот новый пустой каталог; существующий архив запрещён";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьЖурнал85(Метка, ВходнойФайл)
Текущий = ПроверитьСтенд85();
Если ТипЗнч(Метка) <> Тип("Строка") Или ТипЗнч(ВходнойФайл) <> Тип("Строка") Тогда
ВызватьИсключение "Нужны точные строковые метка и источник";
КонецЕсли;
Если ВходнойФайл <> "" И ВходнойФайл <> ИмяАрхива85() Тогда
ВызватьИсключение "Чужие файлы журнала читать запрещено";
КонецЕсли;
Отбор = Новый Структура;
Если Метка <> "" Тогда
Отбор.Вставить("Событие", ИмяСобытия85(Метка));
Отбор.Вставить("Комментарий", "Учебный маркер " + Метка);
Отбор.Вставить("Пользователь", Текущий);
КонецЕсли;
Таблица = Новый ТаблицаЗначений;
Если ВходнойФайл = "" Тогда
ВыгрузитьЖурналРегистрации(Таблица, Отбор, "Дата,Пользователь,Событие,Комментарий,Уровень", , 0);
Иначе
ВыгрузитьЖурналРегистрации(Таблица, Отбор, "Дата,Пользователь,Событие,Комментарий,Уровень", ВходнойФайл, 0);
КонецЕсли;
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Или Таблица.Колонки.Количество() <> 5 Тогда
ВызватьИсключение "Нужна фактическая таблица ровно с пятью колонками";
КонецЕсли;
Для Каждого ИмяКолонки Из СтрРазделить("Дата,Пользователь,Событие,Комментарий,Уровень", ",") Цикл
Если Таблица.Колонки.Найти(ИмяКолонки) = Неопределено Тогда
ВызватьИсключение "Не найдена обязательная колонка журнала";
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаЖР Из Таблица Цикл
Если ТипЗнч(СтрокаЖР) <> Тип("СтрокаТаблицыЗначений") Или ТипЗнч(СтрокаЖР.Дата) <> Тип("Дата")
Или ТипЗнч(СтрокаЖР.Пользователь) <> Тип("УникальныйИдентификатор")
Или ТипЗнч(СтрокаЖР.Событие) <> Тип("Строка") Или ТипЗнч(СтрокаЖР.Комментарий) <> Тип("Строка")
Или ТипЗнч(СтрокаЖР.Уровень) <> Тип("УровеньЖурналаРегистрации") Тогда
ВызватьИсключение "Каждая строка должна иметь все настоящие документированные типы";
КонецЕсли;
Если Метка <> "" Тогда
Уровень = ?(Метка = "Note3" Или Метка = "Note4", УровеньЖурналаРегистрации.Примечание, УровеньЖурналаРегистрации.Информация);
Если СтрокаЖР.Событие <> ИмяСобытия85(Метка) Или СтрокаЖР.Комментарий <> "Учебный маркер " + Метка
Или СтрокаЖР.Пользователь <> Текущий.УникальныйИдентификатор Или СтрокаЖР.Уровень <> Уровень Тогда
ВызватьИсключение "Не подтверждены имя, комментарий, UUID и уровень собственного события";
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Таблица;
КонецФункции
Процедура ЗаписатьМаркер85(Метка, Уровень)
ЗаписьЖурналаРегистрации(ИмяСобытия85(Метка), Уровень, , , "Учебный маркер " + Метка);
КонецПроцедуры
Функция МаскаУровней85()
Уровни = ПолучитьИспользованиеЖурналаРегистрации();
Если ТипЗнч(Уровни) <> Тип("Массив") Или Уровни.Количество() > 4 Тогда
ВызватьИсключение "Получатель должен вернуть настоящий массив не более четырёх уровней";
КонецЕсли;
Просмотренные = Новый Массив;
Маска = 0;
Для Каждого Уровень Из Уровни Цикл
Если ТипЗнч(Уровень) <> Тип("УровеньЖурналаРегистрации") Или Просмотренные.Найти(Уровень) <> Неопределено Тогда
ВызватьИсключение "Произвольные значения и повторные уровни запрещены";
КонецЕсли;
Просмотренные.Добавить(Уровень);
Если Уровень = УровеньЖурналаРегистрации.Ошибка Тогда
Маска = Маска + 1;
ИначеЕсли Уровень = УровеньЖурналаРегистрации.Предупреждение Тогда
Маска = Маска + 2;
ИначеЕсли Уровень = УровеньЖурналаРегистрации.Информация Тогда
Маска = Маска + 4;
ИначеЕсли Уровень = УровеньЖурналаРегистрации.Примечание Тогда
Маска = Маска + 8;
Иначе
ВызватьИсключение "Неизвестный уровень журнала";
КонецЕсли;
КонецЦикла;
Если Маска <> 0 И Маска <> 1 И Маска <> 3 И Маска <> 7 И Маска <> 15 Тогда
ВызватьИсключение "Набор уровней не разрешён установленной платформой";
КонецЕсли;
Возврат Маска;
КонецФункции
Процедура УстановитьУровни85(Маска)
Если ТипЗнч(Маска) <> Тип("Число") Тогда
ВызватьИсключение "Код набора уровней должен быть числом";
КонецЕсли;
Если Маска <> 0 И Маска <> 1 И Маска <> 3 И Маска <> 7 И Маска <> 15 Тогда
ВызватьИсключение "Допускаются только пять документированных наборов";
КонецЕсли;
Уровни = Новый Массив;
Если Маска >= 1 Тогда Уровни.Добавить(УровеньЖурналаРегистрации.Ошибка); КонецЕсли;
Если Маска >= 3 Тогда Уровни.Добавить(УровеньЖурналаРегистрации.Предупреждение); КонецЕсли;
Если Маска >= 7 Тогда Уровни.Добавить(УровеньЖурналаРегистрации.Информация); КонецЕсли;
Если Маска = 15 Тогда Уровни.Добавить(УровеньЖурналаРегистрации.Примечание); КонецЕсли;
УстановитьИспользованиеЖурналаРегистрации(Уровни);
Если МаскаУровней85() <> Маска Тогда
ВызватьИсключение "Настройка уровней фактически не совпала с ожидаемой";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьПолитику85()
Политика = ПолучитьИспользованиеСобытияЖурналаРегистрации(ИмяСобытия85("Enabled"));
Если ТипЗнч(Политика) <> Тип("ИспользованиеСобытияЖурналаРегистрации") Тогда
ВызватьИсключение "Нужен настоящий объект использования собственного события";
КонецЕсли;
Если ТипЗнч(Политика.Использование) <> Тип("Булево") Или Политика.ОписаниеИспользования <> Неопределено Тогда
ВызватьИсключение "Неожиданная политика: произвольное описание не изменяем";
КонецЕсли;
Возврат Политика.Использование;
КонецФункции
Процедура УстановитьПолитику85(Использовать)
Если ТипЗнч(Использовать) <> Тип("Булево") Тогда
ВызватьИсключение "Нужно точное булево состояние собственного события";
КонецЕсли;
Политика = Новый ИспользованиеСобытияЖурналаРегистрации(Использовать, Неопределено);
УстановитьИспользованиеСобытияЖурналаРегистрации(ИмяСобытия85("Enabled"), Политика);
Если ПрочитатьПолитику85() <> Использовать Тогда
ВызватьИсключение "Состояние собственного события не подтверждено";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьПериод85()
Период = ПолучитьПериодРазделенияХраненияДанныхЖурналаРегистрации();
Если ТипЗнч(Период) <> Тип("ПериодРазделенияХраненияДанныхЖурналаРегистрации") Тогда
ВызватьИсключение "Период должен быть настоящим значением перечисления";
КонецЕсли;
Возврат Период;
КонецФункции
Процедура ПроверитьПоля85(Пакет, Описание)
Если ТипЗнч(Пакет) <> Тип("ФиксированнаяСтруктура") Тогда
ВызватьИсключение "До чтения полей нужен настоящий неизменяемый пакет";
КонецЕсли;
Если Пакет.Количество() <> Описание.Количество() Тогда
ВызватьИсключение "Отсутствующие и лишние поля запрещены";
КонецЕсли;
Для Каждого Поле Из Описание Цикл
Если Не Пакет.Свойство(Поле.Ключ, ЗначениеПоля) Или ТипЗнч(ЗначениеПоля) <> Поле.Значение Тогда
ВызватьИсключение "Не совпали точные имена и типы всех полей";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПроверитьПодготовку85(Пакет) Экспорт
Описание = Новый Структура("ДатаСтарая,МаскаУровней,Период,Использование,Код", Тип("Дата"), Тип("Число"), Тип("ПериодРазделенияХраненияДанныхЖурналаРегистрации"), Тип("Булево"), Тип("Строка"));
ПроверитьПоля85(Пакет, Описание);
Если Пакет.Код <> "OwnEventLogSequential4-e6bf76c4-72d0-490f-819b-d0bb63112546"
Или (Пакет.МаскаУровней <> 0 И Пакет.МаскаУровней <> 1 И Пакет.МаскаУровней <> 3 И Пакет.МаскаУровней <> 7 И Пакет.МаскаУровней <> 15) Тогда
ВызватьИсключение "Не совпали код стенда и разрешённый исходный набор уровней";
КонецЕсли;
КонецПроцедуры
Функция Подготовить85() Экспорт
ПроверитьСтенд85();
ПроверитьПустойАрхив85();
Для Каждого Метка Из СтрРазделить("Info,Note3,Note4,Disabled,Enabled,Keep", ",") Цикл
Если ПрочитатьЖурнал85(Метка, "").Количество() <> 0 Тогда
ВызватьИсключение "Этот стенд уже использовался; повторные изменения запрещены";
КонецЕсли;
КонецЦикла;
СтараяМаска = МаскаУровней85();
СтароеИспользование = ПрочитатьПолитику85();
СтарыйПериод = ПрочитатьПериод85();
УстановитьУровни85(7);
ЗаписатьМаркер85("Info", УровеньЖурналаРегистрации.Информация);
ЗаписатьМаркер85("Note3", УровеньЖурналаРегистрации.Примечание);
Старые = ПрочитатьЖурнал85("Info", "");
Если Старые.Количество() <> 1 Или ПрочитатьЖурнал85("Note3", "").Количество() <> 0 Тогда
ВызватьИсключение "Информация должна записаться, а Примечание при трёх уровнях — нет";
КонецЕсли;
УстановитьУровни85(15);
ЗаписатьМаркер85("Note4", УровеньЖурналаРегистрации.Примечание);
УстановитьПолитику85(Ложь);
ЗаписатьМаркер85("Disabled", УровеньЖурналаРегистрации.Информация);
Если ПрочитатьЖурнал85("Note4", "").Количество() <> 1 Или ПрочитатьЖурнал85("Disabled", "").Количество() <> 0 Тогда
ВызватьИсключение "Не подтверждены четвёртый уровень и отключение своего события";
КонецЕсли;
УстановитьПолитику85(Истина);
ЗаписатьМаркер85("Enabled", УровеньЖурналаРегистрации.Информация);
Если ПрочитатьЖурнал85("Enabled", "").Количество() <> 1 Тогда
ВызватьИсключение "Включённое собственное событие должно появиться один раз";
КонецЕсли;
НовыйПериод = ?(СтарыйПериод = ПериодРазделенияХраненияДанныхЖурналаРегистрации.Час, ПериодРазделенияХраненияДанныхЖурналаРегистрации.День, ПериодРазделенияХраненияДанныхЖурналаРегистрации.Час);
УстановитьПериодРазделенияХраненияДанныхЖурналаРегистрации(НовыйПериод);
Если ПрочитатьПериод85() <> НовыйПериод Тогда
ВызватьИсключение "Новый период разделения фактически не подтверждён";
КонецЕсли;
УстановитьПериодРазделенияХраненияДанныхЖурналаРегистрации(СтарыйПериод);
Если ПрочитатьПериод85() <> СтарыйПериод Тогда
ВызватьИсключение "Исходный период не восстановлен";
КонецЕсли;
УстановитьПолитику85(СтароеИспользование);
УстановитьУровни85(СтараяМаска);
Если ПрочитатьПолитику85() <> СтароеИспользование Или ПрочитатьПериод85() <> СтарыйПериод Тогда
ВызватьИсключение "Вся исходная настройка должна быть подтверждена до второй команды";
КонецЕсли;
Пакет = Новый ФиксированнаяСтруктура(Новый Структура("ДатаСтарая,МаскаУровней,Период,Использование,Код", Старые.Получить(0).Дата, СтараяМаска, СтарыйПериод, СтароеИспользование, "OwnEventLogSequential4-e6bf76c4-72d0-490f-819b-d0bb63112546"));
ПроверитьПодготовку85(Пакет);
Возврат Пакет;
КонецФункции
Процедура ПроверитьИтог85(Итог) Экспорт
Описание = Новый Структура("ДатаСтарая,Граница,СтарыхПосле,НовыхПосле,СтарыхВАрхиве,ВсегоВАрхиве,Архив", Тип("Дата"), Тип("Дата"), Тип("Число"), Тип("Число"), Тип("Число"), Тип("Число"), Тип("Строка"));
ПроверитьПоля85(Итог, Описание);
Если Итог.ДатаСтарая >= Итог.Граница Или Итог.СтарыхПосле <> 0 Или Итог.НовыхПосле <> 1
Или Итог.СтарыхВАрхиве <> 1 Или Итог.ВсегоВАрхиве < 1 Или Итог.Архив <> ИмяАрхива85() Тогда
ВызватьИсключение "Ожидаемый результат сокращения фактически не подтверждён";
КонецЕсли;
КонецПроцедуры
Функция Архивировать85(Пакет) Экспорт
ПроверитьСтенд85();
ПроверитьПодготовку85(Пакет);
ПроверитьПустойАрхив85();
Старые = ПрочитатьЖурнал85("Info", "");
Если Старые.Количество() <> 1 Или ПрочитатьЖурнал85("Keep", "").Количество() <> 0
Или ПрочитатьЖурнал85("Note4", "").Количество() <> 1 Или ПрочитатьЖурнал85("Enabled", "").Количество() <> 1
Или ПрочитатьЖурнал85("Note3", "").Количество() <> 0 Или ПрочитатьЖурнал85("Disabled", "").Количество() <> 0 Тогда
ВызватьИсключение "Нужен полностью подтверждённый первый этап без повторного Keep";
КонецЕсли;
Если Старые.Получить(0).Дата <> Пакет.ДатаСтарая Или ТекущаяДата() <= Пакет.ДатаСтарая
Или МаскаУровней85() <> Пакет.МаскаУровней Или ПрочитатьПериод85() <> Пакет.Период
Или ПрочитатьПолитику85() <> Пакет.Использование Тогда
ВызватьИсключение "Нужны исходные настройки, фактическая старая дата и реальный разрыв времени";
КонецЕсли;
УстановитьУровни85(15);
ЗаписатьМаркер85("Keep", УровеньЖурналаРегистрации.Информация);
Новые = ПрочитатьЖурнал85("Keep", "");
Если Новые.Количество() <> 1 Тогда
ВызватьИсключение "Новый сохраняемый маркер должен появиться ровно один раз";
КонецЕсли;
Граница = Новые.Получить(0).Дата;
Если Граница <= Пакет.ДатаСтарая Тогда
ВызватьИсключение "Фактическая новая дата должна быть строго позже старой";
КонецЕсли;
УстановитьУровни85(Пакет.МаскаУровней);
Если ПрочитатьПериод85() <> Пакет.Период Или ПрочитатьПолитику85() <> Пакет.Использование Тогда
ВызватьИсключение "Все настройки должны быть восстановлены до необратимого сокращения";
КонецЕсли;
До = ПрочитатьЖурнал85("", "");
ПериодЖР = ПолучитьПериодЖурналаРегистрации();
Если ТипЗнч(ПериодЖР) <> Тип("Диапазон") Тогда
ВызватьИсключение "Период журнала должен быть настоящим диапазоном";
КонецЕсли;
Если ТипЗнч(ПериодЖР.Начало) <> Тип("Дата") Или ТипЗнч(ПериодЖР.Конец) <> Тип("Дата")
Или До.Количество() < 2 Или ПериодЖР.Начало > Пакет.ДатаСтарая Или ПериодЖР.Конец < Граница Тогда
ВызватьИсключение "Весь собственный журнал должен содержать обе реальные даты";
КонецЕсли;
ПроверитьСтенд85();
ПроверитьПустойАрхив85();
СократитьЖурналРегистрации(Граница, ИмяАрхива85());
Выход = Новый Файл(ИмяАрхива85());
Если Не Выход.Существует() Или Не Выход.ЭтоФайл() Тогда
ВызватьИсключение "Новый собственный архив не появился";
КонецЕсли;
СтарыеПосле = ПрочитатьЖурнал85("Info", "");
НовыеПосле = ПрочитатьЖурнал85("Keep", "");
АрхивСтарых = ПрочитатьЖурнал85("Info", ИмяАрхива85());
Если СтарыеПосле.Количество() <> 0 Или НовыеПосле.Количество() <> 1 Или АрхивСтарых.Количество() <> 1
Или ПрочитатьЖурнал85("Keep", ИмяАрхива85()).Количество() <> 0 Тогда
ВызватьИсключение "Не подтверждено разделение собственных старого и сохраняемого событий";
КонецЕсли;
Если АрхивСтарых.Получить(0).Дата <> Пакет.ДатаСтарая Или НовыеПосле.Получить(0).Дата <> Граница Тогда
ВызватьИсключение "Изменились реальные даты сохранённых событий";
КонецЕсли;
После = ПрочитатьЖурнал85("", "");
Для Каждого СтрокаЖР Из После Цикл
Если СтрокаЖР.Дата < Граница Тогда ВызватьИсключение "В текущем журнале осталась запись старше границы"; КонецЕсли;
КонецЦикла;
ВесьАрхив = ПрочитатьЖурнал85("", ИмяАрхива85());
Для Каждого СтрокаЖР Из ВесьАрхив Цикл
Если СтрокаЖР.Дата >= Граница Тогда ВызватьИсключение "В архив попала запись не старше границы"; КонецЕсли;
КонецЦикла;
ПериодЖР = ПолучитьПериодЖурналаРегистрации();
Если ТипЗнч(ПериодЖР) <> Тип("Диапазон") Тогда ВызватьИсключение "Нужен фактический диапазон после сокращения"; КонецЕсли;
Если ТипЗнч(ПериодЖР.Начало) <> Тип("Дата") Или ТипЗнч(ПериодЖР.Конец) <> Тип("Дата")
Или ПериодЖР.Начало < Граница Или ПериодЖР.Конец < Граница Тогда
ВызватьИсключение "Границы всего журнала не подтверждены";
КонецЕсли;
Итог = Новый ФиксированнаяСтруктура(Новый Структура("ДатаСтарая,Граница,СтарыхПосле,НовыхПосле,СтарыхВАрхиве,ВсегоВАрхиве,Архив", Пакет.ДатаСтарая, Граница, СтарыеПосле.Количество(), НовыеПосле.Количество(), АрхивСтарых.Количество(), ВесьАрхив.Количество(), ИмяАрхива85()));
ПроверитьИтог85(Итог);
Возврат Итог;
КонецФункцииДве собственные команды, проверенные пакеты и постоянная остановка
Общие → Общие формы → УрокЖурнала85 → Модуль
Толстый управляемый клиент / &НаСервере
&НаКлиенте
Процедура Подготовить85(Команда)
Попытка
Если Остановка85 Или Этап85 <> 0 Или ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Подготовить85 Тогда
ВызватьИсключение "Команда разрешена только один раз на новом стенде";
КонецЕсли;
ПодготовитьНаСервере85();
Если Остановка85 Или Этап85 <> 1 Или ТипЗнч(ДатаСтарая85) <> Тип("Дата")
Или ТипЗнч(МаскаУровней85) <> Тип("Число") Или ТипЗнч(Период85) <> Тип("ПериодРазделенияХраненияДанныхЖурналаРегистрации")
Или ТипЗнч(Использование85) <> Тип("Булево") Или Код85 <> "OwnEventLogSequential4-e6bf76c4-72d0-490f-819b-d0bb63112546" Тогда
ВызватьИсключение "Первый этап не подтверждён на границе клиент/сервер";
КонецЕсли;
Исключение
Остановка85 = Истина;
Протокол85 = "ОТКАЗ, не успех. Не повторяйте команды и не переоткрывайте форму для обхода STOP. Настройки могли не восстановиться. Сохраните исходную ошибку и остановите учебную VM.";
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаСервере
Процедура ПодготовитьНаСервере85()
Попытка
Если Остановка85 Или Этап85 <> 0 Тогда ВызватьИсключение "Подготовка уже запускалась"; КонецЕсли;
Пакет = ЖРПоследовательный85.Подготовить85();
ЖРПоследовательный85.ПроверитьПодготовку85(Пакет);
ДатаСтарая85 = Пакет.ДатаСтарая;
МаскаУровней85 = Пакет.МаскаУровней;
Период85 = Пакет.Период;
Использование85 = Пакет.Использование;
Код85 = Пакет.Код;
Этап85 = 1;
Протокол85 = "Первый этап подтверждён. Исходные уровни, собственная политика и период восстановлены. Старая дата: " + Строка(ДатаСтарая85) + ". Подождите несколько секунд, затем отдельно нажмите Архивировать. Будут удалены ВСЕ записи собственной учебной базы старше новой реальной даты, включая системные.";
Исключение
Остановка85 = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Архивировать85(Команда)
Попытка
Если Остановка85 Или Этап85 <> 1 Или ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Архивировать85 Тогда
ВызватьИсключение "Нужен завершённый первый этап и ровно одна своя команда архивации";
КонецЕсли;
АрхивироватьНаСервере85();
Если Остановка85 Или Этап85 <> 2 Или ТипЗнч(Граница85) <> Тип("Дата") Или Граница85 <= ДатаСтарая85
Или ТипЗнч(СтарыхПосле85) <> Тип("Число") Или СтарыхПосле85 <> 0
Или ТипЗнч(НовыхПосле85) <> Тип("Число") Или НовыхПосле85 <> 1
Или ТипЗнч(СтарыхВАрхиве85) <> Тип("Число") Или СтарыхВАрхиве85 <> 1
Или ТипЗнч(ВсегоВАрхиве85) <> Тип("Число") Или ВсегоВАрхиве85 < 1
Или Архив85 <> "C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\Archive\own-journal-before-cutoff.lgf" Тогда
ВызватьИсключение "Не подтверждён весь фактический итог";
КонецЕсли;
Исключение
Остановка85 = Истина;
Протокол85 = "ОТКАЗ, не успех. После ошибки нет повторных мутаций или автоматического отката. Удалённые записи не восстановлены в текущий журнал; архив не является импортом. Сохраните ошибку и остановите учебную VM.";
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаСервере
Процедура АрхивироватьНаСервере85()
Попытка
Если Остановка85 Или Этап85 <> 1 Тогда ВызватьИсключение "Архивация на этом этапе запрещена"; КонецЕсли;
Пакет = Новый ФиксированнаяСтруктура(Новый Структура("ДатаСтарая,МаскаУровней,Период,Использование,Код", ДатаСтарая85, МаскаУровней85, Период85, Использование85, Код85));
ЖРПоследовательный85.ПроверитьПодготовку85(Пакет);
Итог = ЖРПоследовательный85.Архивировать85(Пакет);
ЖРПоследовательный85.ПроверитьИтог85(Итог);
Если Итог.ДатаСтарая <> ДатаСтарая85 Тогда ВызватьИсключение "Подменена исходная дата"; КонецЕсли;
Граница85 = Итог.Граница;
СтарыхПосле85 = Итог.СтарыхПосле;
НовыхПосле85 = Итог.НовыхПосле;
СтарыхВАрхиве85 = Итог.СтарыхВАрхиве;
ВсегоВАрхиве85 = Итог.ВсегоВАрхиве;
Архив85 = Итог.Архив;
Этап85 = 2;
Протокол85 = "В текущем журнале старых своих Info:0, сохранённых Keep:1; в архиве старых Info:1. ВСЕ записи всего собственного журнала старше " + Строка(Граница85) + " удалены. В архиве всего " + Строка(ВсегоВАрхиве85) + " записей, включая возможные системные. Архив: " + Архив85 + ". Настройки восстановлены ДО сокращения. Импорт удалённых записей не выполнялся.";
Исключение
Остановка85 = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыШтатное событие запуска открывает только собственную лабораторию
Конфигурация → Открыть модуль управляемого приложения
Толстый управляемый клиент
Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnEventLogSequential4_9e2c4621-52cc-4d19-8c2d-f035ba650763\IB"";" Тогда
ВызватьИсключение "Откройте только свою новую учебную File базу в отдельной VM";
КонецЕсли;
ОткрытьФорму("ОбщаяФорма.УрокЖурнала85", , , Истина);
#Иначе
ВызватьИсключение "Нужен толстый управляемый клиент 8.5.1.1343";
#КонецЕсли
КонецПроцедурыРазбор по шагам
Подготовить отдельную новую пустую VM/File CF, одного своего пользователя, последовательный журнал, точные форму/модуль и пустой каталог архива; проверить все маркеры и единственное соединение.
Подготовить85: получить исходные настройки через native getters, наблюдать уровни7/15 и один свой Policy Ложь/Истина на реальных строках. Проверить период Час/День, восстановить и подтвердить все исходные настройки.
Подождать реальный разрыв времени между двумя командами. Архивировать85 перечитывает старую строку и настройки, создаёт Keep и берёт его настоящую дату. Временные уровни восстанавливаются ДО сокращения.
После полного readback и отказа от любого существующего архива один раз сократить весь собственный журнал до фактической даты Keep с новым .lgf архивом. Проверить Info0/Keep1 в текущем журнале и Info1/Keep0 в архиве, все даты обоих журналов и настоящий период текущего журнала.
Как проверить результат
Будущий первый протокол: Info1, Note3=0, Note4=1, Disabled0, Enabled1; уровни, свой Policy и период восстановлены. Getter сам по себе не доказывает запись события: проверяются actual строки.
Будущий итог: старая дата строго меньше границы, СтарыхПосле0, НовыхПосле1, СтарыхВАрхиве1, ВсегоВАрхиве≥1 и точный новый путь. Общее число может включать системные записи и берётся фактически.
Пакеты имеют ровно5 и7 полей с проверкой всех имён/типов до чтения. Только4 primary. Ошибка/отказ не отмечается как полезный успешный пример; повторение и автоматический ремонт запрещены.
Ожидаемый результат
Ожидаемый будущий ручной результат: исходные настройки восстановлены до whole-own-lab сокращения; старый Info доступен в новом архиве, новый Keep остаётся в текущем журнале. Здесь 1С не запускалась.
На что обратить внимание
Никогда не запускайте в рабочей базе: дата сокращения касается всего журнала, без event-фильтра. Проверки учебных имён/UUID не являются защитой от намеренной подмены.
Setter уровня допускает лишь0/1/3/7/15 наборы enum, требует администратора и отсутствие других соединений. Числа — только представление пакета, не аргумент native setter.
Period setter доступен только последовательному журналу. Native enum периода имеет серверный контекст; не переносите код в чисто клиентский модуль.
Native Range.Начало/Конец и ТаблицаЗначений.Колонки только читаются. UUID строки журнала сравнивается с фактическим пользовательским UUID, не с объектом пользователя.
Truncate существующий архив пытается дополнить: здесь любой старый файл или содержимое каталога запрещены. Удаление не может быть отменено повторным чтением архива.
STOP действует в текущей форме; не закрывайте/открывайте её заново ради повторного запуска. Ошибка до восстановления может оставить учебные настройки изменёнными; успешное восстановление не выдумывается.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.