You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ak...@apache.org on 2019/10/02 18:22:21 UTC
[incubator-pinot] branch master updated: [TE] Clean up legacy group
id and name logic (#4656)
This is an automated email from the ASF dual-hosted git repository.
akshayrai09 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 0b69aab [TE] Clean up legacy group id and name logic (#4656)
0b69aab is described below
commit 0b69aab2fc207dcb35458c3de7d852bb615a27d6
Author: Akshay Rai <ak...@linkedin.com>
AuthorDate: Wed Oct 2 11:22:14 2019 -0700
[TE] Clean up legacy group id and name logic (#4656)
---
.../anomaly/alert/v2/AlertTaskRunnerV2.java | 363 +--------------------
.../onboard/tasks/NotificationOnboardingTask.java | 2 +-
.../alert/scheme/DetectionEmailAlerter.java | 2 +-
.../content/BaseNotificationContent.java | 18 +-
.../notification/content/NotificationContent.java | 2 +-
.../content/templates/EntityGroupKeyContent.java | 4 +-
.../templates/HierarchicalAnomaliesContent.java | 4 +-
.../content/templates/MetricAnomaliesContent.java | 4 +-
.../templates/OnboardingNotificationContent.java | 5 +-
.../formatter/channels/EmailContentFormatter.java | 7 +-
.../templates/TestEntityGroupKeyContent.java | 6 +-
.../TestHierarchicalAnomaliesContent.java | 3 +-
.../templates/TestMetricAnomaliesContent.java | 2 +-
.../TestOnboardingNotificationContent.java | 2 +-
14 files changed, 29 insertions(+), 395 deletions(-)
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/alert/v2/AlertTaskRunnerV2.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/alert/v2/AlertTaskRunnerV2.java
index 5a5915a..8ad4389 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/alert/v2/AlertTaskRunnerV2.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/alert/v2/AlertTaskRunnerV2.java
@@ -21,29 +21,10 @@ package org.apache.pinot.thirdeye.anomaly.alert.v2;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
-import org.apache.pinot.thirdeye.alert.commons.AnomalyFeedConfig;
-import org.apache.pinot.thirdeye.alert.commons.AnomalyFeedFactory;
-import org.apache.pinot.thirdeye.datalayer.util.ThirdEyeStringUtils;
-import org.apache.pinot.thirdeye.notification.content.BaseNotificationContent;
-import org.apache.pinot.thirdeye.notification.formatter.AlertContentFormatterFactory;
-import org.apache.pinot.thirdeye.notification.commons.EmailEntity;
-import org.apache.pinot.thirdeye.notification.formatter.ADContentFormatterContext;
-import org.apache.pinot.thirdeye.notification.formatter.channels.EmailContentFormatter;
-import org.apache.pinot.thirdeye.alert.feed.AnomalyFeed;
import org.apache.pinot.thirdeye.anomaly.SmtpConfiguration;
import org.apache.pinot.thirdeye.anomaly.ThirdEyeAnomalyConfiguration;
import org.apache.pinot.thirdeye.anomaly.alert.AlertTaskInfo;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.AlertGrouper;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.AlertGrouperFactory;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.DummyAlertGrouper;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.SimpleGroupedAnomalyMerger;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.auxiliary_info_provider.AlertGroupAuxiliaryInfoProvider;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.auxiliary_info_provider.AlertGroupRecipientProviderFactory;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.auxiliary_info_provider.AuxiliaryAlertGroupInfo;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.filter.AlertGroupFilter;
-import org.apache.pinot.thirdeye.anomaly.alert.grouping.filter.AlertGroupFilterFactory;
import org.apache.pinot.thirdeye.anomaly.alert.template.pojo.MetricDimensionReport;
-import org.apache.pinot.thirdeye.anomaly.alert.util.AlertFilterHelper;
import org.apache.pinot.thirdeye.anomaly.alert.util.DataReportHelper;
import org.apache.pinot.thirdeye.anomaly.alert.util.EmailHelper;
import org.apache.pinot.thirdeye.anomaly.task.TaskContext;
@@ -52,29 +33,16 @@ import org.apache.pinot.thirdeye.anomaly.task.TaskResult;
import org.apache.pinot.thirdeye.anomaly.task.TaskRunner;
import org.apache.pinot.thirdeye.anomaly.utils.EmailUtils;
import org.apache.pinot.thirdeye.anomaly.utils.ThirdeyeMetricsUtil;
-import org.apache.pinot.thirdeye.anomalydetection.context.AnomalyResult;
-import org.apache.pinot.thirdeye.common.dimension.DimensionMap;
-import org.apache.pinot.thirdeye.constant.AnomalyResultSource;
import org.apache.pinot.thirdeye.dashboard.views.contributor.ContributorViewResponse;
import org.apache.pinot.thirdeye.datalayer.bao.AlertConfigManager;
-import org.apache.pinot.thirdeye.datalayer.bao.AlertSnapshotManager;
-import org.apache.pinot.thirdeye.datalayer.bao.GroupedAnomalyResultsManager;
-import org.apache.pinot.thirdeye.datalayer.bao.MergedAnomalyResultManager;
import org.apache.pinot.thirdeye.datalayer.bao.MetricConfigManager;
import org.apache.pinot.thirdeye.datalayer.dto.AlertConfigDTO;
-import org.apache.pinot.thirdeye.datalayer.dto.AlertSnapshotDTO;
-import org.apache.pinot.thirdeye.datalayer.dto.GroupedAnomalyResultsDTO;
-import org.apache.pinot.thirdeye.datalayer.dto.MergedAnomalyResultDTO;
import org.apache.pinot.thirdeye.datalayer.dto.MetricConfigDTO;
-import org.apache.pinot.thirdeye.datalayer.pojo.AlertConfigBean.AlertGroupConfig;
-import org.apache.pinot.thirdeye.datalayer.pojo.AlertConfigBean.EmailConfig;
-import org.apache.pinot.thirdeye.datalayer.pojo.AlertConfigBean.EmailFormatterConfig;
import org.apache.pinot.thirdeye.datalayer.pojo.AlertConfigBean.ReportConfigCollection;
import org.apache.pinot.thirdeye.datalayer.pojo.AlertConfigBean.ReportMetricConfig;
import org.apache.pinot.thirdeye.datasource.DAORegistry;
import org.apache.pinot.thirdeye.detection.ConfigUtils;
import org.apache.pinot.thirdeye.detection.alert.DetectionAlertFilterRecipients;
-import org.apache.pinot.thirdeye.detector.email.filter.AlertFilterFactory;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
@@ -85,15 +53,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.MapUtils;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
@@ -104,36 +67,31 @@ import org.slf4j.LoggerFactory;
import static org.apache.pinot.thirdeye.anomaly.SmtpConfiguration.SMTP_CONFIG_KEY;
-
+/**
+ * This method of sending emails is deprecated. This class will be removed once
+ * we migrate/deprecate the daily data report.
+ *
+ * @deprecated use {@link org.apache.pinot.thirdeye.detection.alert.scheme.DetectionEmailAlerter} instead.
+ */
@Deprecated
public class AlertTaskRunnerV2 implements TaskRunner {
private static final Logger LOG = LoggerFactory.getLogger(AlertTaskRunnerV2.class);
public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("America/Los_Angeles");
- public static final String DEFAULT_EMAIL_FORMATTER_TYPE = "MetricAnomaliesContent";
public static final String CHARSET = "UTF-8";
public static final String EMAIL_WHITELIST_KEY = "emailWhitelist";
- private final MergedAnomalyResultManager anomalyMergedResultDAO;
private final AlertConfigManager alertConfigDAO;
private final MetricConfigManager metricConfigManager;
- private final GroupedAnomalyResultsManager groupedAnomalyResultsDAO;
- private final AlertSnapshotManager alertSnapshotDAO;
private AlertConfigDTO alertConfig;
private ThirdEyeAnomalyConfiguration thirdeyeConfig;
- private AlertFilterFactory alertFilterFactory;
- private AlertGroupRecipientProviderFactory alertGroupAuxiliaryInfoProviderFactory;
- private final String MAX_ALLOWED_MERGE_GAP_KEY = "maxAllowedMergeGap";
- private final long DEFAULT_MAX_ALLOWED_MERGE_GAP = 14400000L;
+
public AlertTaskRunnerV2() {
- anomalyMergedResultDAO = DAORegistry.getInstance().getMergedAnomalyResultDAO();
alertConfigDAO = DAORegistry.getInstance().getAlertConfigDAO();
- alertSnapshotDAO = DAORegistry.getInstance().getAlertSnapshotDAO();
metricConfigManager = DAORegistry.getInstance().getMetricConfigDAO();
- groupedAnomalyResultsDAO = DAORegistry.getInstance().getGroupedAnomalyResultsDAO();
}
@Override
@@ -144,9 +102,6 @@ public class AlertTaskRunnerV2 implements TaskRunner {
// Fetch the latest alert config instead of the one provided by task context, which could be out-of-dated.
alertConfig = alertConfigDAO.findById(alertTaskInfo.getAlertConfigDTO().getId());
thirdeyeConfig = taskContext.getThirdEyeAnomalyConfiguration();
- alertFilterFactory = new AlertFilterFactory(thirdeyeConfig.getAlertFilterConfigPath());
- alertGroupAuxiliaryInfoProviderFactory =
- new AlertGroupRecipientProviderFactory(thirdeyeConfig.getAlertGroupRecipientProviderConfigPath());
try {
LOG.info("Begin executing task {}", taskInfo);
@@ -166,199 +121,12 @@ public class AlertTaskRunnerV2 implements TaskRunner {
try {
LOG.info("Starting email report for id : {}, name : {} ", alertConfig.getId(),
alertConfig.getName());
- sendAnomalyReport();
sendScheduledDataReport();
-
} finally {
ThirdeyeMetricsUtil.alertTaskSuccessCounter.inc();
}
}
- private void sendAnomalyReport() throws Exception {
- EmailConfig emailConfig = alertConfig.getEmailConfig();
- List<MergedAnomalyResultDTO> results = new ArrayList<>();
- List<MergedAnomalyResultDTO> mergedAnomaliesAllResults = new ArrayList<>();
- AnomalyFeed anomalyFeed = null;
- if (alertConfig.getAnomalyFeedConfig() != null &&
- StringUtils.isNotBlank(alertConfig.getAnomalyFeedConfig().getAnomalyFeedType())) {
- LOG.info("Use Anomaly Feed for alert {}", alertConfig.getId());
- AnomalyFeedConfig anomalyFeedConfig = alertConfig.getAnomalyFeedConfig();
- AlertSnapshotDTO alertSnapshot = alertSnapshotDAO.findById(anomalyFeedConfig.getAlertSnapshotId());
- if (alertSnapshot == null) { // if alert snapshot doesn't exist, create a new one
- alertSnapshot = new AlertSnapshotDTO();
- alertSnapshot.setLastNotifyTime(0);
- long snapshotId = alertSnapshotDAO.save(alertSnapshot);
- anomalyFeedConfig.setAlertSnapshotId(snapshotId);
- alertConfigDAO.update(alertConfig);
- }
- anomalyFeed = AnomalyFeedFactory.fromClassName(anomalyFeedConfig.getAnomalyFeedType());
- anomalyFeed.init(alertFilterFactory, anomalyFeedConfig);
- Collection<MergedAnomalyResultDTO> anaomalyAlertCandidates = anomalyFeed.getAnomalyFeed();
- mergedAnomaliesAllResults.addAll(anaomalyAlertCandidates);
- } else if (emailConfig != null && emailConfig.getFunctionIds() != null) {
- LOG.info("Use Email Config for alert {}", alertConfig.getId());
- List<Long> functionIds = alertConfig.getEmailConfig().getFunctionIds();
- long lastNotifiedAnomaly = emailConfig.getAnomalyWatermark();
- for (Long functionId : functionIds) {
- List<MergedAnomalyResultDTO> resultsForFunction =
- anomalyMergedResultDAO.findByFunctionIdAndIdGreaterThan(functionId, lastNotifiedAnomaly);
- if (CollectionUtils.isNotEmpty(resultsForFunction)) {
- mergedAnomaliesAllResults.addAll(resultsForFunction);
- }
- // fetch anomalies having id lesser than the watermark for the same function with notified = false & endTime > last one day
- // these anomalies are the ones that did not qualify filtration rule and got modified.
- // We should add these again so that these could be included in email if qualified through filtration rule
- List<MergedAnomalyResultDTO> filteredAnomalies = anomalyMergedResultDAO.findUnNotifiedByFunctionIdAndIdLesserThanAndEndTimeGreaterThanLastOneDay(functionId,
- lastNotifiedAnomaly);
- if (CollectionUtils.isNotEmpty(filteredAnomalies)) {
- mergedAnomaliesAllResults.addAll(filteredAnomalies);
- }
- }
- }
- // apply filtration rule
- results = AlertFilterHelper.applyFiltrationRule(mergedAnomaliesAllResults, alertFilterFactory);
-
- // only anomalies detected by default scheduler are sent; the anomalies detected during replay or given by users will not be sent
- Iterator<MergedAnomalyResultDTO> mergedAnomalyIterator = results.iterator();
- while (mergedAnomalyIterator.hasNext()) {
- MergedAnomalyResultDTO anomaly = mergedAnomalyIterator.next();
- if (anomaly.getAnomalyResultSource() == null) {
- continue;
- }
- if (!AnomalyResultSource.DEFAULT_ANOMALY_DETECTION.equals(anomaly.getAnomalyResultSource())) {
- mergedAnomalyIterator.remove();
- }
- }
-
- if (results.isEmpty()) {
- LOG.info("Zero anomalies found, skipping sending email");
- } else {
- // TODO: Add dimensional alert grouping before the stage of task runner?
- // There are two approaches to solve the problem of alert grouping:
- // 1. Anomaly results from detection --> Grouped anomalies from grouper --> Alerter sends emails on grouped anomalies
- // 2. Anomaly results from detection --> Alerter performs simple grouping and sends alerts in one go
-
- // Current implementation uses the second approach for experimental purpose. We might need to move to
- // approach 1 in order to consider multi-metric grouping.
- // Input: a list of anomalies.
- // Output: lists of anomalies; each list contains the anomalies of the same group.
- AlertGroupConfig alertGroupConfig = alertConfig.getAlertGroupConfig();
- if (alertGroupConfig == null) {
- alertGroupConfig = new AlertGroupConfig();
- }
- AlertGrouper alertGrouper = AlertGrouperFactory.fromSpec(alertGroupConfig.getGroupByConfig());
- Map<DimensionMap, GroupedAnomalyResultsDTO> groupedAnomalyResultsMap = alertGrouper.group(results);
-
- Map<DimensionMap, GroupedAnomalyResultsDTO> filteredGroupedAnomalyResultsMap;
- // DummyAlertGroupFilter does not generate any GroupedAnomaly. Thus, we don't apply any additional processes.
- if (alertGrouper instanceof DummyAlertGrouper) {
- filteredGroupedAnomalyResultsMap = groupedAnomalyResultsMap;
- } else {
- filteredGroupedAnomalyResultsMap = timeBasedMergeAndFilterGroupedAnomalies(groupedAnomalyResultsMap, alertGroupConfig);
- }
-
- for (Map.Entry<DimensionMap, GroupedAnomalyResultsDTO> entry : filteredGroupedAnomalyResultsMap.entrySet()) {
- // Anomaly results for this group
- DimensionMap dimensions = entry.getKey();
- GroupedAnomalyResultsDTO groupedAnomalyDTO = entry.getValue();
- List<AnomalyResult> anomalyResultListOfGroup = new ArrayList<>();
- for (MergedAnomalyResultDTO anomaly : groupedAnomalyDTO.getAnomalyResults()) {
- anomalyResultListOfGroup.add(anomaly);
- }
- // Append auxiliary recipients for this group
- DetectionAlertFilterRecipients recipientsForThisGroup = alertConfig.getReceiverAddresses();
- // Get auxiliary email recipient from provider
- AlertGroupAuxiliaryInfoProvider auxiliaryInfoProvider =
- alertGroupAuxiliaryInfoProviderFactory.fromSpec(alertGroupConfig.getGroupAuxiliaryEmailProvider());
- AuxiliaryAlertGroupInfo auxiliaryInfo =
- auxiliaryInfoProvider.getAlertGroupAuxiliaryInfo(dimensions, groupedAnomalyDTO.getAnomalyResults());
- // Check if this group should be skipped
- if (auxiliaryInfo.isSkipGroupAlert()) {
- continue;
- }
- // Construct email subject
- StringBuilder emailSubjectBuilder = new StringBuilder("Thirdeye Alert : ");
- emailSubjectBuilder.append(alertConfig.getName());
- // Append group tag to email subject
- if (StringUtils.isNotBlank(auxiliaryInfo.getGroupTag())) {
- emailSubjectBuilder.append(" (").append(auxiliaryInfo.getGroupTag()).append(") ");
- }
- // Append auxiliary recipients
- recipientsForThisGroup.getTo().addAll(EmailUtils.getValidEmailAddresses(auxiliaryInfo.getAuxiliaryRecipients()));
-
- // Construct group name if dimensions of this group is not empty
- String groupName = null;
- if (dimensions.size() != 0) {
- StringBuilder sb = new StringBuilder();
- String separator = "";
- for (Map.Entry<String, String> dimension : dimensions.entrySet()) {
- sb.append(separator).append(dimension.getKey()).append(":").append(dimension.getValue());
- separator = ", ";
- }
- groupName = sb.toString();
- }
- // Generate and send out an anomaly report for this group
- EmailContentFormatter emailFormatter;
- EmailFormatterConfig emailFormatterConfig = alertConfig.getEmailFormatterConfig();
- AlertContentFormatterFactory<BaseNotificationContent> alertContentFactory = new AlertContentFormatterFactory<>();
- BaseNotificationContent notificationContent;
- try {
- notificationContent = alertContentFactory.fromClassPath(Class.forName(emailFormatterConfig.getType()).getCanonicalName());
- } catch (Exception e) {
- LOG.error("User-assigned Email Formatter Config {} is not available. Use default instead.", alertConfig.getEmailFormatterConfig());
- notificationContent = alertContentFactory.fromClassPath(Class.forName(DEFAULT_EMAIL_FORMATTER_TYPE).getCanonicalName());
- }
-
- Properties prop;
- if (emailFormatterConfig != null && StringUtils.isNotBlank(emailFormatterConfig.getProperties())) {
- prop = ThirdEyeStringUtils.decodeCompactedProperties(emailFormatterConfig.getProperties());
- } else {
- prop = new Properties();
- }
- emailFormatter = new EmailContentFormatter(notificationContent, prop, thirdeyeConfig);
-
- // whitelisted recipients only
- List<String> emailWhitelist = ConfigUtils.getList(
- this.thirdeyeConfig.getAlerterConfiguration().get(SMTP_CONFIG_KEY).get(EMAIL_WHITELIST_KEY));
- if (!emailWhitelist.isEmpty()) {
- recipientsForThisGroup = retainWhitelisted(recipientsForThisGroup, emailWhitelist);
- }
-
- ADContentFormatterContext context = new ADContentFormatterContext();
- context.setAlertConfig(alertConfig);
- EmailEntity emailEntity = emailFormatter
- .getEmailEntity(recipientsForThisGroup, emailSubjectBuilder.toString(),
- groupedAnomalyDTO.getId(), groupName, anomalyResultListOfGroup, context);
- EmailHelper.sendEmailWithEmailEntity(emailEntity,
- SmtpConfiguration.createFromProperties(thirdeyeConfig.getAlerterConfiguration().get(SMTP_CONFIG_KEY)));
- // Update notified flag
- if (alertGrouper instanceof DummyAlertGrouper) {
- // DummyAlertGroupFilter does not generate real GroupedAnomaly, so the flag has to be set on merged anomalies.
- updateNotifiedStatus(groupedAnomalyDTO.getAnomalyResults());
- } else {
- // For other alert groupers, the notified flag is set on the grouped anomalies.
- groupedAnomalyDTO.setNotified(true);
- groupedAnomalyResultsDAO.update(groupedAnomalyDTO);
- }
- }
-
- // update anomaly watermark in alertConfig
- long lastNotifiedAlertId = emailConfig.getAnomalyWatermark();
- for (MergedAnomalyResultDTO anomalyResult : results) {
- if (anomalyResult.getId() > lastNotifiedAlertId) {
- lastNotifiedAlertId = anomalyResult.getId();
- }
- }
- if (lastNotifiedAlertId != emailConfig.getAnomalyWatermark()) {
- alertConfig.getEmailConfig().setAnomalyWatermark(lastNotifiedAlertId);
- alertConfigDAO.update(alertConfig);
- }
- if (anomalyFeed != null && results.size() > 0) {
- anomalyFeed.updateSnapshot(results);
- }
- }
- }
-
private void sendScheduledDataReport() throws Exception {
ReportConfigCollection reportConfigCollection =
alertConfig.getReportConfigCollection();
@@ -460,13 +228,6 @@ public class AlertTaskRunnerV2 implements TaskRunner {
}
}
- private void updateNotifiedStatus(List<MergedAnomalyResultDTO> mergedResults) {
- for (MergedAnomalyResultDTO mergedResult : mergedResults) {
- mergedResult.setNotified(true);
- anomalyMergedResultDAO.update(mergedResult);
- }
- }
-
private void sendFailureEmail(Throwable t) throws JobExecutionException {
HtmlEmail email = new HtmlEmail();
String subject = String
@@ -485,116 +246,6 @@ public class AlertTaskRunnerV2 implements TaskRunner {
}
/**
- * Given a map, which maps from a dimension map to a grouped anomaly, of new GroupedAnomalies, this method performs
- * a time based merged with existing grouped anomalies, which are stored in a DB. Afterwards, if a merged grouped
- * anomaly passes through the filter, it is returned in a map.
- *
- * @param groupedAnomalyResultsMap a map of new GroupedAnomaly.
- * @param alertGroupConfig the configuration for alert group.
- *
- * @return a map of merged GroupedAnomaly that pass through the filter.
- */
- private Map<DimensionMap, GroupedAnomalyResultsDTO> timeBasedMergeAndFilterGroupedAnomalies(
- Map<DimensionMap, GroupedAnomalyResultsDTO> groupedAnomalyResultsMap,
- AlertGroupConfig alertGroupConfig) {
- // Populate basic fields of the new grouped anomaly
- for (Map.Entry<DimensionMap, GroupedAnomalyResultsDTO> entry : groupedAnomalyResultsMap.entrySet()) {
- GroupedAnomalyResultsDTO groupedAnomaly = entry.getValue();
- DimensionMap dimensions = entry.getKey();
- groupedAnomaly.setAlertConfigId(alertConfig.getId());
- groupedAnomaly.setDimensions(dimensions);
- }
-
- Map<DimensionMap, GroupedAnomalyResultsDTO> mergedGroupedAnomalyResultsMap =
- this.timeBasedMergeGroupedAnomalyResults(groupedAnomalyResultsMap,
- alertGroupConfig.getGroupTimeBasedMergeConfig());
- // Read and update grouped anomalies in DB
- for (Map.Entry<DimensionMap, GroupedAnomalyResultsDTO> entry : mergedGroupedAnomalyResultsMap.entrySet()) {
- GroupedAnomalyResultsDTO groupedAnomaly = entry.getValue();
- Long groupId = groupedAnomalyResultsDAO.save(groupedAnomaly);
- groupedAnomaly.setId(groupId);
- for (MergedAnomalyResultDTO mergedAnomalyResultDTO : groupedAnomaly.getAnomalyResults()) {
- if (!mergedAnomalyResultDTO.isNotified()) {
- mergedAnomalyResultDTO.setNotified(true);
- anomalyMergedResultDAO.update(mergedAnomalyResultDTO);
- }
- }
- }
-
- // Filter out the grouped anomalies that trigger an alert
- return this
- .filterMergedGroupedAnomalyResults(mergedGroupedAnomalyResultsMap, alertGroupConfig.getGroupFilterConfig());
- }
-
- /**
- * Given a map, which maps from a dimension map to a grouped anomaly, of new GroupedAnomalies, this method performs
- * a time based merged with existing grouped anomalies, which are stored in a DB.
- *
- * @param newGroupedAnomalies a map of new GroupedAnomaly.
- * @param mergeConfig the configuration for time-based merge strategy.
- *
- * @return a map of merged GroupedAnomaly in time dimensions.
- */
- private Map<DimensionMap, GroupedAnomalyResultsDTO> timeBasedMergeGroupedAnomalyResults(
- Map<DimensionMap, GroupedAnomalyResultsDTO> newGroupedAnomalies, Map<String, String> mergeConfig) {
-
- // Parse max allowed merge gap from config
- long maxAllowedMergeGap = DEFAULT_MAX_ALLOWED_MERGE_GAP;
- if (MapUtils.isNotEmpty(mergeConfig)) {
- if (mergeConfig.containsKey(MAX_ALLOWED_MERGE_GAP_KEY)) {
- try {
- Long value = Long.parseLong(mergeConfig.get(MAX_ALLOWED_MERGE_GAP_KEY));
- maxAllowedMergeGap = value;
- } catch (Exception e) {
- LOG.warn("Failed to parse {} as 'MAX_ALLOWED_MERGE_GAP_KEY'; Use default value {}",
- mergeConfig.get(MAX_ALLOWED_MERGE_GAP_KEY), DEFAULT_MAX_ALLOWED_MERGE_GAP);
- }
- }
- }
-
- // Retrieve the most recent grouped anomalies from DB
- // TODO: Get update time from merged anomaly after the field "updateTime" is updated in DB correctly
- Map<DimensionMap, GroupedAnomalyResultsDTO> recentGroupedAnomalies = new HashMap<>();
- for (Map.Entry<DimensionMap, GroupedAnomalyResultsDTO> groupedAnomalyEntry : newGroupedAnomalies.entrySet()) {
- DimensionMap dimensions = groupedAnomalyEntry.getKey();
- GroupedAnomalyResultsDTO newGroupedAnomaly = groupedAnomalyEntry.getValue();
-
- long approximateUpdateTime = newGroupedAnomaly.getEndTime();
- GroupedAnomalyResultsDTO recentGroupedAnomaly = groupedAnomalyResultsDAO
- .findMostRecentInTimeWindow(alertConfig.getId(), dimensions.toString(),
- approximateUpdateTime - maxAllowedMergeGap, approximateUpdateTime);
- recentGroupedAnomalies.put(dimensions, recentGroupedAnomaly);
- }
- // Merge grouped anomalies
- return SimpleGroupedAnomalyMerger.timeBasedMergeGroupedAnomalyResults(recentGroupedAnomalies, newGroupedAnomalies);
- }
-
- /**
- * Given a map, which maps from a dimension map to a grouped anomaly, of new GroupedAnomalies, this method returns
- * the GroupedAnomalies that pass through the filter.
- *
- * @param mergedGroupedAnomalies a map of GroupedAnomaly.
- * @param filterConfig the configuration for group filter
- *
- * @return a map of GroupedAnomaly that pass through the filter.
- */
- private Map<DimensionMap, GroupedAnomalyResultsDTO> filterMergedGroupedAnomalyResults(
- Map<DimensionMap, GroupedAnomalyResultsDTO> mergedGroupedAnomalies, Map<String, String> filterConfig) {
- Map<DimensionMap, GroupedAnomalyResultsDTO> filteredGroupedAnomalies = new HashMap<>();
- AlertGroupFilter filter = AlertGroupFilterFactory.fromSpec(filterConfig);
- for (Map.Entry<DimensionMap, GroupedAnomalyResultsDTO> groupedAnomalyEntry : mergedGroupedAnomalies.entrySet()) {
- GroupedAnomalyResultsDTO groupedAnomaly = groupedAnomalyEntry.getValue();
- if (!groupedAnomaly.isNotified()) {
- assert (groupedAnomalyEntry.getKey().equals(groupedAnomaly.getDimensions()));
- if (filter.isQualified(groupedAnomaly)) {
- filteredGroupedAnomalies.put(groupedAnomalyEntry.getKey(), groupedAnomaly);
- }
- }
- }
- return filteredGroupedAnomalies;
- }
-
- /**
* Retain whitelisted email addresses for email recipient string only.
*
* @param recipients email recipient
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/onboard/tasks/NotificationOnboardingTask.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/onboard/tasks/NotificationOnboardingTask.java
index 13f360b..23c82e7 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/onboard/tasks/NotificationOnboardingTask.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/anomaly/onboard/tasks/NotificationOnboardingTask.java
@@ -139,7 +139,7 @@ public class NotificationOnboardingTask extends BaseDetectionOnboardTask {
EmailContentFormatter
emailFormatter = new EmailContentFormatter(new OnboardingNotificationContent(), thirdEyeAnomalyConfig);
EmailEntity emailEntity = emailFormatter.getEmailEntity(alertConfig.getReceiverAddresses(),
- subject, null, "", filteredAnomalyResults, context);
+ subject, filteredAnomalyResults, context);
try {
EmailHelper.sendEmailWithEmailEntity(emailEntity, smtpConfiguration);
} catch (EmailException e) {
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/alert/scheme/DetectionEmailAlerter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/alert/scheme/DetectionEmailAlerter.java
index 0f59f01..c85a806 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/alert/scheme/DetectionEmailAlerter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/alert/scheme/DetectionEmailAlerter.java
@@ -230,7 +230,7 @@ public class DetectionEmailAlerter extends DetectionAlertScheme {
ADContentFormatterContext context = new ADContentFormatterContext();
context.setAlertConfig(alertConfig);
EmailEntity emailEntity = emailContentFormatter.getEmailEntity(null,
- "Thirdeye Alert : " + this.config.getName(), null, null, anomalyResultListOfGroup,
+ "Thirdeye Alert : " + this.config.getName(), anomalyResultListOfGroup,
context);
if (emailEntity.getContent() == null) {
// Ignore, nothing to send
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/BaseNotificationContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/BaseNotificationContent.java
index f25eee0..f90a9a6 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/BaseNotificationContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/BaseNotificationContent.java
@@ -142,12 +142,9 @@ public abstract class BaseNotificationContent implements NotificationContent {
/**
* Generate subject based on configuration.
*/
- public static String makeSubject(String baseSubject, String groupName, AlertConfigBean.SubjectType type, Map<String, Object> templateData) {
+ public static String makeSubject(String baseSubject, AlertConfigBean.SubjectType type, Map<String, Object> templateData) {
switch (type) {
case ALERT:
- if (StringUtils.isNotBlank(groupName)) {
- return baseSubject + " - " + groupName;
- }
return baseSubject;
case METRICS:
@@ -186,8 +183,7 @@ public abstract class BaseNotificationContent implements NotificationContent {
templateData.put("metricsMap", metricsMap);
}
- protected Map<String, Object> getTemplateData(AlertConfigDTO alertConfigDTO, Long groupId, String groupName,
- Collection<AnomalyResult> anomalies) {
+ protected Map<String, Object> getTemplateData(AlertConfigDTO alertConfigDTO, Collection<AnomalyResult> anomalies) {
Map<String, Object> templateData = new HashMap<>();
DateTimeZone timeZone = DateTimeZone.forTimeZone(TimeZone.getTimeZone(DEFAULT_TIME_ZONE));
@@ -224,16 +220,6 @@ public abstract class BaseNotificationContent implements NotificationContent {
templateData.put("alertConfigName", alertConfigDTO.getName());
templateData.put("includeSummary", includeSummary);
templateData.put("reportGenerationTimeMillis", System.currentTimeMillis());
- if (groupId != null) {
- templateData.put("isGroupedAnomaly", true);
- templateData.put("groupId", Long.toString(groupId));
- } else {
- templateData.put("isGroupedAnomaly", false);
- templateData.put("groupId", Long.toString(-1));
- }
- if (StringUtils.isNotBlank(groupName)) {
- templateData.put("groupName", groupName);
- }
if(precisionRecallEvaluator.getTotalResponses() > 0) {
templateData.put("precision", precisionRecallEvaluator.getPrecisionInResponse());
templateData.put("recall", precisionRecallEvaluator.getRecall());
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/NotificationContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/NotificationContent.java
index 9564094..da08685 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/NotificationContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/NotificationContent.java
@@ -41,7 +41,7 @@ public interface NotificationContent {
/**
* Generate the template dictionary from the list of anomaly results to render in the template
*/
- Map<String, Object> format(Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context);
+ Map<String, Object> format(Collection<AnomalyResult> anomalies, ADContentFormatterContext context);
/**
* Retrieves the template file (.ftl)
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/EntityGroupKeyContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/EntityGroupKeyContent.java
index 4aafb60..278485b 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/EntityGroupKeyContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/EntityGroupKeyContent.java
@@ -95,8 +95,8 @@ public class EntityGroupKeyContent extends BaseNotificationContent {
}
@Override
- public Map<String, Object> format(Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
- Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), groupId, groupName, anomalies);
+ public Map<String, Object> format(Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
+ Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), anomalies);
DetectionConfigDTO config = null;
Preconditions.checkArgument(anomalies != null && !anomalies.isEmpty(), "Report has empty anomalies");
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/HierarchicalAnomaliesContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/HierarchicalAnomaliesContent.java
index fa0d2f5..e9bd63d 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/HierarchicalAnomaliesContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/HierarchicalAnomaliesContent.java
@@ -87,8 +87,8 @@ public class HierarchicalAnomaliesContent extends BaseNotificationContent {
}
@Override
- public Map<String, Object> format(Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
- Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), groupId, groupName, anomalies);
+ public Map<String, Object> format(Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
+ Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), anomalies);
enrichMetricInfo(templateData, anomalies);
List<AnomalyReportEntity> rootAnomalyDetails = new ArrayList<>();
SortedMap<String, List<AnomalyReportEntity>> leafAnomalyDetails = new TreeMap<>();
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/MetricAnomaliesContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/MetricAnomaliesContent.java
index 0965f16..8f18abb 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/MetricAnomaliesContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/MetricAnomaliesContent.java
@@ -71,8 +71,8 @@ public class MetricAnomaliesContent extends BaseNotificationContent {
}
@Override
- public Map<String, Object> format(Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
- Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), groupId, groupName, anomalies);
+ public Map<String, Object> format(Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
+ Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), anomalies);
enrichMetricInfo(templateData, anomalies);
DateTime windowStart = DateTime.now();
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/OnboardingNotificationContent.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/OnboardingNotificationContent.java
index e7731de..29b2872 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/OnboardingNotificationContent.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/content/templates/OnboardingNotificationContent.java
@@ -36,6 +36,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Deprecated
public class OnboardingNotificationContent extends BaseNotificationContent {
private static final Logger LOG = LoggerFactory.getLogger(OnboardingNotificationContent.class);
@@ -61,8 +62,8 @@ public class OnboardingNotificationContent extends BaseNotificationContent {
* The actual function that convert anomalies into parameter map
*/
@Override
- public Map<String, Object> format(Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
- Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), groupId, groupName, anomalies);
+ public Map<String, Object> format(Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
+ Map<String, Object> templateData = super.getTemplateData(context.getAlertConfig(), anomalies);
enrichMetricInfo(templateData, anomalies);
AnomalyFunctionDTO anomalyFunctionSpec = context.getAnomalyFunctionSpec();
for (AnomalyResult anomalyResult : anomalies) {
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/formatter/channels/EmailContentFormatter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/formatter/channels/EmailContentFormatter.java
index 2cfe7cc..42aaba8 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/formatter/channels/EmailContentFormatter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/notification/formatter/channels/EmailContentFormatter.java
@@ -70,12 +70,11 @@ public class EmailContentFormatter {
content.init(emailProps, teConfig);
}
- public EmailEntity getEmailEntity(DetectionAlertFilterRecipients recipients, String subject,
- Long groupId, String groupName, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
- Map<String, Object> templateData = notificationContent.format(groupId, groupName, anomalies, context);
+ public EmailEntity getEmailEntity(DetectionAlertFilterRecipients recipients, String subject, Collection<AnomalyResult> anomalies, ADContentFormatterContext context) {
+ Map<String, Object> templateData = notificationContent.format(anomalies, context);
templateData.put("dashboardHost", thirdEyeAnomalyConfig.getDashboardHost());
- String outputSubject = notificationContent.makeSubject(subject, groupName, context.getAlertConfig().getSubjectType(), templateData);
+ String outputSubject = notificationContent.makeSubject(subject, context.getAlertConfig().getSubjectType(), templateData);
return buildEmailEntity(templateData, outputSubject, recipients, context.getAlertConfig().getFromAddress(), notificationContent.getTemplate());
}
diff --git a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestEntityGroupKeyContent.java b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestEntityGroupKeyContent.java
index ec01557..3bc96cd 100644
--- a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestEntityGroupKeyContent.java
+++ b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestEntityGroupKeyContent.java
@@ -163,8 +163,7 @@ public class TestEntityGroupKeyContent {
ADContentFormatterContext context = new ADContentFormatterContext();
context.setAlertConfig(DaoTestUtils.getTestAlertConfiguration("Test Config"));
EmailEntity emailEntity = contentFormatter.getEmailEntity(
- new DetectionAlertFilterRecipients(EmailUtils.getValidEmailAddresses("a@b.com")),
- TEST, null, "", anomalies, context);
+ new DetectionAlertFilterRecipients(EmailUtils.getValidEmailAddresses("a@b.com")), TEST, anomalies, context);
String htmlPath = ClassLoader.getSystemResource("test-entity-groupby-email-content-formatter.html").getPath();
Assert.assertEquals(
@@ -282,8 +281,7 @@ public class TestEntityGroupKeyContent {
ADContentFormatterContext context = new ADContentFormatterContext();
context.setAlertConfig(DaoTestUtils.getTestAlertConfiguration("Test Config"));
EmailEntity emailEntity = contentFormatter.getEmailEntity(
- new DetectionAlertFilterRecipients(EmailUtils.getValidEmailAddresses("a@b.com")),
- TEST, null, "", anomalies, context);
+ new DetectionAlertFilterRecipients(EmailUtils.getValidEmailAddresses("a@b.com")), TEST, anomalies, context);
String htmlPath = ClassLoader.getSystemResource("test-entity-groupby-with-whitelist-email-content-formatter.html").getPath();
Assert.assertEquals(
diff --git a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestHierarchicalAnomaliesContent.java b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestHierarchicalAnomaliesContent.java
index ff46cd9..fc46f65 100644
--- a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestHierarchicalAnomaliesContent.java
+++ b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestHierarchicalAnomaliesContent.java
@@ -154,8 +154,7 @@ public class TestHierarchicalAnomaliesContent {
context.setAlertConfig(alertConfigDTO);
DetectionAlertFilterRecipients recipients = new DetectionAlertFilterRecipients(
EmailUtils.getValidEmailAddresses("a@b.com"));
- EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST,
- null, "", anomalies, context);
+ EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST, anomalies, context);
String htmlPath = ClassLoader.getSystemResource("test-hierarchical-metric-anomalies-template.html").getPath();
Assert.assertEquals(
diff --git a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestMetricAnomaliesContent.java b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestMetricAnomaliesContent.java
index 5412b89..bef4d0d 100644
--- a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestMetricAnomaliesContent.java
+++ b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestMetricAnomaliesContent.java
@@ -135,7 +135,7 @@ public class TestMetricAnomaliesContent {
context.setAlertConfig(alertConfigDTO);
DetectionAlertFilterRecipients recipients = new DetectionAlertFilterRecipients(
EmailUtils.getValidEmailAddresses("a@b.com"));
- EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST, null, "", anomalies, context);
+ EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST, anomalies, context);
String htmlPath = ClassLoader.getSystemResource("test-metric-anomalies-template.html").getPath();
Assert.assertEquals(
diff --git a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestOnboardingNotificationContent.java b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestOnboardingNotificationContent.java
index b443ffd..13864ab 100644
--- a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestOnboardingNotificationContent.java
+++ b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/notification/content/templates/TestOnboardingNotificationContent.java
@@ -127,7 +127,7 @@ public class TestOnboardingNotificationContent {
contentFormatter = new EmailContentFormatter(new OnboardingNotificationContent(), thirdeyeAnomalyConfig);
DetectionAlertFilterRecipients recipients = new DetectionAlertFilterRecipients(
EmailUtils.getValidEmailAddresses("a@b.com"));
- EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST, null, "", anomalies, context);
+ EmailEntity emailEntity = contentFormatter.getEmailEntity(recipients, TEST, anomalies, context);
String htmlPath = ClassLoader.getSystemResource("test-onboard-notification-email-content-formatter.html").getPath();
Assert.assertEquals(
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org