Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.vality.alerting.tg.bot.dao;

import dev.vality.alerting.tg.bot.pojo.ProviderThread;
import dev.vality.dao.impl.AbstractGenericDao;
import dev.vality.mapper.RecordRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.Optional;

import static dev.vality.alerting.tg.bot.domain.Tables.PROVIDER_THREAD;

@Component
public class ProviderThreadDao extends AbstractGenericDao {

private final RowMapper<ProviderThread> rowMapper;

public ProviderThreadDao(DataSource dataSource) {
super(dataSource);
this.rowMapper = new RecordRowMapper<>(PROVIDER_THREAD, ProviderThread.class);
}

public Optional<ProviderThread> findByProvider(String providerId) {
var query = getDslContext()
.selectFrom(PROVIDER_THREAD)
.where(PROVIDER_THREAD.PROVIDER_ID.eq(providerId));

return Optional.ofNullable(fetchOne(query, rowMapper));
}

public int insert(ProviderThread thread) {
var record = getDslContext().newRecord(PROVIDER_THREAD, thread);
var query = getDslContext()
.insertInto(PROVIDER_THREAD)
.set(record);

return execute(query);
}

public int upsert(ProviderThread thread) {
var query = getDslContext()
.insertInto(PROVIDER_THREAD)
.set(PROVIDER_THREAD.PROVIDER_ID, thread.getProviderId())
.set(PROVIDER_THREAD.THREAD_ID, thread.getThreadId())
.set(PROVIDER_THREAD.PROVIDER_NAME, thread.getProviderName())
.set(PROVIDER_THREAD.NAME, thread.getName())
.onConflict(PROVIDER_THREAD.PROVIDER_ID)
.doUpdate()
.set(PROVIDER_THREAD.THREAD_ID, thread.getThreadId())
.set(PROVIDER_THREAD.PROVIDER_NAME, thread.getProviderName())
.set(PROVIDER_THREAD.NAME, thread.getName());

return execute(query);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.vality.alerting.tg.bot.config.properties.AlertBotProperties;
import dev.vality.alerting.tg.bot.model.Webhook;
import dev.vality.alerting.tg.bot.service.FailedMachinesAlertService;
import dev.vality.alerting.tg.bot.service.ProviderThreadService;
import dev.vality.alerting.tg.bot.service.TelegramApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -22,7 +22,7 @@
public class FailedMachinesAlertHandler implements AlertHandler {
private final AlertBotProperties properties;
private final TelegramApiService telegramApiService;
private final FailedMachinesAlertService service;
private final ProviderThreadService service;

@Override
public boolean filter(String alertName) {
Expand All @@ -34,15 +34,15 @@ public void handle(Webhook webhook, List<Webhook.Alert> alerts) {
Map<Integer, List<Webhook.Alert>> threadIds = new HashMap<>();

for (Webhook.Alert alert : alerts) {
Integer threadId = service.getOrCreateTopicIdForFailedMachinesAlert(alert);
Integer threadId = service.getOrCreateTopicId(alert);
threadIds.computeIfAbsent(threadId, key -> new ArrayList<>()).add(alert);
}

threadIds.forEach((threadId, threadAlerts) -> {
telegramApiService.sendMessage(
properties.getChatId(),
threadId,
formatWebhook(webhook),
formatWebhook(webhook, threadAlerts),
"MarkdownV2"
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
@AllArgsConstructor
@EqualsAndHashCode
@ToString
public class ProviderTerminalThread implements Serializable {
public class ProviderThread implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

private Long id;
private Integer threadId;
private String providerId;
private String terminalId;
private String providerName;
private String terminalName;
private String name;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
package dev.vality.alerting.tg.bot.service;

import dev.vality.alerting.tg.bot.config.properties.AlertBotProperties;
import dev.vality.alerting.tg.bot.dao.ProviderTerminalThreadDao;
import dev.vality.alerting.tg.bot.dao.ProviderThreadDao;
import dev.vality.alerting.tg.bot.exception.TelegramThreadCreationException;
import dev.vality.alerting.tg.bot.model.Webhook;
import dev.vality.alerting.tg.bot.pojo.ProviderTerminalThread;
import dev.vality.alerting.tg.bot.pojo.ProviderThread;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class FailedMachinesAlertService {
private final ProviderTerminalThreadDao providerTerminalThreadDao;
public class ProviderThreadService {
private final ProviderThreadDao providerThreadDao;
private final TelegramApiService telegramApiService;
private final AlertBotProperties properties;

public Integer getOrCreateTopicIdForFailedMachinesAlert(Webhook.Alert alert) {
public Integer getOrCreateTopicId(Webhook.Alert alert) {
var labels = alert.getLabels();
String providerId = labels.getProviderId();
String providerName = labels.getProviderName();
String terminalId = labels.getTerminalId();
String terminalName = labels.getTerminalName();

var existing = providerTerminalThreadDao.findByProviderAndTerminal(providerId, terminalId);
var existing = providerThreadDao.findByProvider(providerId);
if (existing.isPresent() && existing.get().getThreadId() != null) {
return existing.get().getThreadId();
}

String threadName = "(" + providerId + ") " + providerName + " - (" + terminalId + ") " + terminalName;
String threadName = providerId + ": " + providerName;
Integer threadId;
try {
threadId = telegramApiService.createTopicAndReturnThreadId(threadName);
Expand All @@ -39,16 +37,14 @@ public Integer getOrCreateTopicIdForFailedMachinesAlert(Webhook.Alert alert) {
threadId = properties.getThreads().getCommands();
}

var entity = new ProviderTerminalThread(
var entity = new ProviderThread(
null,
threadId,
providerId,
terminalId,
labels.getProviderName(),
labels.getTerminalName(),
threadName
);
providerTerminalThreadDao.upsert(entity);
providerThreadDao.upsert(entity);

return threadId;
}
Expand Down
64 changes: 63 additions & 1 deletion src/main/java/dev/vality/alerting/tg/bot/util/WebhookUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import dev.vality.alerting.tg.bot.model.Webhook;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public final class WebhookUtil {
Expand Down Expand Up @@ -40,4 +42,64 @@ public static String formatWebhook(Webhook webhook) {
throw new IllegalStateException("Отсутствует статус алерта: webhook.getStatus() is null");
}
}

public static String formatWebhook(Webhook webhook, List<Webhook.Alert> alerts) {
if (alerts == null || alerts.isEmpty()) {
log.error("Список алертов пуст. {}", webhook);
throw new IllegalStateException("Список алертов пуст");
}

List<Webhook.Alert> firingAlerts = alerts.stream()
.filter(alert -> FIRING.equals(alert.getStatus()))
.toList();

List<Webhook.Alert> resolvedAlerts = alerts.stream()
.filter(alert -> RESOLVED.equals(alert.getStatus()))
.toList();

StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append("```\n");

if (!firingAlerts.isEmpty()) {
messageBuilder.append("АЛЕРТЫ СРАБОТАЛИ ❗\n\n");

String firingText = firingAlerts.stream()
.map(Webhook.Alert::getAnnotations)
.filter(Objects::nonNull)
.map(Webhook.Annotation::getDescription)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.joining("\n\n"));

messageBuilder.append(firingText);
}

if (!firingAlerts.isEmpty() && !resolvedAlerts.isEmpty()) {
messageBuilder.append("\n\n---\n\n");
}

if (!resolvedAlerts.isEmpty()) {
messageBuilder.append("Ситуации пришли в норму ✅\n\n");

String resolvedText = resolvedAlerts.stream()
.map(Webhook.Alert::getAnnotations)
.filter(Objects::nonNull)
.map(Webhook.Annotation::getSummary)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.joining("\n\n"));

messageBuilder.append(resolvedText);
}

messageBuilder.append("\n```");
String result = messageBuilder.toString();

if (result.isBlank()) {
log.error("Не удалось сформировать текст алертов. {}", webhook);
throw new IllegalStateException("Не удалось сформировать текст алертов");
}

return result;
}
}
17 changes: 17 additions & 0 deletions src/main/resources/db/migration/V2__change_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
ALTER TABLE IF EXISTS alert_tg_bot.provider_terminal_thread
RENAME TO provider_thread;

ALTER TABLE IF EXISTS alert_tg_bot.provider_thread
DROP CONSTRAINT IF EXISTS provider_terminal_thread_provider_terminal_uk;

ALTER TABLE IF EXISTS alert_tg_bot.provider_thread
DROP COLUMN IF EXISTS terminal_id,
DROP COLUMN IF EXISTS terminal_name;

DELETE FROM alert_tg_bot.provider_thread current_row
USING alert_tg_bot.provider_thread duplicate_row
WHERE current_row.provider_id = duplicate_row.provider_id
AND current_row.id > duplicate_row.id;

ALTER TABLE IF EXISTS alert_tg_bot.provider_thread
ADD CONSTRAINT provider_thread_provider_uk UNIQUE (provider_id);
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package dev.vality.alerting.tg.bot;

import dev.vality.alerting.tg.bot.config.PostgresqlSpringBootITest;
import dev.vality.alerting.tg.bot.dao.ProviderTerminalThreadDao;
import dev.vality.alerting.tg.bot.dao.ProviderThreadDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
Expand All @@ -20,6 +20,6 @@ public class ApplicationContextTest {
void startApplicationContextTest() {
assertThat(applicationContext).isNotNull();

assertThat(applicationContext.getBean(ProviderTerminalThreadDao.class)).isNotNull();
assertThat(applicationContext.getBean(ProviderThreadDao.class)).isNotNull();
}
}
Loading
Loading