Commit e1aadeb2 by Johannes Edmeier

Merge pull request #169 from ukjbrown/master

parents c40cd36b ee3a9905
......@@ -428,6 +428,44 @@ To enable pagerduty notifications you just have to add a generic service to your
|
|===
[hipchat-notifications]
==== Hipchat notifications ====
To enable Hipchat notifications you need to create an API token from you Hipchat account and set the appropriate configuration properties.
.Hipchat notifications configuration options
|===
| Property name |Description |Default value
| spring.boot.admin.notify.hipchat.enabled
| Enable Hipchat notifications
| `true`
| spring.boot.admin.notify.hipchat.ignore-changes
| Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.
| `"UNKNOWN:UP"`
| spring.boot.admin.notify.hipchat.url
| The HipChat REST API (V2) URL
|
| spring.boot.admin.notify.hipchat.auth-token
| The API token with access to the notification room
|
| spring.boot.admin.notify.hipchat.room-id
| The ID or url-encoded name of the room to send notifications to
|
| spring.boot.admin.notify.hipchat.notify
| Whether the message should trigger a user notification
| `false`
| spring.boot.admin.notify.hipchat.description
| Description to use in the event. SpEL-expressions are supported
| `+++"<strong>#{application.name}</strong>/#{application.id} is <strong>#{to.status}</strong>"+++`
|
|===
[reminder-notifactaions]
==== Reminder notifications ====
To get reminders for down/offline applications you can add a `RemindingNotifier` to your `ApplicationContext`. The `RemindingNotifier` uses another `Notifier` as delegate to send the reminders.
......
......@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.MailSender;
import de.codecentric.boot.admin.notify.HipchatNotifier;
import de.codecentric.boot.admin.notify.MailNotifier;
import de.codecentric.boot.admin.notify.Notifier;
import de.codecentric.boot.admin.notify.NotifierListener;
......@@ -77,4 +78,17 @@ public class NotifierConfiguration {
return new PagerdutyNotifier();
}
}
@Configuration
@ConditionalOnProperty(prefix = "spring.boot.admin.notify.hipchat", name = "url")
@AutoConfigureBefore({ NotifierListenerConfiguration.class })
public class HipchatNotifierConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.boot.admin.notify.hipchat", name = "enabled", matchIfMissing = true)
@ConfigurationProperties("spring.boot.admin.notify.hipchat")
public HipchatNotifier hipchatNotifier() {
return new HipchatNotifier();
}
}
}
package de.codecentric.boot.admin.notify;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.web.client.RestTemplate;
import de.codecentric.boot.admin.event.ClientApplicationStatusChangedEvent;
/**
* Notifier submitting events to HipChat.
*
* @author Jamie Brown
*/
public class HipchatNotifier extends AbstractStatusChangeNotifier {
private final static String DEFAULT_DESCRIPTION = "<strong>#{application.name}</strong>/#{application.id} is <strong>#{to.status}</strong>";
private final SpelExpressionParser parser = new SpelExpressionParser();
private RestTemplate restTemplate = new RestTemplate();
/**
* Base URL for HipChat API (i.e. https://ACCOUNT_NAME.hipchat.com/v2
*/
private URI url;
/**
* API token that has access to notify in the room
*/
private String authToken;
/**
* Id of the room to notify
*/
private String roomId;
/**
* TRUE will cause OS notification, FALSE will only notify to room
*/
private Boolean notify;
/**
* Trigger description. SpEL template using event as root;
*/
private Expression description;
public HipchatNotifier() {
this.description = parser.parseExpression(DEFAULT_DESCRIPTION,
ParserContext.TEMPLATE_EXPRESSION);
}
@Override
protected void doNotify(ClientApplicationStatusChangedEvent event) {
restTemplate.postForEntity(buildUrl(), createHipChatNotification(event), Void.class);
}
protected String buildUrl() {
return String.format("%s/room/%s/notification?auth_token=%s", url.toString(), roomId,
authToken);
}
private Map<String, Object> createHipChatNotification(
ClientApplicationStatusChangedEvent event) {
Map<String, Object> result = new HashMap<String, Object>();
String color = "UP".equals(event.getTo().getStatus()) ? "green" : "red";
String message = description.getValue(event, String.class);
result.put("color", color);
result.put("message", message);
result.put("notify", Boolean.TRUE.equals(notify));
result.put("message_format", "html");
return result;
}
public void setUrl(URI url) {
this.url = url;
}
public void setAuthToken(String authToken) {
this.authToken = authToken;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
public void setNotify(Boolean notify) {
this.notify = notify;
}
public void setDescription(String description) {
this.description = parser.parseExpression(description, ParserContext.TEMPLATE_EXPRESSION);
}
public void setRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
}
package de.codecentric.boot.admin.notify;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.web.client.RestTemplate;
import de.codecentric.boot.admin.event.ClientApplicationStatusChangedEvent;
import de.codecentric.boot.admin.model.Application;
import de.codecentric.boot.admin.model.StatusInfo;
/**
* @author Jamie Brown
*/
public class HipchatNotifierTest {
private HipchatNotifier notifier;
private RestTemplate restTemplate;
@Before
public void setUp() {
restTemplate = mock(RestTemplate.class);
notifier = new HipchatNotifier();
notifier.setNotify(true);
notifier.setAuthToken("--token-");
notifier.setRoomId("-room-");
notifier.setUrl(URI.create("http://localhost/v2"));
notifier.setRestTemplate(restTemplate);
}
@Test
public void test_onApplicationEvent_resolve() {
StatusInfo infoDown = StatusInfo.ofDown();
StatusInfo infoUp = StatusInfo.ofUp();
notifier.notify(new ClientApplicationStatusChangedEvent(
Application.create("App").withId("-id-").withHealthUrl("http://health").build(),
infoDown, infoUp));
Map<String, Object> expected = new HashMap<String, Object>();
expected.put("color", "green");
expected.put("message", "<strong>App</strong>/-id- is <strong>UP</strong>");
expected.put("notify", Boolean.TRUE);
expected.put("message_format", "html");
verify(restTemplate).postForEntity(any(String.class), eq(expected), eq(Void.class));
}
@Test
public void test_onApplicationEvent_trigger() {
StatusInfo infoDown = StatusInfo.ofDown();
StatusInfo infoUp = StatusInfo.ofUp();
notifier.notify(new ClientApplicationStatusChangedEvent(
Application.create("App").withId("-id-").withHealthUrl("http://health").build(),
infoUp, infoDown));
Map<String, Object> expected = new HashMap<String, Object>();
expected.put("color", "red");
expected.put("message", "<strong>App</strong>/-id- is <strong>DOWN</strong>");
expected.put("notify", Boolean.TRUE);
expected.put("message_format", "html");
verify(restTemplate).postForEntity(any(String.class), eq(expected), eq(Void.class));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment