This is an automated email from the ASF dual-hosted git repository.

jihao 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 365ee85  [TE] Detection and alert config formatters (#4443)
365ee85 is described below

commit 365ee859bafe842b1ba09c88f4b20a0f0daafec8
Author: Jihao Zhang <jihzh...@linkedin.com>
AuthorDate: Thu Jul 18 17:30:44 2019 -0700

    [TE] Detection and alert config formatters (#4443)
    
    Adds the Detection config and the detection alert config formatter. These 
classes include the business logic for UI presentation.
    
    Extract nested metric urns from the nested properties. This enables the 
frontend to show the metrics for entity alerts.
    Show different default window size for different detection granularities.
---
 .../app/pods/manage/explore/route.js               |   4 +-
 .../thirdeye/detection/DetectionResource.java      |  15 +-
 .../pinot/thirdeye/formatter/DTOFormatter.java     |  38 +++++
 .../formatter/DetectionAlertConfigFormatter.java   |  46 +++++
 .../formatter/DetectionConfigFormatter.java        | 189 +++++++++++++++++++++
 .../formatter/DetectionConfigFormatterTest.java    |  82 +++++++++
 6 files changed, 367 insertions(+), 7 deletions(-)

diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js 
b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
index 5dceb3e..22f4f1f2 100644
--- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
@@ -64,8 +64,8 @@ export default Route.extend(AuthenticatedRouteMixin, {
             alertId: alertId,
             detectionInfo,
             rawDetectionYaml: detection_json.yaml,
-            metricUrn: detection_json.properties.nested[0].nestedMetricUrns[0],
-            metricUrnList: 
detection_json.properties.nested[0].nestedMetricUrns,
+            metricUrn: detection_json.metricUrns[0],
+            metricUrnList: detection_json.metricUrns,
             granularity
           });
 
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
index 8d23058..65f9e76 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
@@ -74,6 +74,8 @@ import 
org.apache.pinot.thirdeye.datasource.loader.DefaultTimeSeriesLoader;
 import org.apache.pinot.thirdeye.datasource.loader.TimeSeriesLoader;
 import org.apache.pinot.thirdeye.detection.finetune.GridSearchTuningAlgorithm;
 import org.apache.pinot.thirdeye.detection.finetune.TuningAlgorithm;
+import org.apache.pinot.thirdeye.formatter.DetectionAlertConfigFormatter;
+import org.apache.pinot.thirdeye.formatter.DetectionConfigFormatter;
 import org.apache.pinot.thirdeye.detection.health.DetectionHealth;
 import org.apache.pinot.thirdeye.detection.spi.model.AnomalySlice;
 import org.apache.pinot.thirdeye.detector.function.BaseAnomalyFunction;
@@ -108,8 +110,9 @@ public class DetectionResource {
   private final DetectionConfigManager configDAO;
   private final EvaluationManager evaluationDAO;
   private final TaskManager taskDAO;
-
   private final DetectionAlertConfigManager detectionAlertConfigDAO;
+  private final DetectionConfigFormatter detectionConfigFormatter;
+  private final DetectionAlertConfigFormatter subscriptionConfigFormatter;
 
   public DetectionResource() {
     this.metricDAO = DAORegistry.getInstance().getMetricConfigDAO();
@@ -131,6 +134,8 @@ public class DetectionResource {
     this.loader = new DetectionPipelineLoader();
 
     this.provider = new DefaultDataProvider(metricDAO, datasetDAO, eventDAO, 
anomalyDAO, evaluationDAO, timeseriesLoader, aggregationLoader, loader);
+    this.detectionConfigFormatter = new DetectionConfigFormatter(metricDAO, 
datasetDAO);
+    this.subscriptionConfigFormatter = new DetectionAlertConfigFormatter();
   }
 
   @Path("/{id}")
@@ -138,7 +143,7 @@ public class DetectionResource {
   @ApiOperation("get a detection config with yaml")
   public Response getDetectionConfig(@ApiParam("the detection config id") 
@PathParam("id") long id){
     DetectionConfigDTO config = this.configDAO.findById(id);
-    return Response.ok(config).build();
+    return Response.ok(this.detectionConfigFormatter.format(config)).build();
   }
 
   @Path("/notification/{id}")
@@ -146,7 +151,7 @@ public class DetectionResource {
   @ApiOperation("get a detection alert config with yaml")
   public Response getDetectionAlertConfig(@ApiParam("the detection alert 
config id") @PathParam("id") long id){
     DetectionAlertConfigDTO config = this.detectionAlertConfigDAO.findById(id);
-    return Response.ok(config).build();
+    return 
Response.ok(this.subscriptionConfigFormatter.format(config)).build();
   }
 
   @Path("/dataset")
@@ -168,7 +173,7 @@ public class DetectionResource {
         subscriptionGroupAlertDTOs.add(alertConfigDTO);
       }
     }
-    return Response.ok(new ArrayList<>(subscriptionGroupAlertDTOs)).build();
+    return 
Response.ok(subscriptionGroupAlertDTOs.stream().map(this.subscriptionConfigFormatter::format).collect(Collectors.toList())).build();
   }
 
 
@@ -177,7 +182,7 @@ public class DetectionResource {
   @ApiOperation("get all detection alert configs")
   public Response getAllSubscriptionGroups(){
     List<DetectionAlertConfigDTO> detectionAlertConfigDTOs = 
this.detectionAlertConfigDAO.findAll();
-    return Response.ok(detectionAlertConfigDTOs).build();
+    return 
Response.ok(detectionAlertConfigDTOs.stream().map(this.subscriptionConfigFormatter::format).collect(Collectors.toList())).build();
   }
 
   @Path("{id}/anomalies")
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DTOFormatter.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DTOFormatter.java
new file mode 100644
index 0000000..ac71cff
--- /dev/null
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DTOFormatter.java
@@ -0,0 +1,38 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.pinot.thirdeye.formatter;
+
+import java.util.Map;
+import org.apache.pinot.thirdeye.datalayer.dto.AbstractDTO;
+
+
+/**
+ * Class for building UI formatters for DTOs. Takes in a DTO and returns
+ * a map that contains human-readable data for display on the UI.
+ */
+public interface DTOFormatter<T extends AbstractDTO> {
+  /**
+   * Format a DTO object and returns a human-readable map
+   * @param dto the DTO object to be formatted
+   * @return the formatted map
+   */
+  Map<String, Object> format(T dto);
+}
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionAlertConfigFormatter.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionAlertConfigFormatter.java
new file mode 100644
index 0000000..ea1776d
--- /dev/null
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionAlertConfigFormatter.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.pinot.thirdeye.formatter;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.pinot.thirdeye.datalayer.dto.DetectionAlertConfigDTO;
+
+
+/**
+ * The detection alert config formatter
+ */
+public class DetectionAlertConfigFormatter implements 
DTOFormatter<DetectionAlertConfigDTO> {
+  private static final String ATTR_NAME = "name";
+  private static final String ATTR_YAML = "yaml";
+  private static final String ATTR_ACTIVE = "active";
+  private static final String ATTR_ID = "id";
+
+  @Override
+  public Map<String, Object> format(DetectionAlertConfigDTO config) {
+    Map<String, Object> output = new HashMap<>();
+    output.put(ATTR_NAME, config.getName());
+    output.put(ATTR_YAML, config.getYaml());
+    output.put(ATTR_ID, config.getId());
+    output.put(ATTR_ACTIVE, config.isActive());
+    return output;
+  }
+}
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatter.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatter.java
new file mode 100644
index 0000000..fb5f7e8
--- /dev/null
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatter.java
@@ -0,0 +1,189 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.pinot.thirdeye.formatter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.pinot.thirdeye.common.time.TimeGranularity;
+import org.apache.pinot.thirdeye.datalayer.bao.DatasetConfigManager;
+import org.apache.pinot.thirdeye.datalayer.bao.MetricConfigManager;
+import org.apache.pinot.thirdeye.datalayer.dto.DetectionConfigDTO;
+import org.apache.pinot.thirdeye.detection.ConfigUtils;
+import org.apache.pinot.thirdeye.rootcause.impl.MetricEntity;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The detection config formatter
+ */
+public class DetectionConfigFormatter implements 
DTOFormatter<DetectionConfigDTO> {
+  static final String ATTR_ID = "id";
+  static final String ATTR_CREATED_BY = "createdBy";
+  static final String ATTR_UPDATED_BY = "updatedBy";
+  static final String ATTR_NAME = "name";
+  static final String ATTR_DESCRIPTION = "description";
+  static final String ATTR_LAST_TIMESTAMP = "lastTimestamp";
+  static final String ATTR_YAML = "yaml";
+  static final String ATTR_METRIC_URNS = "metricUrns";
+  static final String ATTR_IS_ACTIVE = "active";
+  static final String ATTR_ALERT_DETAILS_WINDOW_SIZE = 
"alertDetailsDefaultWindowSize";
+
+  private static final String PROP_NESTED_METRIC_URNS_KEY = "nestedMetricUrns";
+  private static final String PROP_NESTED_PROPERTIES_KEY = "nested";
+  private static final String PROP_MONITORING_GRANULARITY = 
"monitoringGranularity";
+  private static final String PROP_BUCKET_PERIOD = "bucketPeriod";
+  private static final String PROP_VARIABLES_BUCKET_PERIOD = 
"variables.bucketPeriod";
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(DetectionConfigFormatter.class);
+
+  private static final long DEFAULT_PRESENTING_WINDOW_SIZE_MINUTELY = 
TimeUnit.HOURS.toMillis(48);
+  private static final long DEFAULT_PRESENTING_WINDOW_SIZE_DAILY = 
TimeUnit.DAYS.toMillis(30);
+  private static final String ALGORITHM_TYPE = "ALGORITHM";
+  private static final String MIGRATED_ALGORITHM_TYPE = "MIGRATED_ALGORITHM";
+  private static final String CONFIGURATION = "configuration";
+
+  private final MetricConfigManager metricDAO;
+  private final DatasetConfigManager datasetDAO;
+
+  public DetectionConfigFormatter(MetricConfigManager metricDAO, 
DatasetConfigManager datasetDAO) {
+    this.datasetDAO = datasetDAO;
+    this.metricDAO = metricDAO;
+  }
+
+  @Override
+  public Map<String, Object> format(DetectionConfigDTO config) {
+    Map<String, Object> output = new HashMap<>();
+    output.put(ATTR_ID, config.getId());
+    output.put(ATTR_IS_ACTIVE, config.isActive());
+    output.put(ATTR_CREATED_BY, config.getCreatedBy());
+    output.put(ATTR_UPDATED_BY, config.getUpdatedBy());
+    output.put(ATTR_NAME, config.getName());
+    output.put(ATTR_DESCRIPTION, config.getDescription());
+    output.put(ATTR_YAML, config.getYaml());
+    output.put(ATTR_LAST_TIMESTAMP, config.getLastTimestamp());
+    List<String> metricUrns = 
extractMetricUrnsFromProperties(config.getProperties());
+    // the metric urns monitored by this detection config
+    output.put(ATTR_METRIC_URNS, metricUrns);
+    // the default window size of the alert details page
+    output.put(ATTR_ALERT_DETAILS_WINDOW_SIZE, 
getAlertDetailsDefaultWindowSize(config, metricUrns));
+    return output;
+  }
+
+  /**
+   * Extract the list of metric urns in the detection config properties
+   * @param properties the detection config properties
+   * @return the list of metric urns
+   */
+  private List<String> extractMetricUrnsFromProperties(Map<String, Object> 
properties) {
+    List<String> metricUrns = new ArrayList<>();
+    if (properties.containsKey(PROP_NESTED_METRIC_URNS_KEY)) {
+      
metricUrns.addAll(ConfigUtils.getList(properties.get(PROP_NESTED_METRIC_URNS_KEY)));
+    }
+    List<Map<String, Object>> nestedProperties = 
ConfigUtils.getList(properties.get(PROP_NESTED_PROPERTIES_KEY));
+    // extract the metric urns recursively from the nested properties
+    for (Map<String, Object> nestedProperty : nestedProperties) {
+      metricUrns.addAll(extractMetricUrnsFromProperties(nestedProperty));
+    }
+    return metricUrns;
+  }
+
+  /**
+   * Generate the default window size for presenting in ThirdEye alert details 
page.
+   * @param config the detection config
+   * @param metricUrns the list of metric urns
+   * @return the window size in milliseconds
+   */
+  private long getAlertDetailsDefaultWindowSize(DetectionConfigDTO config, 
List<String> metricUrns) {
+    try {
+      // first try to get the granularities in config properties
+      List<TimeGranularity> granularities = getMonitoringGranularities(config);
+      // if monitoring granularities is not set, use the metric granularity to 
decide the default window
+      if (granularities.isEmpty()) {
+        granularities = 
metricUrns.stream().map(this::getGranularityForMetricUrn).collect(Collectors.toList());
+      }
+      List<Long> windowSizes =
+          
granularities.stream().map(this::getDefaultWindowSizeForGranularity).collect(Collectors.toList());
+      // show the minimal of all window sizes for UI responsiveness
+      return Collections.min(windowSizes);
+    } catch (Exception e) {
+      LOG.warn("Exception thrown when getting granularities for detection 
config {}, use default presenting window size", config.getId(), e);
+      return DEFAULT_PRESENTING_WINDOW_SIZE_DAILY;
+    }
+  }
+
+  private List<TimeGranularity> getMonitoringGranularities(DetectionConfigDTO 
config) {
+    List<TimeGranularity> monitoringGranularities = new ArrayList<>();
+    for (Map.Entry<String, Object> entry : 
config.getComponentSpecs().entrySet()) {
+      Map<String, Object> specs = (Map<String, Object>) entry.getValue();
+      if (entry.getKey().equals(ALGORITHM_TYPE)) {
+        extractTimeGranularitiesFromAlgorithmSpecs(specs, 
PROP_BUCKET_PERIOD).ifPresent(monitoringGranularities::add);
+      } else if (entry.getKey().equals(MIGRATED_ALGORITHM_TYPE)) {
+        extractTimeGranularitiesFromAlgorithmSpecs(specs, 
PROP_VARIABLES_BUCKET_PERIOD).ifPresent(monitoringGranularities::add);
+      } else if (specs.containsKey(PROP_MONITORING_GRANULARITY)) {
+        
monitoringGranularities.add(TimeGranularity.fromString(MapUtils.getString(specs,
 (PROP_MONITORING_GRANULARITY))));
+      }
+    }
+    return monitoringGranularities;
+  }
+
+  /**
+   * extract the detection granularity for ALGORITHM detector types
+   * @param specs the specs for the ALGORITHM detectors
+   * @return the granularity
+   */
+  private Optional<TimeGranularity> 
extractTimeGranularitiesFromAlgorithmSpecs(Map<String, Object> specs, String 
bucketPeriodFieldName) {
+    String bucketPeriod = String.valueOf(MapUtils.getMap(specs, 
CONFIGURATION).get(bucketPeriodFieldName));
+    Period p = Period.parse(bucketPeriod);
+    PeriodType periodType = p.getPeriodType();
+    if (PeriodType.days().equals(periodType)) {
+      return  Optional.of(new TimeGranularity(p.getDays(), TimeUnit.DAYS));
+    } else if (PeriodType.hours().equals(periodType)) {
+      return Optional.of(new TimeGranularity(p.getHours(), TimeUnit.HOURS));
+    } else if (PeriodType.minutes().equals(periodType)) {
+      return Optional.of(new TimeGranularity(p.getMinutes(), 
TimeUnit.MINUTES));
+    }
+    return Optional.empty();
+  }
+
+  private TimeGranularity getGranularityForMetricUrn(String metricUrn) {
+    MetricEntity me = MetricEntity.fromURN(metricUrn);
+    return 
this.datasetDAO.findByDataset(this.metricDAO.findById(me.getId()).getDataset()).bucketTimeGranularity();
+  }
+
+  private long getDefaultWindowSizeForGranularity(TimeGranularity granularity) 
{
+    TimeUnit unit = granularity.getUnit();
+    if (unit == TimeUnit.MINUTES || unit == TimeUnit.HOURS) {
+      return DEFAULT_PRESENTING_WINDOW_SIZE_MINUTELY;
+    } else {
+      return DEFAULT_PRESENTING_WINDOW_SIZE_DAILY;
+    }
+  }
+}
diff --git 
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatterTest.java
 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatterTest.java
new file mode 100644
index 0000000..25b6d7d
--- /dev/null
+++ 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/formatter/DetectionConfigFormatterTest.java
@@ -0,0 +1,82 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.pinot.thirdeye.formatter;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.apache.pinot.thirdeye.datalayer.bao.DAOTestBase;
+import org.apache.pinot.thirdeye.datalayer.dto.DetectionConfigDTO;
+import org.apache.pinot.thirdeye.datasource.DAORegistry;
+import org.apache.pinot.thirdeye.detection.ConfigUtils;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.apache.pinot.thirdeye.formatter.DetectionConfigFormatter.*;
+
+
+public class DetectionConfigFormatterTest {
+  private DAOTestBase testDAOProvider;
+  private DAORegistry daoRegistry;
+
+  @BeforeMethod
+  public void setUp() {
+    this.testDAOProvider = DAOTestBase.getInstance();
+    this.daoRegistry = DAORegistry.getInstance();
+  }
+
+  @Test
+  public void testDetectionConfigFormatter() {
+    DetectionConfigDTO configDTO = new DetectionConfigDTO();
+    configDTO.setName("test");
+    configDTO.setActive(true);
+    configDTO.setYaml("test yaml");
+    configDTO.setDescription("description");
+    configDTO.setCreatedBy("test");
+    configDTO.setUpdatedBy("test");
+    configDTO.setId(1L);
+    configDTO.setProperties(ImmutableMap.of("nestedMetricUrns", 
Collections.singleton("thirdeye::metric::1"), "nested",
+        Collections.singletonList(ImmutableMap.of("nestedMetricUrns", 
Collections.singleton("thirdeye::metric::2")))));
+    DetectionConfigFormatter formatter =
+        new DetectionConfigFormatter(this.daoRegistry.getMetricConfigDAO(), 
this.daoRegistry.getDatasetConfigDAO());
+    Map<String, Object> result = formatter.format(configDTO);
+    Assert.assertEquals(result.get(ATTR_ID), configDTO.getId());
+    Assert.assertEquals(result.get(ATTR_IS_ACTIVE), configDTO.isActive());
+    Assert.assertEquals(result.get(ATTR_YAML), configDTO.getYaml());
+    Assert.assertEquals(result.get(ATTR_LAST_TIMESTAMP), 
configDTO.getLastTimestamp());
+    Assert.assertEquals(result.get(ATTR_NAME), configDTO.getName());
+    Assert.assertEquals(result.get(ATTR_DESCRIPTION), 
configDTO.getDescription());
+    Assert.assertEquals(result.get(ATTR_CREATED_BY), configDTO.getCreatedBy());
+    Assert.assertEquals(result.get(ATTR_UPDATED_BY), configDTO.getUpdatedBy());
+    Assert.assertTrue(ConfigUtils.getList(result.get(ATTR_METRIC_URNS))
+        .containsAll(Arrays.asList("thirdeye::metric::1", 
"thirdeye::metric::2")));
+    Assert.assertEquals(result.get(ATTR_ALERT_DETAILS_WINDOW_SIZE), 
TimeUnit.DAYS.toMillis(30));
+  }
+
+  @AfterMethod(alwaysRun = true)
+  void afterClass() {
+    testDAOProvider.cleanup();
+  }
+}
\ No newline at end of file


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

Reply via email to