Чем читать логи Directum RX: инструменты для лог-файлов и как найти ошибку за пять минут
Лог-файлы Directum RX пишутся строками JSON, и в обычном блокноте их не прочитать. Какие инструменты подходят на рабочем месте и на сервере (Notepad++, LogExpert, DirectumLogConverter, jq, lnav), готовые команды для поиска ошибок по времени, пользователю и трассе и грабли, на которых теряются строки.
Коротко. Журналы RX это JSON по строке в каталоге
LOGS_PATH. На рабочем месте их удобно читать в Notepad++ с JSTool, LogExpert или переводить в CSV утилитой вендора DirectumLogConverter. На сервере фильтровать черезjq -R 'fromjson?', чтобы битые строки не обрывали разбор, или смотреть в lnav одной лентой по всем сервисам. Порядок поиска: время и пользователь, ошибка в журнале веб-сервера, трассаtrчерез все сервисы, тип исключения.
Пользователь пишет, что в 10:15 не сохранился документ. Администратор открывает папку с логами, видит два десятка файлов по несколько сотен мегабайт и открывает самый большой в блокноте. Через десять минут он прокручивает стену из фигурных скобок, а ошибки так и не нашёл. Журналы RX рассчитаны на разбор программами, и глазами их читать тяжело. Ниже разберём, чем их открывать на рабочем месте и на сервере, и порядок поиска, который приводит к причине за несколько минут.
Симптом
- Файлы большие, в одной строке сотни символов, перенос строк превращает запись в абзац.
- Поиск по слову
Errorнаходит тысячи совпадений, в том числе в тексте сообщений и именах методов. - Ошибка в одном сервисе, а причина в другом, и непонятно, как связать записи двух файлов.
- Часть записей не открывается форматировщиком JSON, и инструмент падает на середине файла.
Почему так
Сервисы Directum RX пишут журналы в структурированном виде: одна запись на строку, каждая запись это объект JSON. Такой формат удобен для автоматического разбора и сбора в хранилище, но без подсветки и фильтров читать его тяжело.
Где лежат файлы. На Linux каталог задаётся параметром LOGS_PATH в config.yml Directum Launcher, по умолчанию
это <папка с данными>/logs. Имя файла собрано из имени компьютера, контейнера, сервиса и даты:
rx01-web.WebServer.2026-10-22.log
rx01-worker.Worker.2026-10-22.log
rx02-preview.PreviewService.2026-10-22.log
Журналы веб-клиента и веб-агента лежат в подпапке remote, по файлу на компьютер пользователя и учётную запись.
Журналы самого Directum Launcher хранятся отдельно, в папке DirectumLauncher/log: там ищут ошибки установки
и обновления.
Что в записи. Самые нужные поля:
| Поле | Что в нём |
|---|---|
t |
время с часовым поясом: 2026-10-22 10:15:03.412+03:00 |
l |
уровень: Fatal, Error, Warning, Info, Debug, Trace |
lg |
логгер, то есть компонент, который написал запись |
mt |
текст сообщения, иногда объект |
ex |
исключение: тип type, текст m, стек stack |
span |
операция и её длительность в durationMs |
un |
учётная запись пользователя |
tr |
трасса: связывает записи одного действия во всех сервисах |
Полный список полей и разбор каждого есть в статье про сбор журналов через Vector.
Трасса. Поле tr выглядит как cl-4e326a73-7815ae. Первая часть общая для всего действия: пользователь
нажал кнопку в веб-клиенте (префикс cl), веб-сервер обратился к сервису хранилищ, тот к сервису предпросмотра,
и у всех этих записей начало трассы одинаковое. Префикс показывает, где действие началось: cl веб-клиент,
ws веб-сервер, js планировщик, do отложенные операции, wk сервис асинхронных событий. По трассе можно
собрать полную историю одного действия из файлов разных сервисов.
Инструменты на рабочем месте
Вендор в документации называет несколько программ. Все они работают на Windows, файлы забирают с сервера.
- Notepad++ с плагином JSTool. Подсвечивает и форматирует строку JSON по
Ctrl+Alt+M, ищет по всем открытым файлам сразу. Ищите"Error"в кавычках: так находятся записи уровня ошибки, а не каждое слово Error в тексте. - Visual Studio Code. То же самое плюс многострочный поиск по регулярным выражениям в целой папке.
- LogExpert и LogViewPlus. Специальные просмотрщики журналов: держат открытыми файлы на гигабайты, обновляют их по мере записи, умеют фильтры и подсветку по условию. Вендор рекомендует их для журналов мобильных сервисов, но для серверных они подходят так же.
- DirectumLogConverter. Утилита вендора, лежит на GitHub. Переводит журнал в простой текст (
dlc файл.log) или в CSV (dlc -c файл.log), после чего файл открывается в Excel с фильтрами по колонкам. Для разовых разборов и для передачи коллегам, которые не работают с консолью, это самый быстрый путь.
Ограничение у всех этих способов одно: файлы надо скопировать к себе, а за инцидент их набирается много.
Инструменты на сервере
На сервере с Linux удобнее не копировать гигабайты, а фильтровать на месте.
jq: отфильтровать и посчитать
jq есть в репозиториях всех дистрибутивов. Журнал нужно читать построчно через -R и разбирать каждую
строку с fromjson?. Если открыть файл как обычный JSON, jq остановится на первой битой строке и молча потеряет
всё, что после неё. Битые строки бывают: веб-агент пишет пути Windows с одиночным обратным слешем, и такая
строка не является корректным JSON.
Ошибки за конкретные пять минут во всех журналах сервера:
cd /srv/logs
jq -rR 'fromjson? | select(.l == "Error" and .t >= "2026-10-22 10:15" and .t < "2026-10-22 10:20")
| [.t, .lg, (.ex.type // "-"), (.mt | tostring)] | @tsv' *.log | sort
Сравнение времени строками работает, потому что время записано в одном формате и в одном часовом поясе сервера.
Какие ошибки случаются чаще всего за день:
jq -rR 'fromjson? | select(.l == "Error") | "\(.ex.type // "-") \(.ex.m // (.mt | tostring))"' \
*.2026-10-22.log | sort | uniq -c | sort -rn | head -20
Всё, что делал пользователь:
jq -rR 'fromjson? | select(.un == "ivanova") | [.t, .l, .lg, (.span.name // (.mt | tostring))] | @tsv' \
*.2026-10-22.log | sort
Одно действие по трассе через все сервисы. Сначала находим ошибку, берём из неё начало поля tr, затем:
grep -h '"tr":"cl-4e326a73' *.2026-10-22.log \
| jq -rR 'fromjson? | [.t, .lg, .l, (.span.name // (.mt | tostring))] | @tsv' | sort
Медленные операции, дольше трёх секунд:
jq -rR 'fromjson? | select(.span.durationMs? > 3000) | [.t, .span.name, .span.durationMs] | @tsv' \
*.2026-10-22.log | sort -t$'\t' -k3 -rn | head
Стек исключения целиком, с переносами строк:
jq -rR 'fromjson? | select(.ex.type == "Npgsql.PostgresException") | .t, .ex.stack, ""' *.log | head -40
lnav: читать глазами
lnav это консольный просмотрщик журналов. Он склеивает файлы разных сервисов в одну ленту
по времени, подсвечивает уровни, фильтрует и даже выполняет SQL по полям. Формат RX ему надо описать один раз:
файл ~/.lnav/formats/installed/directum_rx.json.
{
"$schema": "https://lnav.org/schemas/format-v1.schema.json",
"directum_rx": {
"title": "Directum RX",
"json": true,
"file-pattern": "\\.log$",
"timestamp-field": "t",
"timestamp-format": ["%Y-%m-%d %H:%M:%S.%L%z"],
"level-field": "l",
"level": {
"fatal": "Fatal", "error": "Error", "warning": "Warning",
"info": "Info", "debug": "Debug", "trace": "Trace"
},
"body-field": "mt",
"opid-field": "tr",
"line-format": [
{ "field": "__timestamp__" }, " ",
{ "field": "__level__", "text-transform": "uppercase", "min-width": 7 }, " ",
{ "field": "lg", "max-width": 40, "overflow": "dot-dot" }, " ",
{ "field": "un", "default-value": "-" }, " ",
{ "field": "mt", "default-value": "" },
{ "prefix": " ", "field": "ex/type", "default-value": "" },
{ "prefix": " ", "field": "ex/m", "default-value": "" },
{ "prefix": " span=", "field": "span/name", "default-value": "" },
{ "prefix": " ms=", "field": "span/durationMs", "default-value": "" }
],
"value": {
"lg": { "kind": "string", "identifier": true },
"un": { "kind": "string", "identifier": true },
"tr": { "kind": "string", "identifier": true },
"mt": { "kind": "string" },
"ex": { "kind": "json" },
"ex/type": { "kind": "string", "identifier": true },
"ex/m": { "kind": "string" },
"span": { "kind": "json" },
"span/name": { "kind": "string", "identifier": true },
"span/durationMs": { "kind": "integer" },
"args": { "kind": "json", "hidden": true },
"cust": { "kind": "json", "hidden": true },
"pid": { "kind": "string", "hidden": true },
"v": { "kind": "string", "hidden": true }
}
}
}
После этого lnav /srv/logs/*.2026-10-22.log показывает все сервисы одной лентой:
2026-10-22 10:15:03.412+03:00 ERROR Sungero.Domain.Shar..oteFunctionExecutor petrov Error while executing remote function {name} Npgsql.PostgresException 57014: canceling statement due to statement timeout
tr: cl-9a1b2c3d-81fa02
2026-10-22 10:15:03.900+03:00 ERROR RabbitMqConnectionsProvider - RabbitMQ connection '{connectionName}' recovery failed. System.AggregateException One or more errors occurred. (Connection failed)
Полезные приёмы внутри lnav: e и E прыгают к следующей и предыдущей ошибке, :filter-in petrov оставляет
записи пользователя, :filter-out TraceSpan убирает служебные замеры. Сводка по типам ошибок одним запросом:
;SELECT log_level, "ex/type", count(*) AS n FROM directum_rx GROUP BY 1, 2 ORDER BY n DESC
Формат мы проверили на lnav 0.14 на журналах в формате RX. Битые строки веб-агента lnav, как и jq, пропускает
без предупреждения: если ищете проблему веб-агента, проверьте файл ещё и обычным grep.
Windows и PowerShell
Если сервисы RX работают на Windows, тот же приём делается средствами PowerShell:
Get-Content .\rx01.WebServer.2026-10-22.log |
ForEach-Object { try { $_ | ConvertFrom-Json } catch {} } |
Where-Object { $_.l -eq 'Error' } |
Select-Object t, lg, @{n='ex'; e={$_.ex.type}}, mt
try вокруг разбора нужен по той же причине, что fromjson? в jq: одна битая строка не должна останавливать
обработку.
Как найти ошибку за пять минут
- Узнать время и пользователя. «Утром не сохранилось» не годится: попросите время с точностью до минут, учётную запись и что именно делали. Если пользователь не помнит, ищите по учётной записи за весь день.
- Найти запись в журнале веб-сервера. Большинство действий пользователя начинается там. Фильтр: уровень Error, окно в пять минут вокруг времени, при возможности учётная запись.
- Взять трассу и пройти по всем сервисам. Начало поля
trиз найденной записи ищется во всех файлах за день. Так видно, в каком сервисе действие сломалось на самом деле: веб-сервер часто сообщает только то, что ему не ответили. - Прочитать исключение снизу вверх. Тип исключения и первые строки стека показывают слой:
Npgsqlэто база данных,RabbitMQ.Clientброкер,System.Netсеть или прокси. Текст вроде57014: canceling statement due to statement timeoutуже готовое направление для поиска: что он значит, разобрано в справочнике ошибок. - Проверить, единичный ли это случай. Тот же тип ошибки за день, сгруппированный по часам. Если ошибка повторяется весь день, искать стоит в инфраструктуре, а не в действиях пользователя.
Когда серверов больше одного
Все приёмы выше работают на одном сервере. Если сервисы разнесены по нескольким машинам, трасса уходит в файлы на других серверах, и разбор превращается в обход по SSH. Здесь помогает только сбор журналов в одно место: как это устроить и во что упирается хранение, разобрано в статье «Логи Directum RX: что собирать». Если отдельного хранилища нет, лёгкий вариант на одном сервере без интернета мы собрали в мониторинг в коробке: журналы RX там разбираются на поля, и поиск по трассе или пользователю делается в веб-интерфейсе.
Чего не делать
- Не открывать журнал на сотни мегабайт в «Блокноте» на сервере. Редактор загрузит файл целиком в память рабочего сервера и может зависнуть вместе с сеансом.
- Не искать слово Error без кавычек. Найдутся имена методов и тексты сообщений, а записи уровня Warning
с настоящей причиной останутся незамеченными. Ищите
"l":"Error"или фильтруйте по полю. - Не разбирать журнал обычным
jq .. Первая битая строка остановит разбор, и остаток файла вы не увидите, не получив внятной ошибки. - Не удалять журналы вручную, чтобы освободить место. У Directum Launcher для этого есть команда
./do.sh clean_logs --skip_last_modified_days=7, её ставят в расписание. Сами журналы лучше держать на отдельном диске: если он переполнится, RX перестанет писать журналы, но системный диск и сама ОС не пострадают. - Не отправлять вендору «все логи за месяц». Поддержке нужны время ошибки и журналы за этот день со всех серверов. Архив на десятки гигабайт задержит ответ.
Похожая картина у вас?
Разберём ваш контур за 30 минут бесплатного созвона: версия RX, состав сервисов, что болит сильнее всего.
Написать