slack配置
spring.boot.admin:
notify:
slack:
enabled: true
ignore-changes: #empty, nothing to ignore
webhook-url: https://hooks.slack.com/services/xxxxxxx
channel: general
username: spring cloud admin
message: "*#{application.name}* (#{application.id}) is *#{to.status}*"
排程配置
@Configuration
@EnableScheduling
public class NotifierConfiguration {
@Autowired
private Notifier notifier;
@Bean
@Primary
public RemindingNotifier remindingNotifier() {
RemindingNotifier remindingNotifier = new RemindingNotifier(notifier);
//時間視窗,每次報警的間隔,即這個時間視窗內不重複報警
remindingNotifier.setReminderPeriod(TimeUnit.SECONDS.toMillis(10));
return remindingNotifier;
}
@Scheduled(fixedRate = 5_000L) //每5秒排程一次
public void remind() {
System.out.println("remind....");
remindingNotifier().sendReminders();
}
}
時間視窗
~/.m2/repository/de/codecentric/spring-boot-admin-server/1.4.6/spring-boot-admin-server-1.4.6-sources.jar!/de/codecentric/boot/admin/notify/RemindingNotifier.java
public void sendReminders() {
long now = System.currentTimeMillis();
for (Reminder reminder : new ArrayList<>(reminders.values())) {
if (now - reminder.getLastNotification() > reminderPeriod) {
reminder.setLastNotification(now);
delegate.notify(reminder.getEvent());
}
}
}
是否該報警的判斷
private String[] reminderStatuses = { "DOWN", "OFFLINE" };
@Override
public void doNotify(ClientApplicationEvent event) {
delegate.notify(event);
if (shouldEndReminder(event)) {
reminders.remove(event.getApplication().getId());
} else if (shouldStartReminder(event)) {
reminders.putIfAbsent(event.getApplication().getId(), new Reminder(event));
}
}
public void sendReminders() {
long now = System.currentTimeMillis();
for (Reminder reminder : new ArrayList<>(reminders.values())) {
if (now - reminder.getLastNotification() > reminderPeriod) {
reminder.setLastNotification(now);
delegate.notify(reminder.getEvent());
}
}
}
protected boolean shouldStartReminder(ClientApplicationEvent event) {
if (event instanceof ClientApplicationStatusChangedEvent) {
return Arrays.binarySearch(reminderStatuses,
event.getApplication().getStatusInfo().getStatus()) >= 0;
}
return false;
}
protected boolean shouldEndReminder(ClientApplicationEvent event) {
if (event instanceof ClientApplicationDeregisteredEvent) {
return true;
}
if (event instanceof ClientApplicationStatusChangedEvent) {
return Arrays.binarySearch(reminderStatuses,
event.getApplication().getStatusInfo().getStatus()) < 0;
}
return false;
}
狀態在{"DOWN", "OFFLINE"}的,就加入到reminders中,不在的話,從reminders中移除。
在排程期間,如果status變為up了,會先報警,然後再判斷是否應該刪除該事件。
notifier
delegate.notify(event);
這裡的delegate為SlackNotifier
public class SlackNotifier extends AbstractStatusChangeNotifier {
//...
}
繼承了AbstractStatusChangeNotifier
public abstract class AbstractStatusChangeNotifier extends AbstractEventNotifier {
/**
* List of changes to ignore. Must be in Format OLD:NEW, for any status use * as wildcard, e.g.
* *:UP or OFFLINE:*
*/
private String[] ignoreChanges = { "UNKNOWN:UP" };
@Override
protected boolean shouldNotify(ClientApplicationEvent event) {
if (event instanceof ClientApplicationStatusChangedEvent) {
ClientApplicationStatusChangedEvent statusChange = (ClientApplicationStatusChangedEvent) event;
String from = statusChange.getFrom().getStatus();
String to = statusChange.getTo().getStatus();
return Arrays.binarySearch(ignoreChanges, from + ":" + to) < 0
&& Arrays.binarySearch(ignoreChanges, "*:" + to) < 0
&& Arrays.binarySearch(ignoreChanges, from + ":*") < 0;
}
return false;
}
public void setIgnoreChanges(String[] ignoreChanges) {
String[] copy = Arrays.copyOf(ignoreChanges, ignoreChanges.length);
Arrays.sort(copy);
this.ignoreChanges = copy;
}
}
這裡對ignore的邏輯進行了判斷,不滿足條件的不會呼叫doNotify
public void notify(ClientApplicationEvent event) {
if (enabled && shouldNotify(event)) {
try {
doNotify(event);
} catch (Exception ex) {
getLogger().error("Couldn't notify for event {} ", event, ex);
}
}
}
doNotify才是真正的傳送slack
@Override
protected void doNotify(ClientApplicationEvent event) throws Exception {
restTemplate.postForEntity(webhookUrl, createMessage(event), Void.class);
}
例項