package rocks.inspectit.server.template; import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import rocks.inspectit.server.alerting.state.AlertingState; import rocks.inspectit.server.alerting.util.AlertingUtils; import rocks.inspectit.server.template.AlertEMailTemplateType.Placeholders; import rocks.inspectit.shared.cs.ci.AlertingDefinition; import rocks.inspectit.shared.cs.communication.data.cmr.Alert; /** * Component to resolve templates for alerting e-mails. * * @author Marius Oehler * */ @Component public class EMailTemplateResolver { /** * Date format for pretty printing in email. */ private static final String DATE_FORMAT = "dd-MM-yyyy HH:mm:ss"; /** * Number format for pretty printing in email. */ private static final String NUMBER_FORMAT = "0.0#"; /** * {@link TemplateManager} used to load e-mail templates. */ @Autowired private TemplateManager templateManager; /** * Resolves an e-mail template for the given {@link AlertEMailTemplateType} and * {@link AlertingState}. * * @param templateType * the type of the template * @param alertingState * the state of the alert * @return a template represented as a {@link String} * @throws IOException * Thrown if the template cannot be resolved. */ public String resolveTemplate(AlertEMailTemplateType templateType, AlertingState alertingState) throws IOException { Map<String, String> propertiesMap = createPropertiesMap(alertingState, templateType.isText()); return templateManager.resolveTemplate(templateType, propertiesMap); } /** * Creates a map containing available values which are used to replace corresponding * placeholder. * * @param alertingState * the state of the alert * @param isText * whether the target template is textual * @return {@link Map} containing placeholder and corresponding values */ private Map<String, String> createPropertiesMap(AlertingState alertingState, boolean isText) { if (alertingState == null) { throw new IllegalArgumentException("The given alerting state may not be null."); } Map<String, String> properties = new HashMap<>(); NumberFormat numberFormat = new DecimalFormat(NUMBER_FORMAT); SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); Alert alert = alertingState.getAlert(); AlertingDefinition definition = alertingState.getAlertingDefinition(); properties.put(Placeholders.ALERT_DEFINITION_NAME, definition.getName()); properties.put(Placeholders.MEASUREMENT, definition.getMeasurement()); properties.put(Placeholders.FIELD, definition.getField()); properties.put(Placeholders.THRESHOLD, numberFormat.format(definition.getThreshold())); properties.put(Placeholders.THRESHOLD_TYPE, definition.getThresholdType().getName()); properties.put(Placeholders.START_TIME, String.valueOf(dateFormat.format(new Date(alert.getStartTimestamp())))); properties.put(Placeholders.VIOLATION_VALUE, numberFormat.format(alertingState.getExtremeValue())); properties.put(Placeholders.CURRENT_TIME, String.valueOf(new Date(System.currentTimeMillis()))); properties.put(Placeholders.ALERT_ID, alert.getId()); properties.put(Placeholders.EXTREME_VALUE, numberFormat.format(alertingState.getExtremeValue())); if (AlertingUtils.isBusinessTransactionAlert(definition)) { String applicationName = AlertingUtils.retrieveApplicaitonName(definition); if (null == applicationName) { applicationName = "All"; } properties.put(AlertEMailTemplateType.Placeholders.APPLICATION_NAME, applicationName); String businessTxName = AlertingUtils.retrieveBusinessTransactionName(definition); if (null == businessTxName) { businessTxName = "All"; } properties.put(AlertEMailTemplateType.Placeholders.BUSINESS_TX_NAME, businessTxName); } if (alert.getStopTimestamp() > 0) { properties.put(AlertEMailTemplateType.Placeholders.END_TIME, dateFormat.format(new Date(alert.getStopTimestamp()))); properties.put(AlertEMailTemplateType.Placeholders.CLOSING_REASON, alert.getClosingReason().toString()); } if (isText) { properties.put(Placeholders.TAGS, convertTagsToTextProperty(definition.getTags())); } else { properties.put(Placeholders.TAGS, convertTagsToHtmlTextProperty(definition.getTags())); } return properties; } /** * Converts a map of tags to text representation. * * @param tags * Tag map to convert. * @return A text representation of the tags. */ private String convertTagsToTextProperty(Map<String, String> tags) { StringBuilder stringBuilder = new StringBuilder(); String lineSep = System.getProperty("line.separator"); for (Entry<String, String> tagKeyValuePair : tags.entrySet()) { stringBuilder.append("- ").append(tagKeyValuePair.getKey()).append(": ").append(tagKeyValuePair.getValue()).append(lineSep); } return stringBuilder.toString(); } /** * Converts a map of tags to HTML text representation. * * @param tags * Tag map to convert. * @return A HTML text representation of the tags. */ private String convertTagsToHtmlTextProperty(Map<String, String> tags) { StringBuilder stringBuilder = new StringBuilder(); for (Entry<String, String> tagKeyValuePair : tags.entrySet()) { if (stringBuilder.length() > 0) { stringBuilder.append("<br />"); } stringBuilder.append(tagKeyValuePair.getKey()).append('=').append(tagKeyValuePair.getValue()); } return stringBuilder.toString(); } }