В процессе сопровождения и администрирования информационных баз 1С:Предприятия 7.7 периодически возникает трудноуловимая ошибка: пользователь выполняет действие в программе, однако в стандартном Мониторе пользователей событие фиксируется под именем совершенно другого сотрудника. Проблема носит нерегулярный характер, возникает спонтанно и часто списывается на сбои платформы. Проанализируем внутреннее устройство журнала регистрации в версии 7.7, выясним технические причины подобного поведения и разберем по шагам методы его устранения.
Для понимания сути проблемы рассмотрим, как устроен механизм журналирования в платформе 1С 7.7. Все события записываются в текстовый файл 1Cv7.mlg, расположенный в подкаталоге SYSLOG каталога информационной базы. Формат этого файла представляет собой обычный структурированный текст, где каждая строка содержит запись о событии, а поля (дата, время, пользователь, событие, комментарий и т. д.) разделяются точкой с запятой (;).
Когда Монитор пользователей или внешняя обработка считывает лог, платформа парсит строки, ориентируясь строго на количество разделителей и символы перевода строки. Если в переданных данных нарушается строгая структура, отображение колонок искажается, что и приводит к кажущейся «подмене» автора действия.
Разберем детально ключевые факторы, из-за которых имя автора действия отображается неверно:
ЗаписьЖурналаРегистрации() в текст комментария, наименование события или представление объекта попадает точка с запятой (;), символ возврата каретки (Симв(13)) или перевод строки (Симв(10)), парсер принимает их за служебные разделители. Вся последующая строка смещается в соседние колонки. Значение из колонки комментария или объекта может попасть в поле имени пользователя для следующей визуальной строки.1Cv7.mlg. При активных механизмах сетевого кэширования (Opportunistic Locks / SMB2 / SMB3) операционная система может задерживать сброс буфера на диск. В результате фрагменты строк разных пользователей накладываются друг на друга, обрезаются символы конца строки, что разрушает структуру лога.ЗаписьЖурналаРегистрации() не позволяет произвольно указать автора события — платформа всегда автоматически подставляет имя текущего залогиненного сеанса (ИмяПользователя()). Если в конфигурации настроена интеграция или обмен, запускающий скрытый сеанс 1С через OLE Automation (например, под системной учетной записью), то любые операции внутри этого процесса зарегистрируются под техническим пользователем, а не под сотрудником, вызвавшим обработку.1Cv7.mlg. При разрастании файла журнала до 1–2 Гб встроенные 32-битные механизмы платформы начинают некорректно обрабатывать файловые смещения, что приводит к перескакиванию указателя чтения и «каше» из строк.Прежде чем менять программный код, выясним, повреждена ли сама запись или сбой происходит только на этапе отображения. Откроем файл SYSLOG\1Cv7.mlg любым продвинутым текстовым редактором, способным работать с большими файлами. Найдем проблемную запись по точному времени события. Если в текстовой строке имя пользователя указано правильно, но предшествующие строки содержат незакрытые кавычки, точки с запятой или разорванные строки, значит, отображение в интерфейсе сбито именно сдвигом колонок.
Посмотрим на пример вызова метода программной записи в журнал регистрации. Чтобы гарантированно защитить лог от разрушения структуры, необходимо очищать все строковые параметры от точки с запятой, табуляций и переводов строк перед передачей в метод.
Разберем универсальную функцию очистки строки и правильный вызов записи в журнал:
Функция ОчиститьСтрокуДляЛога(Знач ВходнойТекст)
// Заменяем точку с запятой, чтобы не нарушать структуру колонок MLG-файла
Текст = СтрЗаменить(ВходнойТекст, ";", ",");
// Удаляем символы перевода строки и возврата каретки
Текст = СтрЗаменить(Текст, Симв(10), " ");
Текст = СтрЗаменить(Текст, Симв(13), " ");
// Удаляем символы табуляции
Текст = СтрЗаменить(Текст, Симв(9), " ");
Возврат СокрЛП(Текст);
КонецФункции
Процедура ЗафиксироватьСобытие(Событие, Комментарий)
БезопасноеСобытие = ОчиститьСтрокуДляЛога(Событие);
БезопасныйКомментарий = ОчиститьСтрокуДляЛога(Комментарий);
// Запись в журнал регистрации текущего активного сеанса
ЗаписьЖурналаРегистрации(БезопасныйКомментарий, БезопасноеСобытие, , , 1);
КонецПроцедуры
Обратите внимание: очищать необходимо не только произвольный комментарий, но и строковые представления объектов (документов, справочников), если они передаются в журнал в виде текстовых описаний.
Если программный код проверен, но сбои периодически продолжаются при высокой многопользовательской нагрузке, выполним административные регламентные действия: