package com.linkedin.thirdeye.dashboard.resources; import com.google.common.base.Strings; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import javax.validation.constraints.NotNull; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.lang.NullArgumentException; import org.codehaus.jackson.node.ObjectNode; import com.linkedin.thirdeye.client.DAORegistry; import com.linkedin.thirdeye.dashboard.Utils; import com.linkedin.thirdeye.datalayer.bao.DatasetConfigManager; import com.linkedin.thirdeye.datalayer.dto.DatasetConfigDTO; import com.linkedin.thirdeye.util.JsonResponseUtil; @Path(value = "/thirdeye-admin/dataset-config") @Produces(MediaType.APPLICATION_JSON) public class DatasetConfigResource { private static final DAORegistry DAO_REGISTRY = DAORegistry.getInstance(); private DatasetConfigManager datasetConfigDao; public DatasetConfigResource() { this.datasetConfigDao = DAO_REGISTRY.getDatasetConfigDAO(); } @GET @Path("/create") public String createDatasetConfig(@QueryParam("dataset") String dataset, @QueryParam("dimensions") String dimensions, @QueryParam("dimensionsHaveNoPreAggregation") String dimensionsHaveNoPreAggregation, @QueryParam("active") boolean active, @QueryParam("additive") boolean additive, @QueryParam("metricAsDimension") boolean metricAsDimension, @QueryParam("metricValuesColumn") String metricValuesColumn, @QueryParam("metricNamesColumn") String metricNamesColumn, @QueryParam("nonAdditiveBucketSize") Integer nonAdditiveBucketSize, @QueryParam("nonAdditiveBucketUnit") String nonAdditiveBucketUnit, @QueryParam("preAggregatedKeyword") String preAggregatedKeyword, @QueryParam("timeColumn") String timeColumn, @QueryParam("timeDuration") Integer timeDuration, @QueryParam("timeFormat") String timeFormat, @QueryParam("timezone") TimeUnit timeUnit, @QueryParam("timezone") String timezone) { try { DatasetConfigDTO datasetConfigDTO = new DatasetConfigDTO(); datasetConfigDTO.setDataset(dataset); datasetConfigDTO.setDimensions(toList(dimensions)); if (!Strings.isNullOrEmpty(dimensionsHaveNoPreAggregation)) { datasetConfigDTO.setDimensionsHaveNoPreAggregation(toList(dimensionsHaveNoPreAggregation)); } datasetConfigDTO.setActive(active); datasetConfigDTO.setAdditive(additive); datasetConfigDTO.setMetricAsDimension(metricAsDimension); datasetConfigDTO.setMetricNamesColumn(metricNamesColumn); datasetConfigDTO.setMetricValuesColumn(metricValuesColumn); datasetConfigDTO.setNonAdditiveBucketSize(nonAdditiveBucketSize); datasetConfigDTO.setNonAdditiveBucketUnit(TimeUnit.valueOf(nonAdditiveBucketUnit)); datasetConfigDTO.setPreAggregatedKeyword(preAggregatedKeyword); datasetConfigDTO.setTimeColumn(timeColumn); datasetConfigDTO.setTimeDuration(timeDuration); datasetConfigDTO.setTimeFormat(timeFormat); datasetConfigDTO.setTimeUnit(timeUnit); datasetConfigDTO.setTimezone(timezone); Long id = datasetConfigDao.save(datasetConfigDTO); datasetConfigDTO.setId(id); return JsonResponseUtil.buildResponseJSON(datasetConfigDTO).toString(); } catch (Exception e) { return JsonResponseUtil.buildErrorResponseJSON("Failed to create dataset:" + dataset).toString(); } } private List<String> toList(String string) { String[] splitArray = string.split(","); List<String> list = new ArrayList<>(); for (String split : splitArray) { list.add(split.trim()); } return list; } @GET @Path("/update") public String updateDatasetConfig(@NotNull @QueryParam("id") long datasetConfigId, @QueryParam("dataset") String dataset, @QueryParam("dimensions") String dimensions, @QueryParam("dimensionsHaveNoPreAggregation") String dimensionsHaveNoPreAggregation, @QueryParam("active") boolean active, @QueryParam("additive") boolean additive, @QueryParam("metricAsDimension") boolean metricAsDimension, @QueryParam("metricValuesColumn") String metricValuesColumn, @QueryParam("metricNamesColumn") String metricNamesColumn, @QueryParam("nonAdditiveBucketSize") Integer nonAdditiveBucketSize, @QueryParam("nonAdditiveBucketUnit") String nonAdditiveBucketUnit, @QueryParam("preAggregatedKeyword") String preAggregatedKeyword, @QueryParam("timeColumn") String timeColumn, @QueryParam("timeDuration") Integer timeDuration, @QueryParam("timeFormat") String timeFormat, @QueryParam("timezone") TimeUnit timeUnit, @QueryParam("timezone") String timezone) { try { DatasetConfigDTO datasetConfigDTO = datasetConfigDao.findById(datasetConfigId); datasetConfigDTO.setDataset(dataset); datasetConfigDTO.setDimensions(toList(dimensions)); datasetConfigDTO.setDimensionsHaveNoPreAggregation(toList(dimensionsHaveNoPreAggregation)); datasetConfigDTO.setActive(active); datasetConfigDTO.setAdditive(additive); datasetConfigDTO.setMetricAsDimension(metricAsDimension); datasetConfigDTO.setMetricValuesColumn(metricValuesColumn); datasetConfigDTO.setNonAdditiveBucketSize(nonAdditiveBucketSize); datasetConfigDTO.setNonAdditiveBucketUnit(TimeUnit.valueOf(nonAdditiveBucketUnit)); datasetConfigDTO.setPreAggregatedKeyword(preAggregatedKeyword); datasetConfigDTO.setTimeColumn(timeColumn); datasetConfigDTO.setTimeDuration(timeDuration); datasetConfigDTO.setTimeFormat(timeFormat); datasetConfigDTO.setTimeUnit(timeUnit); datasetConfigDTO.setTimezone(timezone); int numRowsUpdated = datasetConfigDao.update(datasetConfigDTO); if (numRowsUpdated == 1) { return JsonResponseUtil.buildResponseJSON(datasetConfigDTO).toString(); } else { return JsonResponseUtil.buildErrorResponseJSON("Failed to update dataset config id:" + datasetConfigId).toString(); } } catch (Exception e) { return JsonResponseUtil.buildErrorResponseJSON("Failed to update dataset config id:" + datasetConfigId + ". Exception:" + e.getMessage()).toString(); } } @POST @Path("/requiresCompletenessCheck/enable/{dataset}") public Response enableRequiresCompletenessCheck(@PathParam("dataset") String dataset) throws Exception { toggleRequiresCompletenessCheck(dataset, true); return Response.ok().build(); } @POST @Path("/requiresCompletenessCheck/disable/{dataset}") public Response disableRequiresCompletenessCheck(@PathParam("dataset") String dataset) throws Exception { toggleRequiresCompletenessCheck(dataset, false); return Response.ok().build(); } private void toggleRequiresCompletenessCheck(String dataset, boolean state) { DatasetConfigDTO datasetConfig = datasetConfigDao.findByDataset(dataset); if(datasetConfig == null) { throw new NullArgumentException("dataset config spec not found"); } datasetConfig.setRequiresCompletenessCheck(state); datasetConfigDao.update(datasetConfig); } @GET @Path("/delete") public String deleteDatasetConfig(@NotNull @QueryParam("id") Long datasetConfigId) { datasetConfigDao.deleteById(datasetConfigId); return JsonResponseUtil.buildSuccessResponseJSON("Successully deleted dataset id: " + datasetConfigId).toString(); } @GET @Path("/list") @Produces(MediaType.APPLICATION_JSON) public String viewDatsetConfig(@DefaultValue("0") @QueryParam("jtStartIndex") int jtStartIndex, @DefaultValue("100") @QueryParam("jtPageSize") int jtPageSize) { List<DatasetConfigDTO> datasetConfigDTOs = datasetConfigDao.findAll(); List<DatasetConfigDTO> subList = Utils.sublist(datasetConfigDTOs, jtStartIndex, jtPageSize); ObjectNode rootNode = JsonResponseUtil.buildResponseJSON(subList); return rootNode.toString(); } }