Создание скрипта активного действия
Условные обозначения
OSD_HOME- домашняя директория Smart Monitor Web, обычно это/app/opensearch-dashboards/
Общие правила
Скрипт активного действия определяет пользовательскую логику обработки инцидентов и агрегаций в модуле Incident Manager.
Скрипты для активных действий универсальны и для инцидентов, и для агрегаций. Их можно использовать как при одиночном ручном запуске, так и при переходе инцидентов в новое состояние Рабочего процесса в результате выполнения первичных и других действий.
Разница между первичными и другими действиями описана в статье Активные действия.
Скрипты для Активных действий можно создавать на двух языках программирования: JavaScript (NodeJS) и Python. Для этого необходимо создать файл скрипта в папке $OSD_HOME/plugins/smartMonitorIncidentManager/common/actions или $OSD_HOME/config/actions.
Если скрипты будут созданы в $OSD_HOME/config/actions, то при обновлении плагинов они будут сохранены, в противном случае они будут потеряны при обновлении.
У всех скриптов должны быть уникальные имена, иначе нужный скрипт может быть распознан некорректно.
Вне зависимости от выбранного языка в скрипт при выполнении активного действия для инцидента будут переданы следующие данные:
{
"currentUser": {
"backend_roles": [
// backend-роли текущего пользователя
],
"roles": [
// роли текущего пользователя
]
},
"incidentId": "zGQt4o8BqXcWBDa4I1DFGDH5", // ID инцидента
"index": ".incident-index-2023.21", // индекс, в котором хранится инцидент
"log": "", // логи инцидента (история изменения)
"metadata": {
"incidentId": "zGQt4o8BqXcWBDa4I1DFGDH5", // ID инцидента
"incidentTitle": "Exchange: антиспам пропустил письмо", // название инцидента
"incidentDescription": "Антиспам пропустил письмо", // описание инцидента
"index": ".smos_incident-2024.23", // индекс, в котором хранится инцидент
"urlToIncident": "https://smarthost.ru/incident-manager/...", // URL инцидента
"baseFields": {}, // базовые поля инцидента
"additionalFields": {}, // дополнительные поля инцидента
"fields": {
// дополнительные поля инцидента, установленные в активном действии
},
"reviewer": {
// ответственный за инцидент
}
},
"sideEffects": {
"status": {
"from": "open",
"to": "in_progress"
},
"assignedTo": {
"id": "sm_user",
"name": "Иван Иванов"
},
"fields": {
"severity": "high",
"category": "email_security"
},
"comment": "Инцидент принят в работу",
"actions": [
{
"type": "notification",
"channel": "email",
"recipients": ["admin@company.ru"],
"message": "Инцидент переведен в статус in_progress"
}
]
},
"target": "manual", // manual - флаг того, что используется активное действие или новый статус Рабочего процесса
"workflowId": "my-workflow", // ID Рабочего процесса инцидента
"_source": {
// тело инцидента
}
}
При выполнении скрипта активного действия для агрегации будут переданы следующие параметры:
{
"currentUser": {
"backend_roles": [
// backend-роли текущего пользователя
],
"roles": [
// роли текущего пользователя
]
},
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // ID агрегации
"index": ".incident_of_aggregation_results", // индекс, в котором хранится агрегация
"log": "", // логи агрегации (история изменения)
"metadata": {
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // ID агрегации
"aggregationTitle": "Exchange: антиспам пропустил письма", // Название агрегации
"aggregationDescription": "Exchange: антиспам пропустил письма с архивом", // Описание агрегации
"index": ".incident_of_aggregation_results", // индекс, в котором хранится агрегация
"urlToAggregation": "https://smarthost.ru//incident-manager/aggregations-result...", // URL агрегации
"baseFields": {
// базовые поля агрегации, которые были заданы при настройке
},
"additionalFields": {
// дополнительные поля агрегации, которые были заданы при настройке, а также поля для сравнения из самой агрегации
},
"comparation_fields": {
// Поля для сравнения в агрегации
},
"functional_fields": {
// функциональные поля в агрегации
}
},
"sideEffects": {}, // действия при переходе между статусами Рабочего процесса
"target": "manual", // manual - флаг того, что используется активное действие или новый статус Рабочего процесса
"workflowId": "my-workflow", // ID Рабочего процесса агрегации
"_source": {
// тело агрегации инцидентов
}
}
Скрипты, выполняемые в режиме ручного запуска (target: "manual"), не могут напрямую изменять данные инцидента или агрегации.
Если требуется выполнить действие, влияющее на состояние или поля инцидента либо агрегации, такой скрипт необходимо использовать в качестве первичного действия (pre-action) в рамках Рабочего процесса при переходе в новое состояние.
Использование JavaScript
При создании активного действия на JavaScript используется следующий шаблон:
/** ! Функция для выполнения активных действий
* @param doc - JSON с активными действиями
* @param metadata - метаданные переданные сущности (агрегации или инцидента)
* @param entities - переданный список инцидентов (используется при массовом редактировании статуса Рабочего процесса)
* @param currentUser - текущий пользователя
* @param index - индекс, в котором хранится сущность (агрегация или инцидент)
* @param log - логи сущности (история изменения агрегации или инцидента)
* @param sideEffects - действия при переходе между статусами
* @param workflowId - ID Рабочего процесса сущности (агрегации или инцидента)
* @param target - флаг того, что используется активное действие или новый статус Рабочего процесса
* @param incidentId - ID инцидента (передается в случае передачи инцидента)
* @param aggregationId - ID агрегации (передается в случае передачи агрегации)
* @param _source - нетроннутый полный результат сущности (агрегации или инцидента)
* @param logger - функция логирования
*/
export default async (doc, metadata, entities, currentUser, index, log, sideEffects, workflowId, target, incidentId, aggregationId, _source, logger) => {
// тело функции
};
Параметры передаются непосредственно при вызове функции. Функция должна быть асинхронной для корректной работы и предотвращения преждевременного завершения выполнения.
Использование Python
При создании активного действия на Python используется следующий шаблон:
import json
class Object:
# Вспомогательная функция для конвертации объекта в JSON
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=1)
""" Функция выполнения активных действий
@param: doc - сущность (агрегации или инцидента),
@param: metadata - метаданные переданные сущности (агрегации или инцидента)
@param: entities - переданный список инцидентов (используется при массовом редактировании статуса Рабочего процесса)
@param: currentUser - текущий пользователь
@param: index - индекс, в котором хранится сущность (агрегация или инцидент)
@param: log - логи сущности (история изменения агрегации или инцидента)
@param: sideEffects - действия при переходе между статусами
@param: workflowId - ID Рабочего процесса сущности (агрегации или инцидента)
@param: target - флаг того, что используется активное действие или новый статус Рабочего процесса
@param: incidentId - ID инцидента (передается в случае передачи инцидента)
@param: aggregationId - ID агрегации (передается в случае передачи агрегации)
@param: _source - нетронутый полный результат сущности (агрегации или инцидента)
"""
def my_func(doc, metadata, entities, currentUser, index, log, sideEffects, workflowId, target, incidentId, aggregationId, _source):
# код функции
print(json.dumps(doc)) # Вывести данные doc
if __name__ == "__main__":
_json = input() # Считывание данных из потока происходит через stdin
res = json.loads(_json)
my_func(
doc=res.get("doc"),
metadata=res.get("metadata"),
entities=res.get("entities"),
currentUser=res.get("currentUser"),
index=res.get("index"),
log=res.get("log"),
sideEffects=res.get("sideEffects"),
workflowId=res.get("workflowId"),
target=res.get("target"),
incidentId=res.get("incidentId"),
aggregationId=res.get("aggregationId"),
_source=res.get("_source"),
)
Параметры в активное действие на Python передаются через стандартный поток ввода консоли (stdin). Выходящие параметры измененной сущности инцидента или агрегации (doc) необходимо передать через выходной поток (stdout).
Данный пример является одним из возможных вариантов реализации — можно использовать любые удобные методы и функции.