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/07/18 00:22:09 UTC

[incubator-pinot] branch master updated: [TE] Improvements to the Entity GroupKey Template (#4444)

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 2e07b0b  [TE] Improvements to the Entity GroupKey Template (#4444)
2e07b0b is described below

commit 2e07b0bd234e0b8673f7ff075c49f454cff6a1b9
Author: Akshay Rai <ak...@gmail.com>
AuthorDate: Wed Jul 17 17:22:04 2019 -0700

    [TE] Improvements to the Entity GroupKey Template (#4444)
---
 .../alert/content/BaseEmailContentFormatter.java   |  8 ++---
 .../content/EntityGroupByContentFormatter.java     | 38 ++++++++++++----------
 ...HierarchicalAnomaliesEmailContentFormatter.java |  4 +--
 .../MetricAnomaliesEmailContentFormatter.java      |  4 +--
 .../dashboard/resources/v2/pojo/SearchFilters.java |  2 --
 .../alert/scheme/DetectionEmailAlerter.java        | 19 ++++++-----
 .../apache/pinot/thirdeye/util/ThirdEyeUtils.java  |  5 +--
 .../detector/entity-groupby-anomaly-report.ftl     |  9 ++---
 .../tools/RunAdhocDatabaseQueriesTool.java         |  6 ++--
 ...est-entity-groupby-email-content-formatter.html | 18 +++++-----
 10 files changed, 59 insertions(+), 54 deletions(-)

diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/BaseEmailContentFormatter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/BaseEmailContentFormatter.java
index dd06e34..a645759 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/BaseEmailContentFormatter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/BaseEmailContentFormatter.java
@@ -599,13 +599,13 @@ public abstract class BaseEmailContentFormatter implements EmailContentFormatter
     private static String RAW_VALUE_FORMAT = "%.0f";
     private static String PERCENTAGE_FORMAT = "%.2f %%";
 
-    public AnomalyReportEntity(String anomalyId, String anomalyURL, String baselineVal, String currentVal, Double swi,
+    public AnomalyReportEntity(String anomalyId, String anomalyURL, double baselineVal, double currentVal, Double swi,
         List<String> dimensions, String duration, String feedback, String function, String funcDescription,
         String metric, String startTime, String endTime, String timezone, String issueType) {
       this.anomalyId = anomalyId;
       this.anomalyURL = anomalyURL;
-      this.baselineVal = baselineVal;
-      this.currentVal = currentVal;
+      this.baselineVal = ThirdEyeUtils.getRoundedValue(baselineVal);
+      this.currentVal = ThirdEyeUtils.getRoundedValue(currentVal);
       this.dimensions = dimensions;
       this.duration = duration;
       this.feedback = feedback;
@@ -615,7 +615,7 @@ public abstract class BaseEmailContentFormatter implements EmailContentFormatter
       if (swi != null) {
         this.swi = String.format(PERCENTAGE_FORMAT, swi * 100);
       }
-      double lift = BaseEmailContentFormatter.getLift(Double.valueOf(currentVal), Double.valueOf(baselineVal));
+      double lift = BaseEmailContentFormatter.getLift(currentVal, baselineVal);
       this.lift = String.format(PERCENTAGE_FORMAT, lift * 100);
       this.positiveLift = getLiftDirection(lift);
       this.metric = metric;
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/EntityGroupByContentFormatter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/EntityGroupByContentFormatter.java
index a20ed2a..632ec63 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/EntityGroupByContentFormatter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/EntityGroupByContentFormatter.java
@@ -23,16 +23,13 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.stream.Collectors;
 import org.apache.pinot.thirdeye.anomalydetection.context.AnomalyResult;
 import org.apache.pinot.thirdeye.datalayer.bao.DetectionConfigManager;
 import org.apache.pinot.thirdeye.datalayer.dto.DetectionConfigDTO;
@@ -57,9 +54,10 @@ public class EntityGroupByContentFormatter extends BaseEmailContentFormatter{
   static final String PROP_GROUP_KEY = "groupKey";
 
   private DetectionConfigManager configDAO = null;
-  private Map<String, Double> entityAnomalyToScoreMap = new HashMap<>();
-  private Multimap<String, AnomalyReportEntity> entityAnomalyReports = ArrayListMultimap.create();
-  private Map<String, String> entityToAnomalyIdsMap = new HashMap<>();
+  private Multimap<String, AnomalyReportEntity> entityToAnomaliesMap = ArrayListMultimap.create();
+  private Map<String, List<AnomalyReportEntity>> entityToSortedAnomaliesMap = new HashMap<>();
+  private Map<AnomalyReportEntity, Double> anomalyToGroupScoreMap = new HashMap<>();
+  private Map<String, String> anomalyToChildIdsMap = new HashMap<>();
 
   public EntityGroupByContentFormatter() {}
 
@@ -90,15 +88,16 @@ public class EntityGroupByContentFormatter extends BaseEmailContentFormatter{
       updateEntityToAnomalyDetailsMap(anomaly, config);
     }
 
-    List<Map.Entry<String, Double>> anomaliesSortedByScores = new ArrayList<>(entityAnomalyToScoreMap.entrySet());
-    anomaliesSortedByScores.sort(Map.Entry.comparingByValue());
-    List<String> entityList = anomaliesSortedByScores.stream().map(Map.Entry::getKey).collect(Collectors.toList());
-    entityList.sort(Collections.reverseOrder());
+    // Sort the anomalies within each entity by crticality score
+    for (String entityName : entityToAnomaliesMap.keySet()) {
+      List<AnomalyReportEntity> groupedAnomalies = (List<AnomalyReportEntity>) entityToAnomaliesMap.get(entityName);
+      groupedAnomalies.sort((u1, u2) -> anomalyToGroupScoreMap.get(u2).compareTo(anomalyToGroupScoreMap.get(u1)));
+      entityToSortedAnomaliesMap.put(entityName, groupedAnomalies);
+    }
 
     templateData.put("emailHeading", config.getName());
-    templateData.put("entityToAnomalyIdsMap", entityToAnomalyIdsMap);
-    templateData.put("entitySortedByScoreList", entityList);
-    templateData.put("entityToAnomalyDetailsMap", entityAnomalyReports.asMap());
+    templateData.put("anomalyToChildIdsMap", anomalyToChildIdsMap);
+    templateData.put("entityToSortedAnomaliesMap", entityToSortedAnomaliesMap);
   }
 
   /**
@@ -108,8 +107,8 @@ public class EntityGroupByContentFormatter extends BaseEmailContentFormatter{
     if (anomaly.getProperties() != null && anomaly.getProperties().containsKey(PROP_GROUP_KEY)) {
       AnomalyReportEntity anomalyReport = new AnomalyReportEntity(String.valueOf(anomaly.getId()),
           getAnomalyURL(anomaly, emailContentFormatterConfiguration.getDashboardHost()),
-          ThirdEyeUtils.getRoundedValue(anomaly.getAvgBaselineVal()),
-          ThirdEyeUtils.getRoundedValue(anomaly.getAvgCurrentVal()), 0d, null,
+          anomaly.getAvgBaselineVal(),
+          anomaly.getAvgCurrentVal(), 0d, null,
           getTimeDiffInHours(anomaly.getStartTime(), anomaly.getEndTime()), getFeedbackValue(anomaly.getFeedback()),
           detectionConfig.getName(), detectionConfig.getDescription(), anomaly.getMetric(),
           getDateString(anomaly.getStartTime(), dateTimeZone), getDateString(anomaly.getEndTime(), dateTimeZone),
@@ -134,9 +133,12 @@ public class EntityGroupByContentFormatter extends BaseEmailContentFormatter{
 
       // include notified alerts only in the email
       if (!includeSentAnomaliesOnly || anomaly.isNotified()) {
-        entityToAnomalyIdsMap.put(anomaly.getProperties().get(PROP_ENTITY_NAME), Joiner.on(",").join(childIds));
-        entityAnomalyToScoreMap.put(anomaly.getProperties().get(PROP_ENTITY_NAME), score);
-        entityAnomalyReports.put(anomaly.getProperties().get(PROP_ENTITY_NAME), anomalyReport);
+        // Freemarker doesn't support non-string key in the map. Hence the custom generated key using groupKey and startTime
+        // See https://freemarker.apache.org/docs/app_faq.html#faq_nonstring_keys
+        anomalyToChildIdsMap.put(anomalyReport.getGroupKey() + anomalyReport.getStartDateTime(), Joiner.on(",").join(childIds));
+
+        anomalyToGroupScoreMap.put(anomalyReport, score);
+        entityToAnomaliesMap.put(anomaly.getProperties().get(PROP_ENTITY_NAME), anomalyReport);
       }
     } else {
       for (MergedAnomalyResultDTO childAnomaly : anomaly.getChildren()) {
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/HierarchicalAnomaliesEmailContentFormatter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/HierarchicalAnomaliesEmailContentFormatter.java
index fd79eb9..dc3c3f5 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/HierarchicalAnomaliesEmailContentFormatter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/HierarchicalAnomaliesEmailContentFormatter.java
@@ -140,8 +140,8 @@ public class HierarchicalAnomaliesEmailContentFormatter extends BaseEmailContent
     AnomalyReportEntity
         anomalyReport = new AnomalyReportEntity(String.valueOf(anomaly.getId()),
         getAnomalyURL(anomaly, dashboardHost),
-        ThirdEyeUtils.getRoundedValue(anomaly.getAvgBaselineVal()),
-        ThirdEyeUtils.getRoundedValue(anomaly.getAvgCurrentVal()),
+        anomaly.getAvgBaselineVal(),
+        anomaly.getAvgCurrentVal(),
         anomaly.getImpactToGlobal(),
         getDimensionsList(anomaly.getDimensions()),
         getTimeDiffInHours(anomaly.getStartTime(), anomaly.getEndTime()), // duration
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/MetricAnomaliesEmailContentFormatter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/MetricAnomaliesEmailContentFormatter.java
index 51d8610..fad1356 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/MetricAnomaliesEmailContentFormatter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/alert/content/MetricAnomaliesEmailContentFormatter.java
@@ -129,8 +129,8 @@ public class MetricAnomaliesEmailContentFormatter extends BaseEmailContentFormat
 
       AnomalyReportEntity anomalyReport = new AnomalyReportEntity(String.valueOf(anomaly.getId()),
           getAnomalyURL(anomaly, emailContentFormatterConfiguration.getDashboardHost()),
-          ThirdEyeUtils.getRoundedValue(anomaly.getAvgBaselineVal()),
-          ThirdEyeUtils.getRoundedValue(anomaly.getAvgCurrentVal()),
+          anomaly.getAvgBaselineVal(),
+          anomaly.getAvgCurrentVal(),
           0d,
           getDimensionsList(anomaly.getDimensions()),
           getTimeDiffInHours(anomaly.getStartTime(), anomaly.getEndTime()), // duration
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/pojo/SearchFilters.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/pojo/SearchFilters.java
index e76cfa4..f766eeb 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/pojo/SearchFilters.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/pojo/SearchFilters.java
@@ -197,8 +197,6 @@ public class SearchFilters {
         String issueType = properties.get(ClassificationTaskRunner.ISSUE_TYPE_KEY);
         passed = passed && checkFilter(issueTypeFilterMap, issueType);
       }
-      // check isChild
-      passed = passed && !mergedAnomalyResultDTO.isChild(); // TODO configurable filter
 
       if (passed) {
         filteredAnomalies.add(mergedAnomalyResultDTO);
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 e059a4e..56377a9 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
@@ -25,6 +25,8 @@ import org.apache.pinot.thirdeye.alert.commons.EmailEntity;
 import org.apache.pinot.thirdeye.alert.content.EmailContentFormatter;
 import org.apache.pinot.thirdeye.alert.content.EmailContentFormatterConfiguration;
 import org.apache.pinot.thirdeye.alert.content.EmailContentFormatterContext;
+import org.apache.pinot.thirdeye.alert.content.EntityGroupByContentFormatter;
+import org.apache.pinot.thirdeye.alert.content.MetricAnomaliesEmailContentFormatter;
 import org.apache.pinot.thirdeye.anomaly.SmtpConfiguration;
 import org.apache.pinot.thirdeye.anomaly.ThirdEyeAnomalyConfiguration;
 import org.apache.pinot.thirdeye.anomalydetection.context.AnomalyResult;
@@ -60,8 +62,6 @@ public class DetectionEmailAlerter extends DetectionAlertScheme {
 
   private static final Comparator<AnomalyResult> COMPARATOR_DESC =
       (o1, o2) -> -1 * Long.compare(o1.getStartTime(), o2.getStartTime());
-  private static final String DEFAULT_EMAIL_FORMATTER_TYPE = "MetricAnomaliesEmailContentFormatter";
-  private static final String ENTITY_REPORT_FORMATTER_TYPE = "EntityContentFormatter";
   private static final String EMAIL_WHITELIST_KEY = "emailWhitelist";
   private static final String PROP_EMAIL_SCHEME = "emailScheme";
   private static final String PROP_EMAIL_TEMPLATE = "template";
@@ -143,17 +143,20 @@ public class DetectionEmailAlerter extends DetectionAlertScheme {
       template = EmailTemplate.valueOf(emailParams.get(PROP_EMAIL_TEMPLATE).toString());
     }
 
+    String className;
     switch (template) {
       case DEFAULT_EMAIL:
-        LOG.info("Using the " + DEFAULT_EMAIL_FORMATTER_TYPE + " email template.");
-        return EmailContentFormatterFactory.fromClassName(DEFAULT_EMAIL_FORMATTER_TYPE);
+        className = MetricAnomaliesEmailContentFormatter.class.getSimpleName();
+        LOG.info("Using " + className + " to render the template.");
+        return EmailContentFormatterFactory.fromClassName(className);
 
       case ENTITY_GROUPBY_REPORT:
-        LOG.info("Using the " + template + " email template.");
-        return EmailContentFormatterFactory.fromClassName(ENTITY_REPORT_FORMATTER_TYPE);
+        className = EntityGroupByContentFormatter.class.getSimpleName();
+        LOG.info("Using " + className + " to render the template.");
+        return EmailContentFormatterFactory.fromClassName(className);
 
       default:
-        throw new IllegalArgumentException(String.format("Unknown type '%s'", template));
+        throw new IllegalArgumentException(String.format("Unknown email template '%s'", template));
     }
   }
 
@@ -209,7 +212,7 @@ public class DetectionEmailAlerter extends DetectionAlertScheme {
   }
 
   private void generateAndSendEmails(DetectionAlertFilterResult detectionResult) throws Exception {
-    LOG.info("Sending Email alert for {}", config.getId());
+    LOG.info("Preparing an email alert for subscription group id {}", config.getId());
     Preconditions.checkNotNull(detectionResult.getResult());
     for (Map.Entry<DetectionAlertFilterRecipients, Set<MergedAnomalyResultDTO>> entry : detectionResult.getResult().entrySet()) {
       DetectionAlertFilterRecipients recipients = entry.getKey();
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/util/ThirdEyeUtils.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/util/ThirdEyeUtils.java
index 04b1cc9..b334c2a 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/util/ThirdEyeUtils.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/util/ThirdEyeUtils.java
@@ -88,8 +88,8 @@ public abstract class ThirdEyeUtils {
   private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
   private static final DAORegistry DAO_REGISTRY = DAORegistry.getInstance();
   private static final ThirdEyeCacheRegistry CACHE_REGISTRY = ThirdEyeCacheRegistry.getInstance();
-  private static final String TWO_DECIMALS_FORMAT = "##.##";
-  private static final String MAX_DECIMALS_FORMAT = "##.#####";
+  private static final String TWO_DECIMALS_FORMAT = "#,###.##";
+  private static final String MAX_DECIMALS_FORMAT = "#,###.#####";
   private static final String DECIMALS_FORMAT_TOKEN = "#";
 
   private static final int DEFAULT_HEAP_PERCENTAGE_FOR_RESULTSETGROUP_CACHE = 50;
@@ -436,6 +436,7 @@ public abstract class ThirdEyeUtils {
       compareValue = compareValue * 0.1;
     }
     DecimalFormat decimalFormat = new DecimalFormat(decimalFormatBuffer.toString());
+
     return decimalFormat.format(value);
   }
 
diff --git a/thirdeye/thirdeye-pinot/src/main/resources/org/apache/pinot/thirdeye/detector/entity-groupby-anomaly-report.ftl b/thirdeye/thirdeye-pinot/src/main/resources/org/apache/pinot/thirdeye/detector/entity-groupby-anomaly-report.ftl
index 97a06ee..e80449d 100644
--- a/thirdeye/thirdeye-pinot/src/main/resources/org/apache/pinot/thirdeye/detector/entity-groupby-anomaly-report.ftl
+++ b/thirdeye/thirdeye-pinot/src/main/resources/org/apache/pinot/thirdeye/detector/entity-groupby-anomaly-report.ftl
@@ -26,12 +26,12 @@
       <table border="0" cellpadding="0" cellspacing="0" style="border:1px solid #E9E9E9; border-radius: 2px; width: 100%;">
 
         <!-- List all the alerts -->
-        <#list entitySortedByScoreList as entity>
+        <#list entityToSortedAnomaliesMap as entityName, groupedAnomalies>
           <@utils.addBlock title="" align="left">
             <!-- Display Entity Name -->
             <p>
               <span style="color: #1D1D1D; font-size: 20px; font-weight: bold; display:inline-block; vertical-align: middle;">Entity:&nbsp;</span>
-              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${entity}</span>
+              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${entityName}</span>
             </p>
 
             <!-- List all the anomalies under this entity in a table -->
@@ -43,11 +43,12 @@
                 <th style="padding: 6px 12px; font-size: 12px; font-weight: bold; line-height: 20px;">Predicted</th>
               </tr>
 
-              <#list entityToAnomalyDetailsMap[entity] as anomaly>
+              <#list groupedAnomalies as anomaly>
                 <tr style="border-bottom: 1px solid #C7D1D8;">
                   <td style="padding: 6px 12px;white-space: nowrap;">
-                    <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="${dashboardHost}/app/#/anomalies?anomalyIds=${entityToAnomalyIdsMap[entity]}"
+                    <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="${dashboardHost}/app/#/anomalies?anomalyIds=${anomalyToChildIdsMap[anomaly.groupKey + anomaly.startDateTime]}"
                        target="_blank">${anomaly.groupKey}</a>
+                    <div style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px;">${anomaly.startDateTime} ${anomaly.timezone}</div>
                     <span style="color: rgba(0,0,0,0.6); font-size:12px; line-height:16px;">${anomaly.duration}</span>
                   </td>
                   <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">${anomaly.score}</td>
diff --git a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/tools/RunAdhocDatabaseQueriesTool.java b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/tools/RunAdhocDatabaseQueriesTool.java
index de90e00..d729dfc 100644
--- a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/tools/RunAdhocDatabaseQueriesTool.java
+++ b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/tools/RunAdhocDatabaseQueriesTool.java
@@ -598,10 +598,8 @@ public class RunAdhocDatabaseQueriesTool {
   private void removeReplayFlagFromAnomalies(long detectionConfigId) {
     List<MergedAnomalyResultDTO> anomalies = mergedResultDAO.findByDetectionConfigAndIdGreaterThan(detectionConfigId,0l);
     for (MergedAnomalyResultDTO anomaly : anomalies) {
-      if (!anomaly.isChild()) {
-        anomaly.setAnomalyResultSource(AnomalyResultSource.DEFAULT_ANOMALY_DETECTION);
-        mergedResultDAO.save(anomaly);
-      }
+      anomaly.setAnomalyResultSource(AnomalyResultSource.DEFAULT_ANOMALY_DETECTION);
+      mergedResultDAO.save(anomaly);
     }
   }
 
diff --git a/thirdeye/thirdeye-pinot/src/test/resources/test-entity-groupby-email-content-formatter.html b/thirdeye/thirdeye-pinot/src/test/resources/test-entity-groupby-email-content-formatter.html
index 0d3616f..a90b747 100644
--- a/thirdeye/thirdeye-pinot/src/test/resources/test-entity-groupby-email-content-formatter.html
+++ b/thirdeye/thirdeye-pinot/src/test/resources/test-entity-groupby-email-content-formatter.html
@@ -28,7 +28,7 @@
             <!-- Display Entity Name -->
             <p>
               <span style="color: #1D1D1D; font-size: 20px; font-weight: bold; display:inline-block; vertical-align: middle;">Entity:&nbsp;</span>
-              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">sub-entity-B</span>
+              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">sub-entity-A</span>
             </p>
             <!-- List all the anomalies under this entity in a table -->
             <table border="0" width="100%" align="center" style="width:100%; padding:0; margin:0; border-collapse: collapse;text-align:left;">
@@ -40,11 +40,12 @@
               </tr>
               <tr style="border-bottom: 1px solid #C7D1D8;">
                 <td style="padding: 6px 12px;white-space: nowrap;">
-                  <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="http://localhost:8080/dashboard/app/#/anomalies?anomalyIds=2"
-                     target="_blank">group-2</a>
+                  <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="http://localhost:8080/dashboard/app/#/anomalies?anomalyIds=1"
+                     target="_blank">group-1</a>
+                  <div style="color:rgba(0,0,0,0.9);font-size:14px;line-height:20px;">Nov07,10:00PDT</div>
                   <span style="color: rgba(0,0,0,0.6); font-size:12px; line-height:16px;">7 hours</span>
                 </td>
-                <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">20</td>
+                <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">10</td>
                 <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">0</td>
                 <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">
                   0
@@ -59,7 +60,7 @@
             <!-- Display Entity Name -->
             <p>
               <span style="color: #1D1D1D; font-size: 20px; font-weight: bold; display:inline-block; vertical-align: middle;">Entity:&nbsp;</span>
-              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">sub-entity-A</span>
+              <span style="color: #606060; font-size: 20px; text-decoration: none; display:inline-block; vertical-align: middle; width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">sub-entity-B</span>
             </p>
             <!-- List all the anomalies under this entity in a table -->
             <table border="0" width="100%" align="center" style="width:100%; padding:0; margin:0; border-collapse: collapse;text-align:left;">
@@ -71,11 +72,12 @@
               </tr>
               <tr style="border-bottom: 1px solid #C7D1D8;">
                 <td style="padding: 6px 12px;white-space: nowrap;">
-                  <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="http://localhost:8080/dashboard/app/#/anomalies?anomalyIds=1"
-                     target="_blank">group-1</a>
+                  <a style="font-weight: bold; text-decoration: none; font-size:14px; line-height:20px; color: #0073B1;" href="http://localhost:8080/dashboard/app/#/anomalies?anomalyIds=2"
+                     target="_blank">group-2</a>
+                  <div style="color:rgba(0,0,0,0.9);font-size:14px;line-height:20px;">Nov07,10:00PDT</div>
                   <span style="color: rgba(0,0,0,0.6); font-size:12px; line-height:16px;">7 hours</span>
                 </td>
-                <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">10</td>
+                <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">20</td>
                 <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">0</td>
                 <td style="color: rgba(0,0,0,0.9); font-size:14px; line-height:20px; text-align:center;">
                   0


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org