Фильтры и трансформеры
Мапперы превращают сырое событие в поля инцидента. Маппер — это список правил; каждое правило берёт значение из сырого payload (по пути источника данных) и пишет его в целевое поле. Между чтением и записью правило может гонять два вида операторов:
- Фильтры отбирают — они оставляют или отбрасывают значения до маппинга.
- Трансформеры изменяют — они переформовывают значение, которое записывается.
Эта глава объясняет, как ведут себя оба вида, как они компонуются и как они обрабатывают отсутствующие или странно устроенные данные. Полный каталог по каждому оператору — каждый идентификатор, его аргументы и разобранный пример — живёт в файле-спутнике Справочник фильтров и трансформеров маппера. Операторов 148: 138 трансформеров и 10 фильтров.
Где это появляется в продукте. Фильтры и трансформеры настраиваются на каждое правило в редакторе маппера (Objects Setup → маппер для типа инцидента). Та же библиотека операторов также питает output-трансформеры на узлах-задачах плейбуков Automation Engine (см. §5.6).
5.1. Фильтры и трансформеры — в чём разница
Фильтр отвечает на вопрос «стоит ли это значение (или эти элементы) вообще маппить?». Он никогда не меняет содержимое элемента; он лишь оставляет или отбрасывает. Над массивом он оставляет элементы, которые проходят; получив один скаляр, он трактует его как один элемент, и скаляр, не прошедший фильтр, отбрасывается — значение становится отсутствующим, и правило откатывается к своему значению по умолчанию (если оно есть). Фильтры — это как вы чистите список (убираете пустые, дедуплицируете) или сужаете его (оставляете только объекты, совпадающие с условием) до того, как что-либо ещё отработает.
Трансформер отвечает на вопрос «чем должно стать значение?». Он переформовывает:
обрезает строку, форматирует дату, извлекает IP из текста, склеивает список в одну
строку, выбирает поле из объекта и так далее. Трансформеры могут менять тип
значения — stringCount превращает строку в число, split превращает строку в
массив, keys превращает объект в массив.
Оба вида выбираются из одного и того же пикера в редакторе маппера, но живут в двух отдельных списках на правиле: список filters (where) и список transformers.
5.2. Как выполняется правило (порядок операций)
Для каждого правила маппинга движок гоняет фиксированную последовательность:
- Прочитать значение по пути источника данных правила из сырого payload.
- Фильтры отрабатывают, в порядке списка, над этим значением.
- Значение по умолчанию. Если значение теперь пусто (отсутствует,
nullили"") и правило определяет значение по умолчанию, здесь подставляется умолчание. - Трансформеры отрабатывают, в порядке списка, над значением.
- Записать результат в целевое поле, с учётом overwrite policy правила
(
always,neverили толькоif_empty). Правило, помеченное required, но всё же не произведшее значения, поднимает предупреждение.
Важное следствие: фильтры всегда отрабатывают до трансформеров, а значение по
умолчанию применяется между ними. Так что нельзя в пределах одного правила
трансформировать значение, а затем фильтровать по трансформированному результату —
фильтрация происходит первой, над сырым значением. Если нужно «трансформировать,
затем решить», смоделируйте это как два правила или используйте условный трансформер,
такой как MapPattern, If-Elif или If-Then-Else.
5.3. Цепочки собираются слева направо — порядок важен
Внутри каждого списка операторы образуют конвейер: выход одного — вход следующего, оцениваемый сверху вниз. Переупорядочивание цепочки, как правило, меняет результат.
Например, на входном массиве ["b", "a", "c"]:
sort→firstпроизводит"a"(сортируем в["a","b","c"], затем берём первый).first→sortпроизводит"b"(берём первый элемент"b", затем сортируем один скаляр, который проходит насквозь).
Те же два оператора, другой порядок, другой ответ. Стройте цепочки осознанно: нормализуйте до извлечения, фильтруйте до склейки, форматируйте последним.
5.4. Null, отсутствие и неожиданные типы
Операторы написаны прощающими на пути ingest — плохое значение не должно ронять маппинг. Правила согласованы:
- Отсутствующий путь источника. Если путь источника резолвится в ничто, значение отсутствует. Значение по умолчанию правила (шаг 3 выше) заполняет его до того, как отработают трансформеры; без умолчания правило просто ничего не пишет.
null/ пустой вход трансформеру. Большинство трансформеров возвращаютnullили пустой вход без изменений. Исключения — предикатные операторы (семействоis*), которые сначала приводят черезString(value)— такisEmail(null)тестирует текст"null"и возвращаетfalse, а неnull.- Неверный тип — это проброс, а не ошибка. Строковый оператор, которому подали число, оператор массива, которому подали объект, или оператор даты, которому подали неразбираемую строку, возвращают вход без изменений. Это позволяет цепочке оставаться устойчивой, когда поле иногда «неправильной» формы.
- Поэлементно vs всё-значение. Строковые операторы (
trim,toUpperCase,base64Encode, пара defang/refang, …) применяются поэлементно: над массивом они трансформируют каждый строковый элемент и не трогают нестроки. Операторы object, date и math действуют на всё значение. Справочник помечает обработку значения у каждого оператора. - Пустые скаляры и фильтры. Поскольку фильтр трактует скаляр как один элемент,
скаляр, который не проходит, отбрасывается в отсутствие. Например,
drop_emptyна скаляре""даёт отсутствие значения (так что применяется умолчание правила), тогда какdrop_emptyна["a", "", "b"]даёт["a", "b"].
5.5. Синтаксис аргументов в интерфейсе
Большинство операторов не берут аргументов — вы просто добавляете их в цепочку. Операторы, которые берут аргументы, экспонируют их как именованные поля в редакторе, каждое со своим типом:
- string — свободный текст (например
separator,search,format). - number — числовое поле (например
length,count,operand). - boolean — переключатель (например
descending,caseInsensitive). - json — структурированное значение: объект или массив, набранный как JSON
(например
mappingsуMapPattern,otherуmerge,equalsуwhere_equals).
Обязательные аргументы помечены; опциональные аргументы откатываются к
задокументированному умолчанию, если оставлены пустыми (каждое перечислено в
справочнике). Некоторые аргументы принимают альтернативные имена (алиасы) для
совместимости с импортированным контентом — например, аргумент выражения у DT
принимает dt, expression или path.
Аргументы-регулярные-выражения валидируются. Операторы вроде replace,
regexReplace и фильтр RegexExtractAll берут regex. Редактор проверяет паттерн
при сохранении правила и отклоняет тот, что не компилируется или рискует
катастрофическим бэктрекингом (паттерн длиннее 512 символов или вложенные
неограниченные квантификаторы вроде (a+)+). В момент выполнения применяется тот же
страж: небезопасный паттерн делает оператор безопасным no-op, а не подвешивает
приём. Это намеренная граница безопасности — операторы никогда не выполняют
свободный код; условные операторы используют только фиксированную грамматику
сравнения.
5.6. Те же операторы в плейбуках
Библиотека трансформеров не ограничена мапперами. Узлы-задачи плейбуков Automation
Engine поддерживают output-трансформеры: после того как задача отработала, её
вывод можно прогнать через цепочку трансформеров до того, как он попадёт в контекст
плейбука. Эти цепочки черпают из того же реестра операторов, что задокументирован
здесь, так что трансформер ведёт себя идентично, гоняется ли он в правиле маппера
или на выводе задачи. Операторы-фильтры (where) — в первую очередь концепция
маппера: они выражают шаг select-before-map правила маппинга.
5.7. Разобранные примеры цепочек
Три сквозных примера. Каждый показывает значение источника, применённые по порядку операторы и сопоставленный результат.
Пример A — нормализация строки severity (трансформеры)
Вендор шлёт severity как свободный текст со случайным регистром и пробелами; вы хотите канонический код приоритета.
- Значение источника (
alert.priority):" high " - Трансформеры:
trim→toUpperCase→MapPatternсmappings = {"HIGH":"P1","MEDIUM":"P3","LOW":"P5"}
" high "
→ trim → "high"
→ toUpperCase → "HIGH"
→ MapPattern → "P1"
- Результат:
"P1"
Пример B — очистка и склейка списка получателей (фильтры + трансформеры)
Сырое событие несёт массив получателей с пустыми и дубликатами; вы хотите одну читаемую строку.
- Значение источника (
event.to):["a@b.com", "", "a@b.com", "c@d.com"] - Фильтры:
drop_empty→unique - Трансформеры:
joinComma
["a@b.com", "", "a@b.com", "c@d.com"]
→ drop_empty → ["a@b.com", "a@b.com", "c@d.com"] (filters run first)
→ unique → ["a@b.com", "c@d.com"]
→ joinComma → "a@b.com, c@d.com" (then transformers)
- Результат:
"a@b.com, c@d.com"
Пример C — оставить только критичные хосты, затем вывести их имена (объектный фильтр + трансформер)
Payload несёт массив объектов-хостов; вы хотите имена только критичных.
- Значение источника (
hosts):[{"name":"h1","critical":true}, {"name":"h2","critical":false}] - Фильтры:
where_equalsсpath = "critical",equals = true - Трансформеры:
pluckсfield = "name"
[{"name":"h1","critical":true}, {"name":"h2","critical":false}]
→ where_equals (critical == true) → [{"name":"h1","critical":true}]
→ pluck (name) → ["h1"]
- Результат:
["h1"]
Обратите внимание: where_equals использует строгое равенство, так что
JSON-булев true совпадает только с булевым true, а не со строкой "true".
Держите это в уме, когда сырой payload превращает свои булевы в строки.
Точные аргументы каждого оператора, умолчания, краевые случаи и его собственный разобранный пример см. в Справочнике фильтров и трансформеров маппера.