Кастомный Lua-скрипт постобработки событий активности пользователя
Агент мониторинга поддерживает кастомные Lua-скрипты постобработки событий активности пользователя. Скрипт выполняется в дополнение к встроенной постобработке и позволяет управлять составом собираемых данных: исключать или хешировать чувствительную информацию под требования организации.
Скрипт — это файл с расширением .lua размером до 1 Мб.
Lua-окружение
Скрипт выполняется в среде Lua 5.4.7. В ней дополнительно доступна библиотека luautf8, предоставляющая функции utf8.* — в частности, utf8.len, utf8.gmatch, utf8.sub, utf8.match, используемые в примерах ниже.
Шаблон скрипта
Кастомный скрипт содержит четыре функции, которые должны присутствовать в любом скрипте: GetVersion и три функции Lua API.
function GetVersion()
return "1.0.0"
end
function RemoveCustomUninformativeInfo(WAL)
end
function PreExtractCustomParameters(WAL)
end
function PostExtractCustomParameters(WAL)
end
Где:
GetVersion— должна присутствовать в скрипте и быть реализована. Возвращает строку с версией скрипта. Версия обеспечивает совместимость с кодом агента и меняется только при несовместимых изменениях в формате структурыWALRemoveCustomUninformativeInfo,PreExtractCustomParameters,PostExtractCustomParameters— должны присутствовать в скрипте. Реализуйте только те, которые нужны; тело остальных можно оставить пустым
Агент вызывает только эти четыре функции. Внутри скрипта можно объявлять любые вспомогательные функции и вызывать их из основных четырех — это стандартная практика Lua. Вспомогательные функции показаны в разделах ниже и в полном примере скрипта.
Структура WAL
WAL (WindowActivityLua) — структура с данными по событию активности пользователя. Lua-код может изменять ее поля.
| Поле | Тип | Описание |
|---|---|---|
windowHierarchy | VectorWindowDataLua | Иерархия окон события. Список объектов WindowDataLua |
applicationInfo | ApplicationInfoLua | Информация о приложении, в котором произошло событие |
uiElement | ElementDataLua | UI-элемент, с которым взаимодействовал пользователь (может отсутствовать) |
filePath | String | Путь к файлу, открытому в момент события |
url | String | URL, открытый в момент события |
WindowDataLua
Данные одного окна в иерархии.
| Поле | Тип | Описание |
|---|---|---|
name | String | Заголовок окна |
windowType | Number | Внутренний код типа окна |
formData | WindowParametersLua | Параметры формы окна. Содержит поле formData типа VectorFormDataElementLua |
FormDataElementLua
Элемент вектора formData.
| Поле | Тип | Описание |
|---|---|---|
element | ElementDataLua | UI-элемент, которому соответствует поле формы |
value | FormDataValueLua | Значение поля формы |
ApplicationInfoLua
Информация о приложении.
| Поле | Тип | Описание |
|---|---|---|
executablePath | String | Путь к исполняемому файлу приложения |
programName | String | Имя приложения |
version | VersionLua | Версия приложения |
type | Number | Внутренний код типа процесса |
VersionLua
Версия приложения.
| Поле | Тип | Описание |
|---|---|---|
major | Number | Старший номер версии |
minor | Number | Младший номер версии |
build | Number | Номер сборки |
ElementDataLua
UI-элемент.
| Поле | Тип | Описание |
|---|---|---|
name | String | Имя элемента |
nameType | Number | Внутренний код типа имени |
controlType | Number | Внутренний код типа элемента управления |
FormDataValueLua
Значение поля формы.
| Поле | Тип | Описание |
|---|---|---|
value | String | Текстовое значение поля |
type | Number | Тип значения. FormDataValueType.Extracted соответствует извлеченному параметру |
Изменяемость структуры
Lua-код может изменять поля существующих объектов в WAL. Добавление новых окон в windowHierarchy через push_back не поддерживается. Удаление последнего окна (pop_back) и полная очистка иерархии (clear) работают корректно.
Функции Lua API
После сбора данных агент мониторинга выполняет встроенную постобработку события в два этапа: удаляет избыточную информацию по внутренним правилам, затем извлекает параметры из данных окон по встроенным шаблонам. Три функции скрипта — это точки кастомизации: агент вызывает их в определенные моменты этой постобработки, передавая структуру WAL с данными события.
Каждая функция принимает аргумент WAL (структура данных по событию).
Агент вызывает функции в следующем порядке:
RemoveCustomUninformativeInfo— агент вызывает ее после того, как удалил избыточную информацию по собственным правилам, но до начала извлечения параметров. Данные, которые функция удалила, в событии не сохраняютсяPreExtractCustomParameters— агент вызывает ее перед тем, как начнет извлекать параметры по встроенным шаблонамPostExtractCustomParameters— агент вызывает ее после того, как завершит извлечение параметров по встроенным шаблонам. В этот момент событие уже содержит извлеченные параметры
Один и тот же фрагмент данных можно обработать по-разному в зависимости от выбранной функции. Например, для ИНН:
- Чтобы удалить ИНН полностью и не фиксировать в событии, используйте
RemoveCustomUninformativeInfo - Чтобы извлечь ИНН, преобразовать его или заменить на символ-заглушку, используйте
PostExtractCustomParameters
RemoveCustomUninformativeInfo
Агент мониторинга вызывает эту функцию в ходе удаления избыточной информации — после того как выполнил собственное удаление, но до того как начнет извлекать параметры.
Используйте, чтобы дополнительно удалить нужные подстроки из значений полей формы окна.
Фрагмент ниже иллюстрирует функцию RemoveCustomUninformativeInfo и вспомогательную функцию RemoveWordsStartingWithZero. Пример — удалить из значений полей формы окна слова, начинающиеся на «0»:
-- Удаляет из строки слова, начинающиеся на "0".
-- Слово — последовательность непробельных символов; оставшиеся слова
-- разделяются одиночным пробелом.
--
-- @param str string Исходная строка.
-- @return string Строка без слов, начинающихся на "0".
function RemoveWordsStartingWithZero(str)
if utf8.len(str) == 0 then
return str
end
local parts = {}
for word in utf8.gmatch(str, "%S+") do
if utf8.sub(word, 1, 1) ~= "0" then
table.insert(parts, word)
end
end
return table.concat(parts, " ")
end
-- Удаляет из значений полей формы окна слова, начинающиеся на "0".
--
-- @param WAL window activity для lua
function RemoveCustomUninformativeInfo(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
window.formData.formData:at(j).value.value =
RemoveWordsStartingWithZero(window.formData.formData:at(j).value.value)
end
end
end
PreExtractCustomParameters
Агент мониторинга вызывает эту функцию перед тем, как начнет извлекать параметры по встроенным шаблонам.
Используйте, чтобы извлечь параметры до того, как их обработают встроенные шаблоны агента. Для каждого извлеченного параметра установите тип FormDataValueType.Extracted, чтобы стандартное извлечение не обработало значение повторно.
Фрагмент ниже иллюстрирует функцию PreExtractCustomParameters и вспомогательные функции IsOneNumber, ExtractOneNumbers. Пример — извлечь из значений полей формы окна числа, начинающиеся на «1», с префиксом one_number::
-- Проверяет, состоит ли строка только из цифр и начинается ли с "1".
--
-- @param word string Проверяемое слово.
-- @return boolean true, если слово — число, начинающееся на "1".
local function IsOneNumber(word)
return utf8.match(word, "^1%d*$") ~= nil
end
-- Извлекает из значения поля формы окна числа (слова, состоящие только из цифр),
-- начинающиеся на "1", помечая их префиксом "one_number:".
--
-- Функция вызывается до стандартного извлечения параметров, поэтому работает
-- с сырыми значениями полей формы окна (стандартного префикса "number:" здесь еще нет).
--
-- @param value string Значение поля формы окна.
-- @return string Преобразованное значение.
-- @return boolean true, если был извлечен хотя бы один параметр.
function ExtractOneNumbers(value)
local parts = {}
local extracted = false
for word in utf8.gmatch(value, "%S+") do
if IsOneNumber(word) then
table.insert(parts, "one_number:" .. word)
extracted = true
else
table.insert(parts, word)
end
end
return table.concat(parts, " "), extracted
end
-- Извлекает из значений полей формы окна числа, начинающиеся на "1",
-- с префиксом "one_number:". После успешного извлечения помечает значение
-- как Extracted, чтобы стандартный пайплайн не извлекал его повторно.
--
-- @param WAL window activity для lua
function PreExtractCustomParameters(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
local element = window.formData.formData:at(j)
local newValue, extracted = ExtractOneNumbers(element.value.value)
element.value.value = newValue
if extracted then
element.value.type = FormDataValueType.Extracted
end
end
end
end
PostExtractCustomParameters
Агент мониторинга вызывает эту функцию после того, как завершит извлечение параметров по встроенным шаблонам.
Используйте, чтобы извлечь дополнительные параметры, которые встроенные шаблоны агента не извлекают. Для каждого извлеченного параметра установите тип FormDataValueType.Extracted.
Фрагмент ниже иллюстрирует функцию PostExtractCustomParameters и вспомогательные функции IsSpecialWord, ExtractSpecialWords. Пример — извлечь из значений полей формы окна слова, начинающиеся на «абв», с префиксом special_word::
-- Проверяет, начинается ли слово с "абв".
--
-- @param word string Проверяемое слово.
-- @return boolean true, если слово начинается на "абв".
local function IsSpecialWord(word)
local prefix = "абв"
return utf8.sub(word, 1, utf8.len(prefix)) == prefix
end
-- Извлекает из значения поля формы окна слова, начинающиеся на "абв", помечая их
-- префиксом "special_word:".
--
-- Функция вызывается после стандартного извлечения параметров.
--
-- @param value string Значение поля формы окна.
-- @return string Преобразованное значение.
-- @return boolean true, если был извлечен хотя бы один параметр.
function ExtractSpecialWords(value)
local parts = {}
local extracted = false
for word in utf8.gmatch(value, "%S+") do
if IsSpecialWord(word) then
table.insert(parts, "special_word:" .. word)
extracted = true
else
table.insert(parts, word)
end
end
return table.concat(parts, " "), extracted
end
-- Извлекает из значений полей формы окна слова, начинающиеся на "абв",
-- с префиксом "special_word:". После успешного извлечения помечает значение
-- как Extracted.
--
-- @param WAL window activity для lua
function PostExtractCustomParameters(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
local element = window.formData.formData:at(j)
local newValue, extracted = ExtractSpecialWords(element.value.value)
element.value.value = newValue
if extracted then
element.value.type = FormDataValueType.Extracted
end
end
end
end
Пример скрипта
Полный скрипт со всеми четырьмя функциями, которые должны присутствовать в скрипте. Реализована логика из фрагментов выше: удаление слов, начинающихся на «0», извлечение чисел с «1» и слов с «абв».
function GetVersion()
return "1.0.0"
end
-- Удаляет из строки слова, начинающиеся на "0".
-- Слово — последовательность непробельных символов; оставшиеся слова
-- разделяются одиночным пробелом.
--
-- @param str string Исходная строка.
-- @return string Строка без слов, начинающихся на "0".
function RemoveWordsStartingWithZero(str)
if utf8.len(str) == 0 then
return str
end
local parts = {}
for word in utf8.gmatch(str, "%S+") do
if utf8.sub(word, 1, 1) ~= "0" then
table.insert(parts, word)
end
end
return table.concat(parts, " ")
end
-- Удаляет из значений полей формы окна слова, начинающиеся на "0".
--
-- @param WAL window activity для lua
function RemoveCustomUninformativeInfo(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
window.formData.formData:at(j).value.value =
RemoveWordsStartingWithZero(window.formData.formData:at(j).value.value)
end
end
end
-- Проверяет, состоит ли строка только из цифр и начинается ли с "1".
--
-- @param word string Проверяемое слово.
-- @return boolean true, если слово — число, начинающееся на "1".
local function IsOneNumber(word)
return utf8.match(word, "^1%d*$") ~= nil
end
-- Извлекает из значения поля формы окна числа (слова, состоящие только из цифр),
-- начинающиеся на "1", помечая их префиксом "one_number:".
--
-- Функция вызывается до стандартного извлечения параметров, поэтому работает
-- с сырыми значениями полей формы окна (стандартного префикса "number:" здесь еще нет).
--
-- @param value string Значение поля формы окна.
-- @return string Преобразованное значение.
-- @return boolean true, если был извлечен хотя бы один параметр.
function ExtractOneNumbers(value)
local parts = {}
local extracted = false
for word in utf8.gmatch(value, "%S+") do
if IsOneNumber(word) then
table.insert(parts, "one_number:" .. word)
extracted = true
else
table.insert(parts, word)
end
end
return table.concat(parts, " "), extracted
end
-- Извлекает из значений полей формы окна числа, начинающиеся на "1",
-- с префиксом "one_number:". После успешного извлечения помечает значение
-- как Extracted, чтобы стандартный пайплайн не извлекал его повторно.
--
-- @param WAL window activity для lua
function PreExtractCustomParameters(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
local element = window.formData.formData:at(j)
local newValue, extracted = ExtractOneNumbers(element.value.value)
element.value.value = newValue
if extracted then
element.value.type = FormDataValueType.Extracted
end
end
end
end
-- Проверяет, начинается ли слово с "абв".
--
-- @param word string Проверяемое слово.
-- @return boolean true, если слово начинается на "абв".
local function IsSpecialWord(word)
local prefix = "абв"
return utf8.sub(word, 1, utf8.len(prefix)) == prefix
end
-- Извлекает из значения поля формы окна слова, начинающиеся на "абв", помечая их
-- префиксом "special_word:".
--
-- Функция вызывается после стандартного извлечения параметров.
--
-- @param value string Значение поля формы окна.
-- @return string Преобразованное значение.
-- @return boolean true, если был извлечен хотя бы один параметр.
function ExtractSpecialWords(value)
local parts = {}
local extracted = false
for word in utf8.gmatch(value, "%S+") do
if IsSpecialWord(word) then
table.insert(parts, "special_word:" .. word)
extracted = true
else
table.insert(parts, word)
end
end
return table.concat(parts, " "), extracted
end
-- Извлекает из значений полей формы окна слова, начинающиеся на "абв",
-- с префиксом "special_word:". После успешного извлечения помечает значение
-- как Extracted.
--
-- @param WAL window activity для lua
function PostExtractCustomParameters(WAL)
local hierarchy = WAL.windowHierarchy
for i = 0, hierarchy:size() - 1 do
local window = hierarchy:at(i)
for j = 0, window.formData.formData:size() - 1 do
local element = window.formData.formData:at(j)
local newValue, extracted = ExtractSpecialWords(element.value.value)
element.value.value = newValue
if extracted then
element.value.type = FormDataValueType.Extracted
end
end
end
end
Обработка ошибок
Если скрипт содержит ошибку (синтаксическую или возникшую при выполнении), постобработка, выполняемая этим скриптом, пропускается. В логе инспектора появляется запись вида:
[LUA] <имя_функции> <сообщение>
Здесь <имя_функции> — одна из четырех функций, завершившаяся ошибкой. <сообщение> — подробности ошибки, если их удалось получить.
Загрузка скрипта в систему
Готовый .lua-файл загружается в Proceset через GraphQL API и автоматически подписывается сервером. Агент мониторинга проверяет подпись перед каждым запуском. Инструкция по загрузке, просмотру и удалению скрипта — в разделе Кастомный скрипт постобработки документации агента мониторинга.
Была ли статья полезна?