Как получить список вызванных функций 1С в хронологическом порядке?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Стандартный инструмент Замер производительности в Конфигураторе 1С агрегирует данные. Он группирует строки кода по методам, подсчитывает суммарное время выполнения и количество вызовов, но полностью теряет хронологию выполнения (то есть последовательность «друг за другом»). Сортировка по колонкам времени или имени не позволяет восстановить реальный ход выполнения программы.

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

Метод 1. Стек вызовов в режиме отладки

Рассмотрим самый доступный и простой способ, заложенный в платформу по умолчанию — использование панели Стек вызовов (Call Stack).

Этот инструмент позволяет увидеть всю цепочку вызовов, которая привела к текущему состоянию системы. Для этого нам необходимо:

  1. Установить точку останова в интересующем нас месте кода (например, в самом конце исследуемого процесса).
  2. Запустить систему в режиме отладки и дождаться остановки выполнения.
  3. Открыть панель «Стек вызовов» через меню «Отладка» или сочетанием клавиш Ctrl + Alt + C.

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

Метод 2. Ручное логирование выполнения кода

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

В начало каждой интересующей нас процедуры или функции мы добавляем вызов процедуры записи в лог. В качестве лога можно использовать Журнал регистрации 1С или внешний текстовый файл.

Посмотрим на пример кода с записью в Журнал регистрации:


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

    // Основной код процедуры
    // ...
КонецПроцедуры

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


Процедура ЗаписатьВТекстовыйЛог(ИмяМетода) Экспорт
    ПутьКФайлу = "C:\logs\trace_log.txt";
    ТекстДокумент = Новый ТекстовыйДокумент;
    Если ФайлСуществует(ПутьКФайлу) Тогда
        ТекстДокумент.Прочитать(ПутьКФайлу);
    КонецЕсли;
    ТекстДокумент.ДобавитьСтроку(Строка(ТекущаяДатаСеанса()) + " | " + ИмяМетода);
    ТекстДокумент.Записать(ПутьКФайлу);
КонецПроцедуры

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

Метод 3. Использование расширений конфигурации (АОП)

Чтобы обойти ограничение на изменение основной конфигурации, мы можем применить принципы Аспектно-ориентированного программирования (АОП) с помощью механизма расширений 1С.

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

  1. Создаем новое расширение конфигурации.
  2. Добавляем в расширение интересующие нас общие модули или модули объектов.
  3. Для каждого нужного метода создаем обработчик с аннотацией &Перед.

Посмотрим на пример перехвата метода в расширении:


&Перед("РассчитатьПараметрыЗаказа")
Процедура Расш1_РассчитатьПараметрыЗаказаПеред(Параметры)
    // Фиксируем вызов в лог-файле
    ЗаписатьВТекстовыйЛог("Начало: РассчитатьПараметрыЗаказа");
КонецПроцедуры

Этот способ позволяет гибко управлять процессом трассировки: расширение можно легко отключить в пользовательском режиме, и логирование полностью прекратится, не влияя на основную конфигурацию.

Метод 4. Настройка Технологического журнала (ТЖ)

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

Платформа 1С при выполнении серверных вызовов умеет логировать события и выводить свойство Context, которое содержит стек вызовов на момент совершения операции. Мы можем настроить файл конфигурации ТЖ logcfg.xml для сбора интересующих нас событий.

Разберем пример настройки ТЖ для отслеживания серверных вызовов:


<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
    <log location="C:\v8\logs\scall_trace" history="24">
        <event filter="scall">
            <eq property="Name" value="*"/>
        </event>
        <property name="Context"/>
    </log>
</config>

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

Метод 5. Анализ и парсинг файлов замера производительности (.pff)

Вернемся к стандартному замеру производительности. Хотя сам Конфигуратор группирует строки, физический файл замера с расширением .pff (который можно сохранить из окна замера через меню Файл - Сохранить) содержит в себе последовательные данные.

Выясним причину, по которой ручной анализ этого файла затруднен: он имеет специфическую внутреннюю структуру. Однако в сообществе разработчиков 1С есть готовые скрипты и инструменты (например, на базе OneScript или Python), которые умеют парсить файлы .pff.

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

Метод 6. Использование возможностей 1С:EDT (Enterprise Development Tools)

Современная среда разработки 1С:EDT предоставляет гораздо более мощные и гибкие инструменты отладки по сравнению с классическим Конфигуратором.

Проанализируем возможности профилирования в 1С:EDT:

Если проект ведется в 1С:EDT, то задача хронологического анализа вызовов решается штатными инструментами среды в несколько кликов.

Метод 7. Автоматическая разметка (инструментация) кода

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

Разберем этот процесс по шагам:

  1. Конфигурация выгружается в файлы исходного кода (xml/src) через стандартную команду Конфигуратора или с помощью CLI.
  2. Специальный скрипт автоматизации (например, написанный на OneScript) обходит все файлы модулей.
  3. Используя регулярные выражения или парсер синтаксического дерева, скрипт находит ключевые слова Процедура и Функция и автоматически вставляет первую строчку кода, вызывающую логирование (аналогично Меоду 2).
  4. Конфигурация собирается обратно из файлов и загружается в тестовую базу.
  5. Выполняется исследуемый процесс, собирается точнейший хронологический лог выполнения.
  6. После завершения анализа исходный код возвращается в первоначальное состояние (например, простым откатом изменений в системе контроля версий Git).

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

← На главную