Отличная ошибка! Вы столкнулись с особенностью языка VRL (Vector Remap Language) — он fail-safe (отказоустойчивый). Это значит, что программа не скомпилируется, если в ней есть хотя бы один необработанный потенциальный сбой. Ошибка 103 говорит именно об этом: выражение merge(., parsed) может упасть, и вы должны явно указать, что делать в случае ошибки. Вот исправленная секция transforms для вашего vector.yaml, которая учитывает все возможные проблемы: ```yaml transforms: add_nomad_metadata: type: remap inputs: ["docker_logs"] source: |- # 1. БЕЗОПАСНО добавляем метаданные Nomad (они всегда есть) .nomad = { "job_id": "${NOMAD_JOB_ID}", "job_name": "${NOMAD_JOB_NAME}", "task_name": "${NOMAD_TASK_NAME}", "alloc_id": "${NOMAD_ALLOC_ID}", "node_id": "${NOMAD_NODE_ID}", "node_name": "${NOMAD_NODE_NAME}", "datacenter": "${NOMAD_DC}" } # 2. БЕЗОПАСНО парсим JSON, ЕСЛИ поле .message - строка if is_string(.message) { # Пытаемся распарсить. В случае ошибки parsed будет null, а err - описанием ошибки. parsed, err = parse_json(.message) if err == null { # Если парсинг прошел успешно И результат - объект (не массив, не строка) if is_object(parsed) { # Используем "паникующий" merge! потому что мы УВЕРЕНЫ в типах на 100% # . - это объект (весь лог), parsed - тоже объект (результат парсинга) . = merge!(., parsed) } else { # Если внутри .message был валидный JSON, но это массив или строка, # сохраняем его в отдельное поле, чтобы не сломать структуру. .parsed_json = parsed } } else { # Логируем ошибку парсинга (опционально, для отладки) .parse_error = err } } # 3. (Опционально) Удаляем временное поле с ошибкой, если оно пустое if is_null(.parse_error) { del(.parse_error) } ``` 🔍 Что было исправлено и почему 1. Ошибка 103 (Unhandled fallible assignment) — исправлена заменой merge(., parsed) на конструкцию с обработкой ошибки. Теперь программа не "упадет", если parsed окажется не объектом. 2. Проверка типа parsed — добавлена проверка if is_object(parsed). Функция parse_json может вернуть не только объект ({...}), но и массив ([...]), строку или число, если JSON верхнего уровня — это примитив или массив. Слияние (merge) работает только с объектами. Без этой проверки вы бы получили новую ошибку на этапе выполнения. 3. Использование merge! — внутри блока if is_object(parsed) мы на 100% уверены, что parsed — это объект, а . (исходный лог) — всегда объект. Поэтому можно использовать "паникующий" вариант merge!, который не требует обработки ошибок (так как их просто не может быть из-за наших проверок). 4. Обработка краевых случаев: · Если поле message не строка — JSON не парсится (это нормально для бинарных логов). · Если внутри message был JSON-массив (например, ["log1", "log2"]), он сохранится в поле .parsed_json, а структура основного события не сломается. · Если произошла ошибка парсинга, она сохранится в поле .parse_error (потом удаляется для чистоты). 📝 Полный исправленный конфиг для вашего шаблона Nomad Замените содержимое вашего template в задании Nomad на этот исправленный YAML: ```yaml data_dir: "${NOMAD_ALLOC_DIR}/vector/data" api: enabled: true address: "0.0.0.0:${NOMAD_PORT_api}" sources: docker_logs: type: docker_logs include_containers: ["*"] transforms: add_nomad_metadata: type: remap inputs: ["docker_logs"] source: |- .nomad = { "job_id": "${NOMAD_JOB_ID}", "job_name": "${NOMAD_JOB_NAME}", "task_name": "${NOMAD_TASK_NAME}", "alloc_id": "${NOMAD_ALLOC_ID}", "node_id": "${NOMAD_NODE_ID}", "node_name": "${NOMAD_NODE_NAME}", "datacenter": "${NOMAD_DC}" } if is_string(.message) { parsed, err = parse_json(.message) if err == null { if is_object(parsed) { . = merge!(., parsed) } else { .parsed_json = parsed } } else { .parse_error = err } } if is_null(.parse_error) { del(.parse_error) } sinks: openobserve: type: http inputs: ["add_nomad_metadata"] uri: "http://openobserve.service.consul:5080/api/default/default/_json" method: "post" compression: "gzip" encoding: codec: "json" timestamp_format: "rfc3339" auth: strategy: "basic" user: "{{ key "openobserve/user" }}" password: "{{ key "openobserve/password" }}" buffer: type: "disk" max_size: 268435488 when_full: "drop_newest" healthcheck: enabled: false ``` 🚀 После исправления 1. Перезапустите задание: ```bash nomad job stop vector nomad job run vector.nomad ``` 2. Проверьте логи: Ошибка компиляции VRL должна исчезнуть. В OpenObserve будут приходить обогащенные логи, а если внутри message был валидный JSON, его поля "поднимутся" на верхний уровень события для удобной фильтрации. Такой подход делает трансформацию устойчивой к любым нестандартным данным в логах, что критически важно для production-сред. } } } } } } } } } } } } } }