Reputation: 1431
We monitor our Spring Boot apps with the Spring Boot Admin Server and using Slack and Email notification
spring.boot.admin.notify.slack.enabled: true
...
spring.boot.admin.notify.mail.enabled: true
Is it possible to define separate recipients for the notification email per app, e.g. something like this
spring.boot.admin.notify.mail.enabled.app1: true
spring.boot.admin.notify.mail.to.app1: [email protected]
spring.boot.admin.notify.mail.enabled.app2: true
spring.boot.admin.notify.mail.to.app2: [email protected]
Upvotes: 4
Views: 3533
Reputation: 13777
According to the SBA document, we may not implement client-specific notifications (at least not now) as required. I have gone through the code and sharing some brief how it currently works and possible ways to customize implementation using the same,
spring.boot.admin.notify.mail
SBA implements the notifier using the AdminServerNotifierAutoConfiguration
which does the basic configurations based on the properties we defined for notifications. For mail service, it has MailNotifierConfiguration
along with TemplateEngine as mailNotifierTemplateEngine as follows
@Bean
@ConditionalOnMissingBean
@ConfigurationProperties("spring.boot.admin.notify.mail")
public MailNotifier mailNotifier(JavaMailSender mailSender, InstanceRepository repository) {
return new MailNotifier(mailSender, repository, mailNotifierTemplateEngine());
}
@Bean
public TemplateEngine mailNotifierTemplateEngine() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(this.applicationContext);
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(resolver);
return templateEngine;
}
spring.boot.admin.notify.mail.to
spring.boot.admin.notify.mail.from
MailNotifier
consist of the basic mail details such as from, to and additional info, etc along with default mail templet which extends the AbstractStatusChangeNotifier
which is responsible for status update of applications.
I have created one enhancement request for the same here
Step 1: Create client specific MailNotifier
You may also create subclass inside MailNotifier
.
public class MailNotifierClient1 extends AbstractStatusChangeNotifier {
private final JavaMailSender mailSender;
private final TemplateEngine templateEngine;
private String[] to = { "root@localhost" };
private String[] cc = {};
private String from = "Spring Boot Admin <noreply@localhost>";
private Map<String, Object> additionalProperties = new HashMap<>();
@Nullable private String baseUrl;
private String template = "classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html";
public MailNotifierClient1(JavaMailSender mailSender, InstanceRepository repository, TemplateEngine templateEngine) {
super(repository);
this.mailSender = mailSender;
this.templateEngine = templateEngine;
}
@Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
return Mono.fromRunnable(() -> {
Context ctx = new Context();
ctx.setVariables(additionalProperties);
ctx.setVariable("baseUrl", this.baseUrl);
ctx.setVariable("event", event);
ctx.setVariable("instance", instance);
ctx.setVariable("lastStatus", getLastStatus(event.getInstance()));
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name());
message.setText(getBody(ctx).replaceAll("\\s+\\n", "\n"), true);
message.setSubject(getSubject(ctx));
message.setTo(this.to);
message.setCc(this.cc);
message.setFrom(this.from);
mailSender.send(mimeMessage);
}
catch (MessagingException ex) {
throw new RuntimeException("Error sending mail notification", ex);
}
});
}
protected String getBody(Context ctx) {
return templateEngine.process(this.template, ctx);
}
Step 2: Mapping for specific client and properties in AdminServerNotifierAutoConfiguration
@Bean
@ConditionalOnMissingBean
@ConfigurationProperties("spring.boot.admin.notify.mail.client1")
public MailNotifierClient1 mailNotifierClient1(JavaMailSender mailSender, InstanceRepository repository) {
return new MailNotifierClient1(mailSender, repository, mailNotifierTemplateEngine());
}
Here you may add modify doNotify
method using the InstanceEvent, Instance (using Registration which consists of basic client details) domains, and set the recipients for mail into the field. You may change the conditions according to your requirements. These way you do not have to create other class/subclass.
@Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
return Mono.fromRunnable(() -> {
Context ctx = new Context();
ctx.setVariables(additionalProperties);
ctx.setVariable("baseUrl", this.baseUrl);
ctx.setVariable("event", event);
ctx.setVariable("instance", instance);
ctx.setVariable("lastStatus", getLastStatus(event.getInstance()));
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name());
message.setText(getBody(ctx).replaceAll("\\s+\\n", "\n"), true);
message.setSubject(getSubject(ctx));
message.setCc(this.cc);
message.setFrom(this.from);
if(instance.getRegistration().getName().equals("client1")) {
message.setTo("client1.to");
}
mailSender.send(mimeMessage);
}
catch (MessagingException ex) {
throw new RuntimeException("Error sending mail notification", ex);
}
});
}
In case if we do not want to customize SBA then alternative way to achieve the requirement is to create the individual SBA for each client
Upvotes: 4