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);
}
实例
doc
- notifications