Всем привет, если у вас появилась идея связать эти два инструмента, то хочу вас огорчить, прямой интеграции у них пока нет…
4 простеньких шага для решения этой проблемы:
-
Создаем webhook в Mattermost
-
Создаем Custom Integration и Alert в Sentry
-
Пишем небольшой сервис, который будет принимать сообщение(event) из Sentry
-
Приводим event в нужный формат и отправляем в Mattermost с помощью webhook
Весь код сервиса лежит в этом репозитории на гитхибе.
Когда я столкнулся с проблемой, я начал искать готовые решения или хотя бы туториалы по интеграции этих инструментов, но не нашел ничего и решил это исправить, написав гайд и возможно, сэкономив кому-то пару часов, а может и дней жизни. Код сервиса будет максимально простой, главная идея статьи — показать один из способов решения проблемы и направить в какую сторону копать, надеюсь кому-то пригодится:)
Какие проблемы решает сервис
-
Как я уже написал ранее, на сегодняшний день прямой интеграции Sentry и Mattermost нет.
Если в Sentry зайти в settings -> integrations вы увидите очень много разных плагинов, но нужного нам нет.
-
Интеграция напрямую через webhook так же не сработает, так как webhook Mattermost ждет один формат, а Sentry шлет совсем другой (вы получите 404 ошибку при отправке напрямую).
Например если вы захотите получать уведомления из Gitlab в Mattermost, вам достаточно в Gitlab зайти в settings -> integrations -> добавить интеграцию Mattermost notification — done! Но с Sentry так не сработает:(
Приступим по шагам
Создаем webhook Mattermost:
-
Ссылка на документацию: https://developers.mattermost.com/integrate/webhooks/incoming/
-
Заходим Интеграции -> Входяшие вебхуки -> Создать входящий вебхук
-
После создания, запоминаем URL_WEBHOOK
Если у вас нет кнопки «Интеграции» — попросите админа сервера:
Зайти в админ панель Mattermost → Найти раздел Integrations → Enable Incoming Webhooks
Создаем Custom Integration и Alert в Sentry
-
Заходим Settings → Custom Integrations → Create new integration
-
Name — Имя интеграции
-
Webhook URL — домен + роут где будет лежать наш адаптер
-
Alert Rule Action — true
-
В разделе Webhooks ставим галочки на нужные events
-
Остальное можно оставить по дефолту → Создаем интеграцию
-

-
Заходим в Alert → Create new alert → Issues → Set Conditions
-
Далее в открывшемся окне в пункте Set Conditions вы можете задать правила отправки уведомлений, так называемые тригеры по условиям.
-
Главное в окне THEN выбрать раннее созданную интеграцию по имени, которые вы задали
-
Остальное можно оставить по дефолту, подробнее почитать тут

Пишем сам адаптер
-
Приложение напишем на Nodejs, ссылка на репо
-
Ниже прикрепляю 2 основных файла, с комментариями:
Точка входа в приложение — app.js
const express = require("express"); const bodyParser = require("body-parser"); const axios = require("axios"); const logger = require("./utils/logger"); const getTextForMattermost = require("./getTextForMattermost"); require("dotenv").config(); const app = express(); const PORT = process.env.PORT || 4045; // Сюда вставить вебхук из Mattermos const URL_WEBHOOK = process.env.URL_WEBHOOK; app.use(bodyParser.json()); // Endpoint на который Sentry будет кидать event app.post("/webhook", ({ headers, body }) => { try { // Отправляем отформатированный формат eventа в Mattermost axios.post(URL_WEBHOOK, { text: getTextForMattermost({ headers, body }) }); } catch (err) { logger.error("Ошибка при отправке в Mattermost", error); } }); app .listen(PORT, () => { logger.info(`Сервер успешно запущен на порту ${PORT}`); }) .on("error", (error) => logger.error("Ошибка при запуске сервера", error));
Файл форматирования — getTextForMattermost.js
const findDeepValue = require("./utils/findDeepValue"); const logger = require("./utils/logger"); /** Замкнули обьект с данными, для удобного получения нужных полей из этого обьекта на любом уровне вложенности; */ const getDataFromRequest = (reqBody) => { return (fieldName) => { return findDeepValue(reqBody, fieldName); }; }; /** Sentry кидает обьект ошибки, fieldName это нужны поля из этого обьекта; */ const configFields = [ { fieldName: "environment", labelName: "Окружение" }, { fieldName: "title", labelName: "Название" }, { fieldName: "action", labelName: "Действие" }, { fieldName: "web_url", labelName: "Сслыка на Sentry" }, { fieldName: "status", labelName: "Статус" }, { fieldName: "message", labelName: "Описание(message)" }, ]; /** Формируем сообщение для Mattermost */ module.exports = getTextForMattermost = ({ headers, body }) => { try { logger.info("Из Sentry пришло событие", { headers, body }); /** Docs Sentry: https://docs.sentry.io/product/integrations/integration-platform/webhooks/?original_referrer=https%3A%2F%2Fwww.google.com%2F#sentry-hook-resource */ const resource = headers["Sentry-Hook-Resource"]; // installation | event_alert | issue | metric_alert | error | comment const getFieldFromData = getDataFromRequest(body); let message = ""; configFields.forEach((item) => { const value = getFieldFromData(item.fieldName); if (value) { message += `###### ${item.labelName}: ${value}\n`; } }); if (resource) { message += `###### Название ресурса: ${resource}`; } return `#### Ошибка в анкете, подробности ниже:\n ${message}`; } catch (error) { logger.error("Ошибка в методе getTextForMattermost", error); return ( `#### Ошибка в адапторе:\nЧто-то сломалось в методе getTextForMattermost, проверьте логи на сервере адаптера ` + error?.message ); } };
Остается задеплоить ваш сервис на хостинг и запустить (я использую pm2 для управления процессами ноды), не забудьте правильно указать Webhook URL при создании интеграции с правильным доменом, на котором будет лежать ваш адаптер.
Чтобы проверить работы сервисы, вы можете на шаге создания Alert в Sentry, выбрав вашу Интеграцию, отправить “Send Test Notifications” → Должно прийти сообщение в Mattremost
Ресурсы:
Вот и все! Спасибо за внимание:)
ссылка на оригинал статьи https://habr.com/ru/articles/761962/
Добавить комментарий