opentelemetry-v8-logs
Приложение читает технологический журнал (ТЖ) и журнал регистрации (ЖР) 1С:Предприятия и передает их в OpenTelemetry по OTLP. Получатель - любой бэкенд с поддержкой OTLP, например стек LGTM: Loki (логи), Grafana, Tempo (трассы), Mimir или Prometheus (метрики).
Как это работает
каталоги ТЖ и ЖР ──► читатели ──► экспортеры ──► OpenTelemetry SDK ──► OTLP ──► LGTM
▲ │
└──── позиции чтения (autumn-data) ◄── фиксация после успешной отправки- Читатель находит файлы журнала и дочитывает каждый с сохраненной байтовой позиции. Читаются только завершенные события и записи: недописанный хвост файла будет прочитан в следующем проходе. Файлы технологического журнала всех процессов читаются по порядку часа из имени файла: при первом запуске и догоне после простоя события уходят примерно в порядке времени, иначе Loki отклонил бы записи, которые больше чем на час старше уже принятых в тот же поток логов (
too_far_behind). В лог приложения попадают начало чтения файла (первые новые данные с запуска приложения), полное прочтение файла, в который больше не пишут (с числом записей за этот запуск), и усечение файла, но не каждый проход по дописываемому файлу. Файлы, прочитанные до конца в прошлые запуски, не логируются. - Экспортер превращает событие в запись лога, метрики и спаны.
- Записи передаются пакетами, после каждого пакета буферы SDK сбрасываются.
- Позиции сохраняются в базу только после успешной отправки. При сбое отправки они откатываются, и данные будут прочитаны повторно (доставка «хотя бы один раз»). Логи и спаны при повторе могут продублироваться; метрики записываются только после успешного сброса.
Что поддерживается
| Источник | Форматы |
|---|---|
| Технологический журнал | текст (8.3 и 8.2), JSON (8.3.25+, format="json"); файлы <процесс>_<PID>/ГГММДДЧЧ.log и <процесс>_<PID>_ГГММДДЧЧ.log |
| Журнал регистрации | старый формат: словарь 1Cv8.lgf и файлы записей *.lgp |
Журнал регистрации в формате SQLite (1Cv8.lgd) пока не поддерживается: для его чтения переключите базу на старый формат журнала.
Установка и запуск
opm install opentelemetry-v8-logs
opentelemetry-v8-logs # постоянная работа (то же, что run)
opentelemetry-v8-logs run --once # один проход, например из планировщика
opentelemetry-v8-logs --helpПриложение запускается на сервере 1С (или там, где доступны каталоги журналов) и берет настройки из autumn-properties.json текущего каталога, см. настройку. Однократный проход можно включить и переменной окружения OTEL_V8_LOGS_ONCE=true.
Демонстрация
В каталоге demo репозитория:
docker-compose.yml- стек LGTM в одном контейнере (grafana/otel-lgtm);loki-config.yaml- конфигурация Loki, в которой база (v8.infobase.name) - индексируемая метка;tempo-config.yaml- конфигурация Tempo, в которой спаны накопленных журналов находятся поиском по своему времени, см. состав телеметрии;autumn-properties.json- пример настроек приложения;logcfg.xml- пример настройки технологического журнала с событиями для трасс.
docker compose -f demo/docker-compose.yml up -d
cp demo/autumn-properties.json . # укажите свои каталоги журналов
opentelemetry-v8-logsGrafana: http://localhost:3000.
Производительность
Протокол http/protobuf SDK для OneScript сейчас кодирует данные заметно медленнее, чем http/json: на 1000 записей журнала сброс занимает около 6.5 с против 0.25 с. Рекомендуемый протокол - http/json. На этом протоколе приложение передает порядка 600 записей журнала регистрации в секунду, основное время уходит на создание записей в SDK.
Настройка
Настройки читаются из autumn-properties.json в текущем каталоге (или в каталоге профиля пользователя). Секция otel - настройки OpenTelemetry SDK и самого приложения (otel.v8-logs), секция data - база для позиций чтения, секция logos - логи коллектора.
Телеметрия коллектора и данные журналов отправляются под разными service.name:
- собственные логи и метрики коллектора - под
otel.service.name, с атрибутами хоста и процесса коллектора; - данные журналов - под
otel.v8-logs.service.name(илиservice-nameисточника), с атрибутами изotel.v8-logs.resource.attributesи без атрибутов процесса коллектора.
{
"otel": {
"enabled": true,
"service": { "name": "opentelemetry-v8-logs" },
"entity": { "enabled": false },
"exporter": { "otlp": { "endpoint": "http://localhost:4318", "protocol": "http/json" } },
"traces": { "exporter": "otlp" },
"metrics": { "exporter": "otlp" },
"logs": { "exporter": "otlp" },
"v8-logs": {
"service": { "name": "1c-cluster" },
"resource": { "attributes": "deployment.environment.name=prod" },
"timezone": "Europe/Moscow",
"techlog": [
{ "path": "/var/log/1c/techlog" }
],
"eventlog": [
{ "path": "/home/usr1cv8/.1cv8/1C/1cv8/reg_1541/<GUID базы>/1Cv8Log", "infobase": "erp", "service-name": "erp" }
]
}
},
"logos": {
"logger": { "rootLogger": { "level": "INFO", "appenders": ["otel", "console"] } },
"appender": {
"otel": { "type": "ОтелАппендерLogos", "level": "INFO" },
"console": { "type": "ВыводЛогаВКонсоль", "level": "INFO" }
}
},
"data": {
"ИсточникиДанных": {
"ТипКоннектора": "КоннекторSQLite",
"СтрокаСоединения": "Data Source=opentelemetry-v8-logs.db"
}
}
}otel.enabled нужен только для отправки собственных логов коллектора через ОтелАппендерLogos (autumn-opentelemetry). Вместе с ним по умолчанию включается инструментирование autumn-data, и каждый запрос к базе позиций стал бы спаном - поэтому в примере otel.entity.enabled выключен.
otel.v8-logs
| Параметр | По умолчанию | Описание |
|---|---|---|
service.name | 1c | service.name данных журналов. Должен отличаться от otel.service.name коллектора. |
resource.attributes | - | Атрибуты ресурса данных журналов в формате OTEL_RESOURCE_ATTRIBUTES: ключ=значение через запятую. otel.resource.attributes к данным не применяется. |
techlog | - | Массив каталогов технологического журнала (location в logcfg.xml). Элемент: path, необязательные service-name, infobase (база для событий с пустым p:processName, например у файловой базы), timezone, start-from-end, traces-mode. |
eventlog | - | Массив каталогов журнала регистрации (1Cv8Log). Элемент: path, infobase (имя базы; по умолчанию имя родительского каталога, то есть GUID базы), необязательные service-name, timezone, start-from-end. |
timezone | часовой пояс машины | Часовой пояс серверов 1С. Журналы пишутся в местном времени сервера, в OpenTelemetry время передается в UTC. Принимаются имена IANA (Europe/Moscow), Windows и GMT+03:00. |
start-from-end | false | При первом запуске пропустить уже накопленные данные. Файлы, появившиеся позже, читаются с начала. |
language | ru | Язык представлений событий журнала регистрации в теле записи и атрибуте v8.eventlog.event.presentation: ru или en. При другом значении используется идентификатор события. |
interval | 5 | Пауза между проходами без новых данных, секунд. Пока журналы отстают, проходы идут без пауз. |
batch-size | 1000 | Сколько записей передавать в SDK между сбросами буферов. Не больше размера очереди пакетного процессора (otel.blrp.max.queue.size, по умолчанию 2048). |
traces.enabled | true | Собирать трассы вызовов из технологического журнала. |
traces.root-events | CALL | События - корни трасс. Корневое событие закрывает трассу потока, поэтому событие, которое в вашем журнале бывает вложено в CALL того же потока, корнем делать нельзя: оно разорвет трассу вызова. |
traces.mode | auto | Режим сборки трасс: streaming - спаны отправляются сразу, buffered - события копятся до верхнеуровневого (для файловой базы), auto - накопление для процессов 1cv8 и 1cv8c, потоковый для остальных. См. состав телеметрии. |
OpenTelemetry SDK
Все параметры SDK - в его документации. Основные:
| Параметр | Описание |
|---|---|
otel.service.name | Имя сервиса самого коллектора. |
otel.resource.attributes | Дополнительные атрибуты ресурса коллектора. |
otel.metric.export.interval | Интервал экспорта метрик, мс; действует и для метрик данных. Для метрик данных используются настройки транспорта OTLP коллектора, а временная агрегация всегда кумулятивная. |
otel.exporter.otlp.endpoint | Адрес приемника OTLP. |
otel.exporter.otlp.protocol | Протокол: рекомендуется http/json, см. раздел о производительности. |
Параметры можно задавать и переменными окружения (OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT...).
Позиции чтения
Позиции хранятся в таблице ПозицииЧтения источника данных из секции data (autumn-data): подойдет файл SQLite или любой другой коннектор entity. Ключ позиции - полный путь к файлу журнала. Позиции удаленных файлов удаляются автоматически. Чтобы перечитать журналы заново, удалите базу позиций.
Настройка технологического журнала
Для трасс в ТЖ нужны события вызовов (CALL) и вложенные события (DBMSSQL, DBPOSTGRS, SDBL, TLOCK, EXCP...) со свойством OSThread, а для имен корневых вызовов - Context (в файловой базе код пользователя пишется без CALL, трассы строятся накоплением, см. состав телеметрии). Пример - demo/logcfg.xml.
Состав телеметрии
Время журналов 1С - местное время сервера, в OpenTelemetry оно передается в UTC по часовому поясу из настройки otel.v8-logs.timezone.
Ресурс
Данные журналов отправляются с отдельным ресурсом, не с ресурсом коллектора:
| Атрибут ресурса | Значение |
|---|---|
service.name | otel.v8-logs.service.name или service-name источника |
v8.infobase.name | информационная база: для журнала регистрации - infobase источника; для технологического журнала - свойство события p:processName, а если оно пустое - infobase источника |
атрибуты из otel.v8-logs.resource.attributes | как заданы |
Loki делает индексируемыми метками только атрибуты ресурса из своего списка (service.name и другие, см. документацию Loki), остальные сохраняются как структурированные метаданные. Чтобы база стала меткой v8_infobase_name, добавьте v8.infobase.name в limits_config.otlp_config Loki - пример в demo/loki-config.yaml.
В технологическом журнале p:processName бывает и не базой: в журнале файловой базы на macOS (8.3.27) у событий отладчика оно равно RemoteDebugger и DebugControlCenter, и эти значения тоже попадают в v8.infobase.name.
Технологический журнал
Логи
Каждое событие - запись лога (область инструментирования opentelemetry-v8-logs.techlog).
| Поле | Значение |
|---|---|
| Время | время окончания события |
| Тело | исходный текст события |
| Серьезность | из свойства события level: TRACE, DEBUG, INFO, WARNING - WARN, ERROR; без него или при другом значении - по имени события: ERROR для EXCP; WARN для ATTN, TDEADLOCK, TTIMEOUT; иначе INFO |
v8.techlog.event.name | имя события (CALL, DBMSSQL...) |
v8.techlog.duration | длительность, мкс |
v8.techlog.depth | уровень вложенности |
v8.techlog.<свойство> | свойства события как есть: v8.techlog.Usr, v8.techlog.t:clientID, v8.techlog.Sql...; повторяющиеся свойства - массивом |
process.executable.name, process.pid | процесс и PID из имени каталога или файла |
log.file.path | путь к файлу журнала |
Метрики
| Метрика | Тип | Атрибуты |
|---|---|---|
v8.techlog.event.duration, с | гистограмма | v8.techlog.event.name, process.executable.name, v8.infobase.name |
Трассы
Трасса - верхнеуровневое событие потока выполнения (процесс, OSThread и t:clientID, если он есть) со всеми событиями, вложенными в него по уровню и времени. Платформа пишет событие по окончании, поэтому вложенные события появляются в журнале раньше родителя. Сборщик исходит из того, что события одного уровня в одном потоке по времени не пересекаются, и тогда охват интервала [окончание - длительность, окончание] событием меньшего уровня означает, что событие - предок. В журналах автономного сервера ibsrv и файловой базы (macOS, 8.3.27) это выполняется.
Трассы собираются в одном из двух режимов (настройка otel.v8-logs.traces.mode).
Потоковый (streaming). Спан каждого события отправляется сразу при чтении. Корень трассы - событие вызова (CALL, настройка otel.v8-logs.traces.root-events) или событие уровня 0: ниже уровня 0 стека нет, и предка у такого события быть не может. Идентификатор родителя выдается заранее: событие уровня d ссылается на «слот» уровня d-1, а слот копит объединение интервалов своих потомков. Событие уровня d-1 занимает слот, только если его интервал охватывает всех потомков слота. Если уровень не пишется в журнал или следующее событие этого уровня не охватывает потомков, слот отправляется синтетическим спаном UNLOGGED с атрибутом v8.techlog.synthetic. Корень закрывает трассу потока; ожидавшие события, которые он не охватывает, закрываются отдельной трассой с синтетическим корнем. Трасса, в потоке которой больше часа не было событий, закрывается синтетическим корнем.
В журнале ibsrv код пользователя - например, запись документа - выполняется внутри CALL,0 (ib::worker::IInfoBaseWorkingContextCall.execute) того же потока, без t:clientID у вызова и его событий.
Накопление (buffered). В журнале файловой базы код пользователя выполняется в процессе клиента (1cv8c, 1cv8) без событий CALL, и верхнеуровневое событие становится известно, только когда записан его предок или стало ясно, что предка не будет. События потока копятся в памяти деревьями и отправляются: когда в потоке записано событие уровня 0 (охватить накопленные события после него не может ничто), после минуты без событий потока (по времени журнала, а после прохода, дочитавшего журналы, - по часам), при накоплении 10000 событий потока и при завершении работы. Каждое верхнеуровневое событие - например, SDBL Func=HoldConnection с транзакцией внутри или отдельный запрос - становится отдельной трассой. Записи лога отправляются сразу и со спаном не связаны: спан и его запись лога находятся по log.file.path и времени.
Режим по умолчанию auto: накопление для процессов 1cv8 и 1cv8c, потоковый для остальных. Так выбрано по наблюдению: клиент, подключенный к серверу, событий SDBL не пишет, а клиент файловой базы пишет. Режим можно задать явно для всех журналов или для источника (traces-mode).
Имена спанов
Имя спана состоит из имени события, операции и места вызова из последней непустой строки собственного Context. Кадр Модуль : строка : выражение сокращается до Модуль:строка, кадр без модуля — до <dynamic>:строка. Другой формат контекста сохраняется как текст. Контекст дочернего события не заменяет имя родительского вызова.
| Событие | Имя | Пример |
|---|---|---|
CALL фонового задания | Module.Method, если Func=Background job и оба поля заполнены | CALL Jobs.Run |
CALL с собственным Context | место вызова | CALL ОбщийМодуль.Обмен.Модуль:42 |
CALL, SCALL | интерфейс и метод (IName, MName или Method), иначе Func | SCALL ILogMngrData.writeLogEntryData, CALL Dynamic list search |
CALL, SCALL без метода и контекста | Func и, если доступны, Form.FormItem | CALL Dynamic list search · Документ.Заказ.Форма.ФормаДокумента.Список |
SDBL | Func, иначе вид запроса и таблица | SDBL HoldConnection, SDBL UPDATE Document54 |
DBMSSQL, DBPOSTGRS, DBORACLE, DB2 | вид запроса и таблица; для ODBC {call ...} — EXEC и имя процедуры; без запроса — Func | DBMSSQL INSERT _Document54, DBMSSQL EXEC sp_executesql |
TLOCK | пространства блокировок (Regions) | TLOCK Document54.REFLOCK |
EXCP | тип исключения и место вызова; без Context — первый кадр {Модуль(строка)} из Descr | EXCP RuntimeException · ОбщийМодуль.Test.Модуль:42 |
| синтетический | UNLOGGED |
У событий, кроме CALL с собственным контекстом и фоновых заданий, место вызова добавляется после операции через ·: DBMSSQL SELECT _Document54 · ОбщийМодуль.Test.Модуль:42. Операция ограничена 100 символами, модуль — 120 (сохраняется конец имени и номер строки), контекст неизвестного формата — 160. Исходные свойства остаются в атрибутах события. Значения SQL-параметров в имя из запроса не включаются.
Правила именования одинаковы для streaming, buffered и auto. В потоковом режиме спан отправляется сразу: отдельное событие Context, записанное после вызова, не меняет его имя. Для этих правил нужен Context в свойствах самого события.
| Событие | Спан |
|---|---|
CALL | вид SERVER |
DBMSSQL, DBPOSTGRS, DBORACLE, DB2 | вид CLIENT, db.system.name |
EXCP | вид INTERNAL, статус ERROR, событие exception (exception.type, exception.message) |
| остальные | вид INTERNAL |
Атрибуты спанов - те же, что у записей лога. В потоковом режиме каждая запись лога события содержит trace_id и span_id спана этого события: из Loki можно перейти в трассу в Tempo и обратно.
Состояние трасс хранится в памяти. Если приложение перезапустится посреди вызова, в потоковом режиме вложенные события, отправленные до перезапуска, сошлются на родителя, который не придет; в режиме накопления при аварийном завершении накопленные спаны теряются (при штатном - отправляются).
Для трасс в журнал нужно писать свойство OSThread, а для места вызова в именах спанов — Context.
Время спана - время события в журнале. Tempo записывает в метаданные блока время поступления данных, если время спанов отстоит от него больше, чем на ingestion_time_range_slack (по умолчанию 2 минуты), а поиск по интервалу времени выбирает блоки по метаданным. Поэтому спаны, выгруженные при первом запуске по накопленным журналам или при догоне после простоя, с настройками Tempo по умолчанию поиском по своему времени не находятся; по идентификатору трассы, в том числе из записи лога в Loki, они открываются. В demo/tempo-config.yaml запас увеличен до срока хранения блоков (336h) в разделах storage.trace.wal, live_store.wal и block_builder.wal (Tempo 3).
Журнал регистрации
Логи
Каждая запись - запись лога (область инструментирования opentelemetry-v8-logs.eventlog). Пустые поля не передаются.
| Поле | Значение |
|---|---|
| Время | время записи |
| Тело | строка как в просмотре журнала, части через |: представление события (v8.eventlog.event.presentation); у событий с объектом метаданных или данными - объект, представление данных (без него - данные) и пользователь, у остальных - приложение, пользователь и session=<номер>, значения как в журнале. Пустые части пропускаются, комментарий - с новой строки. Например, Данные. Проведение | Document.Document | Document 000000001 dated 10/20/2026 12:56:10 PM, Сеанс. Начало | 1CV8C | session=2 |
| Серьезность | E - ERROR, W - WARN, I - INFO, N (примечание) - DEBUG |
v8.eventlog.event | идентификатор события (_$Session$_.Start, _$Data$_.Post...) |
v8.eventlog.event.presentation | представление события, как в просмотре журнала, на языке из настройки otel.v8-logs.language: «Данные. Проведение» или «Data. Posting». У событий без представления (события пользователя, события, которых нет в платформе 8.3.27) - идентификатор события, поэтому атрибут заполнен у всех записей |
user.name, user.id | имя и идентификатор пользователя |
v8.eventlog.computer, v8.eventlog.application | компьютер и приложение |
v8.eventlog.connection, v8.eventlog.session | соединение и сеанс |
v8.eventlog.transaction.status | committed (код C), rolled_back (код R): в журналах с этими кодами записаны события _$Transaction$_.Commit и Rollback |
v8.eventlog.transaction.status_code | код статуса транзакции как есть: C, R, U (у изменений данных внутри транзакции; значение не расшифровывается) |
v8.eventlog.transaction.id | номер транзакции |
v8.eventlog.metadata, v8.eventlog.metadata.uuid | объект метаданных |
v8.eventlog.data | Структурированный OTLP-атрибут с полями известной формы Data; для неизвестной формы — строка JSON с исходным деревом, для скаляра — текстовое значение. Подробнее о разборе Data. |
v8.eventlog.data.presentation | представление данных |
v8.eventlog.server, v8.eventlog.port, v8.eventlog.sync_port | рабочий сервер и порты |
v8.eventlog.data_separation.<разделитель> | значения разделителей сеанса |
log.file.path | путь к файлу журнала |
Метрики
| Метрика | Тип | Атрибуты |
|---|---|---|
v8.eventlog.records | счетчик | v8.eventlog.event, v8.eventlog.severity, v8.infobase.name, v8.eventlog.application |
Содержимое Data журнала регистрации
Содержимое поля Data передается в атрибуте v8.eventlog.data: для известных полей — структурированный объект OTLP (kvlistValue), для неизвестной формы — компактная строка JSON, для скаляров — прежнее текстовое значение. Пустой объект также сохраняется строкой JSON, чтобы приемник не потерял его при разворачивании. Известные поля не дублируются отдельной JSON-строкой. v8.eventlog.data.presentation, текст тела лога, ресурсы и метрики сохраняются. Включать настройку не требуется.
Правила разбора разработаны в форке OneSTools.EventLog и проверены на искусственных примерах, сопоставленных с выгрузкой платформы 8.3.27.2325. Имена из синтакс-помощника используются после подтверждения реального расположения полей: порядок перечисления в справке не совпадает с порядком значений LGP. Наличие события в таблице ниже не означает распознавание всех его вариантов. Проверяются код события, маска, количество и типы элементов. Именованные пары распознаются в русском и английском вариантах: Имя / Name, Данные / Data, Ссылка / Reference. На тестовой платформе 8.3.27.2325 язык этих ключей определялся вариантом встроенного языка конфигурации (Russian / English); переключение интерфейса и региональных настроек базы их не меняло.
События описаны декларативным OneScript-кодом в ПоляДанныхСобытийЖурналаРегистрации. Один блок объединяет поля, их типы, формы входной записи и преобразования JSON. Декодер читает готовые описания без ветвлений по кодам событий и именам полей. ИменаПолей, Биты, Способ выводятся из поддерживаемых форм; нераспознаваемые варианты в реестр не включаются. Для совместимости JSON использует AuthenticationMethod и Vendor у ConfigUpdate, как в проверенной выгрузке 8.3.27.
Добавление события
Пример битовой формы аутентификации:
Формы = Новый КонструкторыДанныхЖурналаРегистрации;
Реестр.Событие("_$Session$_.Authentication")
.Аналоги("_$Session$_.AuthenticationError")
.Поле("Name").ТипПоля("Строка").Бит(1)
.Поле("CurrentOSUser").ТипПоля("Строка").Бит(2)
.Поле("AuthenticationMethod").ТипПоля("Число").Бит(9)
.Поле("OSUser").ТипПоля("Строка").Бит(0)
.Форма(Формы.ПоМаске("P", "518"))
.Форма(Формы.ПоМаске("P", "514"))
.Форма(Формы.ПоМаске("P", "513"))
.Зарегистрировать();Поля битовой формы читаются по возрастанию номеров битов. Распознаются только перечисленные маски; новая комбинация сохраняется исходным деревом.
ТипПоля(...) принимает Строка, Число, Булево, Дата, Ссылка, МассивСсылок, МассивСтрок, Незаданное, Таблица. Имя Тип() занято встроенной функцией OneScript. Способ вывода настраивается отдельно:
.Поле("Roles").ТипПоля("МассивСсылок").Пропустить()
.Поле("Roles").ТипПоля("МассивСсылок").Как("UserRoles")
.Поле("Roles").ТипПоля("МассивСсылок").Как("RolesCount", Агрегаты.Количество())
.Поле("Roles").ТипПоля("МассивСсылок").Как("UniqueRolesCount", Агрегаты.КоличествоУникальных())Это четыре альтернативы: исключить из JSON, переименовать с сохранением массива, заменить массив количеством всех или только различных элементов. Агрегаты — экземпляр КонструкторыДанныхЖурналаРегистрации. Пропущенное поле все равно читается и проверяется. .Значение("0", "false").Значение("3", "true") задает карту допустимых значений; неизвестный код приводит к сохранению исходного дерева.
КоличествоУникальных() применяется к массивам строк и ссылок. Строки различаются регистром и пробелами; пустая строка тоже считается значением. Ссылки сравниваются по паре UUID типа и объекта, без учета регистра UUID. Для пустого массива результат "0"; количество передается строкой, как и у Количество(). Счетчик массива и все элементы проверяются до возврата результата. Поврежденное значение сохраняется исходным деревом. Множество уникальных ключей создается только для этого агрегата; обычный подсчет обходится без хранения элементов.
Позиционные формы задаются через Формы.Позиционная("P", "65534"). Второй аргумент — необязательный точный маркер, который не обязательно является битовой маской. Состав и порядок задаются одним из способов:
.ВсеПоля()— порядок объявления полей события..ВсеПоляКроме("DefaultInterface")— поле физически отсутствует во входе; позиции следующих полей сдвигаются. Для нескольких имен допустим CSV или массив..Поля("Name,OSUser")— явный порядок; также принимает массив имен..Поле("Name").Поле("OSUser")— тот же явный порядок цепочкой вызовов.
Для вложенной записи используется Формы.Структура("P") с точным .Размер(...), условиями .РазмерУзла(...), .Литерал(...) и .ПолеПоПути(...). Путь "1.1" означает второй элемент второго списка тела; индексы начинаются с нуля. При регистрации проверяются типы, ссылки на поля, биты, повторные коды событий и выходные ключи JSON. Ошибочное описание не добавляется в реестр.
Подтвержденные формы
| События (суффиксы после системной группы) | Содержимое |
|---|---|
User.AuthenticationLock, AuthenticationUnlock, AuthenticationUnlockError; Session.PasswordRequirementsViolationOnAuthentication | Name, включая пустую строку |
Session.Authentication, AuthenticationError | формы 513, 514, 518: OSUser / Name, CurrentOSUser, AuthenticationMethod |
User.New, Update, NewError, UpdateError | формы 65535 и 65534: свойства пользователя, ссылки на язык/интерфейс, RolesCount, настройки второго фактора и политики паролей |
User.Delete, DeleteError; Session.ConfigExtensionApplyError | Name |
InfoBase.UserPasswordPolicyNew, UserPasswordPolicyNewError, UserPasswordPolicyUpdate | форма 255: девять свойств политики, включая проверку компрометации и действие при нарушении требований |
InfoBase.UserPasswordPolicyDelete, UserPasswordPolicyDeleteError | Name |
InfoBase.ParametersUpdate, ParametersUpdateError | подтвержденные маски параметров базы: пароли, блокировка аутентификации, ожидание блокировки и завершение неактивных сеансов |
InfoBase.AdditionalAuthenticationSettingsUpdate | 45 отдельных масок параметров и форма 2564; методы восстановления и отправки кодов, SMTP, интервалы и проверки компрометации |
InfoBase.ConfigUpdate, DBConfigUpdate, ConfigUpdateError, DBConfigUpdateError | Vendor, Version |
InfoBase.ExclusiveModeChange, ExclusiveModeChangeError | ExclusiveMode |
Access.Access, AccessDenied | таблица Data, либо Right, либо Action и незаданные Data |
InfoBase.SecondAuthenticationFactorTemplateNew, SecondAuthenticationFactorTemplateUpdate, SecondAuthenticationFactorTemplateDelete | Name |
InfoBase.EventLogSettingsUpdate, EventLogSettingsUpdateError | Levels либо EventName, EventIsLogged |
InfoBase.EventLogReduce, EventLogReduceError | Date |
InfoBase.RegionalSettingsChange | 11 свойств региональных установок |
Session.ExternalDataProcessorConnect, ExternalDataProcessorConnectError, ExternalReportConnect, ExternalReportConnectError | путь, имя, безопасный режим, профиль безопасности, защита от опасных действий и язык |
Session.AddInAttach, AddInAttachError | Name, Location, незаданные Type, AttachmentType |
InfoBase.SessionLockChange, SessionLockChangeError | Use, Begin, End, Message, KeyCode, Parameter |
InfoBase.ConfigExtensionUpdate, DBConfigExtensionInsert, DBConfigExtensionInsertError, DBConfigExtensionDelete, DBConfigExtensionDeleteError, DBConfigExtensionUpdate, DBConfigExtensionUpdateError | 15 свойств расширения: имя, версия, поставщик, UUID, хэш, синоним, режимы, профиль, назначение, область и роли |
Data.DataHistorySettingsUpdate, PredefinedDataInitialization, UpdatePredefinedData; InfoBase.PredefinedDataUpdate | таблица Data в подтвержденной именованной форме |
Всего специальные правила охватывают 56 кодов событий. Для остальных возможен общий разбор именованных пар; неподтвержденные формы сохраняются целиком.
Представление значений
Числа и булевы значения в разобранных данных представлены строками ("0", "false"), как в исходном декодере. Это сохраняет точность длинных чисел и единый контракт. Даты — локальные значения 1С yyyy-MM-ddTHH:mm:ss, без добавления часового пояса. Пустая дата сохраняется как 0001-01-01T00:00:00. Пустые строки не удаляются. null означает незаданное поле подтвержденной формы; в общем разборе U сохраняется явно как {"$type":"U"}.
Например, блокировка аутентификации: {"Name":"FixtureUser"}.
Для подтвержденных форм User.New, Update, NewError, UpdateError свойства пользователя находятся прямо в корне объекта, без $format, values и nodes. Состав ролей пользователя намеренно не экспортируется; вместо списка UUID сохраняется RolesCount. Точный состав ролей из телеметрии восстановить нельзя. DefaultRoles расширения остается отдельным полем.
Для остальных позиционных форм используется конверт 1c-positional-data-v1: layout, values, unnamedFields, nodes. Для общих именованных пар — 1c-named-data-v1: values, nodes. Ссылки сохраняют идентификаторы, без попытки прочитать объект из информационной базы. Для неизвестных форм расположение ролей не угадывается: сохраняется исходное дерево. Если маска, число или типы полей неизвестны, возвращается {"$format":"1c-brackets-v1","nodes":[...]}. nodes сохраняет дерево и исходный текст листьев, включая удвоенные кавычки. Переход на новую платформу не приводит к угадыванию полей.
Поиск в Loki
При штатном приеме OTLP Loki разворачивает поля объекта в structured metadata: v8.eventlog.data.Name становится v8_eventlog_data_Name. Эти поля не добавляются в индексные метки и доступны без разбора JSON в запросе. Например:
{service_name="erp"} | v8_eventlog_data_Name="FixtureUser"Loki хранит значения metadata строками: незаданные значения (null) в результатах запросов не отображаются, а массив передается JSON-строкой. Сам OTLP-атрибут сохраняет вложенные объекты, массивы, пустые строки и незаданные значения. Другие приемники могут представлять их иначе. При нормализации имен точки и другие неподдерживаемые символы заменяются на _.
Неизвестные формы по-прежнему находятся в v8_eventlog_data как JSON-строка.
Подставьте service.name своего источника и период журнала. Поля Data следует оставлять атрибутами логов, не добавляя их в индексные метки Loki или в разрезы метрик.
