Всем привет, если у вас появилась идея связать эти два инструмента, то хочу вас огорчить, прямой интеграции у них пока нет...
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
Ресурсы:
Вот и все! Спасибо за внимание:)
m1skam
Ээээм, как то странно, у меня поисковая выдача завалена решениями.
nikitapaparimskiy Автор
Да, выдача по запросу sentry-mattermost и правда завалена топиками, где в большинстве случаев просят помочь.
Но я не нашел рабочих решений и туториалов, в которых рассказано как быстро и просто мне реализовать получение евентов из сентри в маттермост без лишнего функционала, может подскажите рабочие решения?
m1skam
Что в вашем понимании "лишний функционал"? Я имел ввиду, что решений, подобно вашему, достаточно много, из первой страницы выдачи гугла:
https://github.com/NDrive/sentry-mattermost / он же в виде приложения для mattermost https://mattermost.com/marketplace/sentry/
https://github.com/xD3CODER/sentry-mattermost
https://pipedream.com/apps/sentry/integrations/mattermost
Лично я бы делал на базе pipedream, так как лимиты бесплатной версии весьма жирные и не требуется поднимать свой сервер/докер.