mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-27 16:55:06 +00:00
Add new Template and Graph building logic for Insights reporting (#15184)
This commit is contained in:
parent
9e867fb279
commit
0b7a4f8839
@ -11,21 +11,23 @@ import static org.openmetadata.service.Entity.TEAM;
|
||||
import static org.openmetadata.service.apps.scheduler.AppScheduler.APP_INFO_KEY;
|
||||
import static org.openmetadata.service.apps.scheduler.AppScheduler.SEARCH_CLIENT_KEY;
|
||||
import static org.openmetadata.service.util.SubscriptionUtil.getAdminsData;
|
||||
import static org.openmetadata.service.util.Utilities.getMonthAndDateFromEpoch;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openmetadata.common.utils.CommonUtil;
|
||||
import org.openmetadata.schema.dataInsight.DataInsightChartResult;
|
||||
import org.openmetadata.schema.dataInsight.kpi.Kpi;
|
||||
@ -35,7 +37,6 @@ import org.openmetadata.schema.dataInsight.type.PercentageOfEntitiesWithOwnerByT
|
||||
import org.openmetadata.schema.dataInsight.type.TotalEntitiesByTier;
|
||||
import org.openmetadata.schema.dataInsight.type.TotalEntitiesByType;
|
||||
import org.openmetadata.schema.entity.app.App;
|
||||
import org.openmetadata.schema.entity.app.AppSchedule;
|
||||
import org.openmetadata.schema.entity.applications.configuration.internal.DataInsightsReportAppConfig;
|
||||
import org.openmetadata.schema.entity.teams.Team;
|
||||
import org.openmetadata.schema.entity.teams.User;
|
||||
@ -54,15 +55,13 @@ import org.openmetadata.service.search.SearchRepository;
|
||||
import org.openmetadata.service.util.EmailUtil;
|
||||
import org.openmetadata.service.util.JsonUtils;
|
||||
import org.openmetadata.service.util.ResultList;
|
||||
import org.openmetadata.service.util.Utilities;
|
||||
import org.openmetadata.service.workflows.searchIndex.PaginatedEntitiesSource;
|
||||
import org.quartz.CronScheduleBuilder;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.Trigger;
|
||||
|
||||
@Slf4j
|
||||
@SuppressWarnings("unused")
|
||||
public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
private static final String MISSING_DATA =
|
||||
"Data Insight Report Data Unavailable or too short of a span for Reporting.";
|
||||
private static final String KPI_NOT_SET = "No Kpi Set";
|
||||
|
||||
@Override
|
||||
@ -73,9 +72,8 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
App app = (App) jobExecutionContext.getJobDetail().getJobDataMap().get(APP_INFO_KEY);
|
||||
// Calculate time diff
|
||||
long currentTime = Instant.now().toEpochMilli();
|
||||
AppSchedule scheduleConfiguration = app.getAppSchedule();
|
||||
long scheduleTime = currentTime - 604800000L;
|
||||
int numberOfDaysChange = getNumberOfDays(scheduleConfiguration);
|
||||
int numberOfDaysChange = 7;
|
||||
try {
|
||||
DataInsightsReportAppConfig insightAlertConfig =
|
||||
JsonUtils.convertValue(app.getAppConfiguration(), DataInsightsReportAppConfig.class);
|
||||
@ -86,7 +84,7 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
}
|
||||
|
||||
// Send to Teams
|
||||
if (Boolean.TRUE.equals(insightAlertConfig.getSendToTeams())) {
|
||||
if (Boolean.FALSE.equals(insightAlertConfig.getSendToTeams())) {
|
||||
sendReportsToTeams(
|
||||
searchRepository.getSearchClient(), scheduleTime, currentTime, numberOfDaysChange);
|
||||
}
|
||||
@ -130,6 +128,8 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
searchClient, team.getName(), scheduleTime, currentTime, numberOfDaysChange);
|
||||
EmailUtil.sendDataInsightEmailNotificationToUser(
|
||||
emails,
|
||||
getMonthAndDateFromEpoch(scheduleTime),
|
||||
getMonthAndDateFromEpoch(currentTime),
|
||||
totalAssetTemplate,
|
||||
descriptionTemplate,
|
||||
ownershipTemplate,
|
||||
@ -165,6 +165,8 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
createTierTemplate(searchClient, null, scheduleTime, currentTime, numberOfDaysChange);
|
||||
EmailUtil.sendDataInsightEmailNotificationToUser(
|
||||
emailList,
|
||||
getMonthAndDateFromEpoch(scheduleTime),
|
||||
getMonthAndDateFromEpoch(currentTime),
|
||||
totalAssetTemplate,
|
||||
descriptionTemplate,
|
||||
ownershipTemplate,
|
||||
@ -190,6 +192,9 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
private DataInsightTotalAssetTemplate createTotalAssetTemplate(
|
||||
SearchClient searchClient, String team, Long scheduleTime, Long currentTime, int numberOfDays)
|
||||
throws ParseException, IOException {
|
||||
// Create A Date Map
|
||||
Map<String, Integer> dateMap = new LinkedHashMap<>();
|
||||
Utilities.getLastSevenDays(currentTime).forEach(day -> dateMap.put(day, 0));
|
||||
// Get total Assets Data
|
||||
TreeMap<Long, List<Object>> dateWithDataMap =
|
||||
searchClient.getSortedDate(
|
||||
@ -199,7 +204,6 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
TOTAL_ENTITIES_BY_TYPE,
|
||||
ENTITY_REPORT_DATA_INDEX.value());
|
||||
if (dateWithDataMap.firstEntry() != null && dateWithDataMap.lastEntry() != null) {
|
||||
|
||||
List<TotalEntitiesByType> first =
|
||||
JsonUtils.convertValue(dateWithDataMap.firstEntry().getValue(), new TypeReference<>() {});
|
||||
List<TotalEntitiesByType> last =
|
||||
@ -207,16 +211,29 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
Double previousCount = getCountOfEntitiesFromList(first);
|
||||
Double currentCount = getCountOfEntitiesFromList(last);
|
||||
|
||||
dateWithDataMap.forEach(
|
||||
(key, value) -> {
|
||||
List<TotalEntitiesByType> list =
|
||||
JsonUtils.convertValue(value, new TypeReference<>() {});
|
||||
Double count = getCountOfEntitiesFromList(list);
|
||||
dateMap.put(Utilities.getDateFromEpoch(key), count.intValue());
|
||||
});
|
||||
|
||||
processDateMapToNormalize(dateMap);
|
||||
|
||||
if (previousCount == 0D) {
|
||||
// it should be undefined
|
||||
return new DataInsightTotalAssetTemplate(currentCount, 0D, numberOfDays);
|
||||
return new DataInsightTotalAssetTemplate(currentCount, 0D, numberOfDays, dateMap);
|
||||
} else {
|
||||
return new DataInsightTotalAssetTemplate(
|
||||
currentCount, ((currentCount - previousCount) / previousCount) * 100, numberOfDays);
|
||||
currentCount,
|
||||
((currentCount - previousCount) / previousCount) * 100,
|
||||
numberOfDays,
|
||||
dateMap);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException(MISSING_DATA);
|
||||
return new DataInsightTotalAssetTemplate(0D, 0D, numberOfDays, dateMap);
|
||||
}
|
||||
|
||||
private DataInsightDescriptionAndOwnerTemplate createDescriptionTemplate(
|
||||
@ -226,6 +243,9 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
Long currentTime,
|
||||
int numberOfDaysChange)
|
||||
throws ParseException, IOException {
|
||||
// Create A Date Map
|
||||
Map<String, Integer> dateMap = new LinkedHashMap<>();
|
||||
Utilities.getLastSevenDays(currentTime).forEach(day -> dateMap.put(day, 0));
|
||||
// Get total Assets Data
|
||||
// This assumes that on a particular date the correct count per entities are given
|
||||
TreeMap<Long, List<Object>> dateWithDataMap =
|
||||
@ -246,6 +266,16 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
double currentCompletedDescription = getCompletedDescriptionCount(last);
|
||||
double currentTotalCount = getTotalEntityFromDescriptionList(last);
|
||||
|
||||
dateWithDataMap.forEach(
|
||||
(key, value) -> {
|
||||
List<PercentageOfEntitiesWithDescriptionByType> list =
|
||||
JsonUtils.convertValue(value, new TypeReference<>() {});
|
||||
Double count = getCompletedDescriptionCount(list);
|
||||
dateMap.put(Utilities.getDateFromEpoch(key), count.intValue());
|
||||
});
|
||||
|
||||
processDateMapToNormalize(dateMap);
|
||||
|
||||
// Previous Percent
|
||||
double previousPercentCompleted = 0D;
|
||||
if (previousTotalCount != 0) {
|
||||
@ -262,10 +292,17 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
PERCENTAGE_OF_ENTITIES_WITH_DESCRIPTION_BY_TYPE,
|
||||
currentPercentCompleted,
|
||||
currentPercentCompleted - previousPercentCompleted,
|
||||
numberOfDaysChange);
|
||||
numberOfDaysChange,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
throw new IOException(MISSING_DATA);
|
||||
return getTemplate(
|
||||
DataInsightDescriptionAndOwnerTemplate.MetricType.DESCRIPTION,
|
||||
PERCENTAGE_OF_ENTITIES_WITH_DESCRIPTION_BY_TYPE,
|
||||
0D,
|
||||
0D,
|
||||
numberOfDaysChange,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
private DataInsightDescriptionAndOwnerTemplate createOwnershipTemplate(
|
||||
@ -275,6 +312,9 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
Long currentTime,
|
||||
int numberOfDaysChange)
|
||||
throws ParseException, IOException {
|
||||
// Create A Date Map
|
||||
Map<String, Integer> dateMap = new LinkedHashMap<>();
|
||||
Utilities.getLastSevenDays(currentTime).forEach(day -> dateMap.put(day, 0));
|
||||
// Get total Assets Data
|
||||
// This assumes that on a particular date the correct count per entities are given
|
||||
TreeMap<Long, List<Object>> dateWithDataMap =
|
||||
@ -305,16 +345,31 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
if (currentTotalCount != 0) {
|
||||
currentPercentCompleted = (currentHasOwner / currentTotalCount) * 100;
|
||||
}
|
||||
dateWithDataMap.forEach(
|
||||
(key, value) -> {
|
||||
List<PercentageOfEntitiesWithOwnerByType> list =
|
||||
JsonUtils.convertValue(value, new TypeReference<>() {});
|
||||
Double count = getCompletedOwnershipCount(list);
|
||||
dateMap.put(Utilities.getDateFromEpoch(key), count.intValue());
|
||||
});
|
||||
|
||||
processDateMapToNormalize(dateMap);
|
||||
|
||||
return getTemplate(
|
||||
DataInsightDescriptionAndOwnerTemplate.MetricType.OWNER,
|
||||
PERCENTAGE_OF_ENTITIES_WITH_OWNER_BY_TYPE,
|
||||
currentPercentCompleted,
|
||||
currentPercentCompleted - previousPercentCompleted,
|
||||
numberOfDaysChange);
|
||||
numberOfDaysChange,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
throw new IOException(MISSING_DATA);
|
||||
return getTemplate(
|
||||
DataInsightDescriptionAndOwnerTemplate.MetricType.OWNER,
|
||||
PERCENTAGE_OF_ENTITIES_WITH_OWNER_BY_TYPE,
|
||||
0D,
|
||||
0D,
|
||||
numberOfDaysChange,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
private DataInsightDescriptionAndOwnerTemplate createTierTemplate(
|
||||
@ -324,6 +379,9 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
Long currentTime,
|
||||
int numberOfDaysChange)
|
||||
throws ParseException, IOException {
|
||||
// Create A Date Map
|
||||
Map<String, Integer> dateMap = new LinkedHashMap<>();
|
||||
Utilities.getLastSevenDays(currentTime).forEach(day -> dateMap.put(day, 0));
|
||||
// Get total Assets Data
|
||||
// This assumes that on a particular date the correct count per entities are given
|
||||
TreeMap<Long, List<Object>> dateWithDataMap =
|
||||
@ -336,6 +394,14 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
if (dateWithDataMap.lastEntry() != null) {
|
||||
List<TotalEntitiesByTier> last =
|
||||
JsonUtils.convertValue(dateWithDataMap.lastEntry().getValue(), new TypeReference<>() {});
|
||||
dateWithDataMap.forEach(
|
||||
(key, value) -> {
|
||||
List<TotalEntitiesByTier> list =
|
||||
JsonUtils.convertValue(value, new TypeReference<>() {});
|
||||
Double count = getCountOfTieredEntities(list);
|
||||
dateMap.put(Utilities.getDateFromEpoch(key), count.intValue());
|
||||
});
|
||||
processDateMapToNormalize(dateMap);
|
||||
Map<String, Double> tierData = getTierData(last);
|
||||
return new DataInsightDescriptionAndOwnerTemplate(
|
||||
DataInsightDescriptionAndOwnerTemplate.MetricType.TIER,
|
||||
@ -346,10 +412,21 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
false,
|
||||
"",
|
||||
numberOfDaysChange,
|
||||
tierData);
|
||||
tierData,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
throw new IOException(MISSING_DATA);
|
||||
return new DataInsightDescriptionAndOwnerTemplate(
|
||||
DataInsightDescriptionAndOwnerTemplate.MetricType.TIER,
|
||||
null,
|
||||
0D,
|
||||
KPI_NOT_SET,
|
||||
0D,
|
||||
false,
|
||||
"",
|
||||
numberOfDaysChange,
|
||||
new HashMap<>(),
|
||||
dateMap);
|
||||
}
|
||||
|
||||
private Double getCountOfEntitiesFromList(List<TotalEntitiesByType> entitiesByTypeList) {
|
||||
@ -361,6 +438,15 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
private Double getCountOfTieredEntities(List<TotalEntitiesByTier> entitiesByTierList) {
|
||||
// If there are multiple entries for same entities then this can yield invalid results
|
||||
double totalCount = 0D;
|
||||
for (TotalEntitiesByTier obj : entitiesByTierList) {
|
||||
totalCount += obj.getEntityCountFraction() * 100;
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
private Map<String, Double> getTierData(List<TotalEntitiesByTier> entitiesByTypeList) {
|
||||
// If there are multiple entries for same entities then this can yield invalid results
|
||||
Map<String, Double> data = new TreeMap<>();
|
||||
@ -415,7 +501,8 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
DataInsightChartResult.DataInsightChartType chartType,
|
||||
Double percentCompleted,
|
||||
Double percentChange,
|
||||
int numberOfDaysChange) {
|
||||
int numberOfDaysChange,
|
||||
Map<String, Integer> dateMap) {
|
||||
|
||||
List<Kpi> kpiList = getAvailableKpi();
|
||||
Kpi validKpi = null;
|
||||
@ -463,60 +550,32 @@ public class DataInsightsReportApp extends AbstractNativeApplication {
|
||||
isKpiAvailable,
|
||||
totalDaysLeft,
|
||||
numberOfDaysChange,
|
||||
null);
|
||||
null,
|
||||
dateMap);
|
||||
}
|
||||
|
||||
private long getTimeFromSchedule(
|
||||
AppSchedule appSchedule, JobExecutionContext jobExecutionContext) {
|
||||
AppSchedule.ScheduleTimeline timeline = appSchedule.getScheduleType();
|
||||
return switch (timeline) {
|
||||
case HOURLY -> 3600000L;
|
||||
case DAILY -> 86400000L;
|
||||
case WEEKLY -> 604800000L;
|
||||
case MONTHLY -> 2592000000L;
|
||||
case CUSTOM -> {
|
||||
if (jobExecutionContext.getTrigger() != null) {
|
||||
Trigger triggerQrz = jobExecutionContext.getTrigger();
|
||||
Date previousFire =
|
||||
triggerQrz.getPreviousFireTime() == null
|
||||
? triggerQrz.getStartTime()
|
||||
: triggerQrz.getPreviousFireTime();
|
||||
yield previousFire.toInstant().toEpochMilli();
|
||||
}
|
||||
yield 86400000L;
|
||||
}
|
||||
};
|
||||
private void processDateMapToNormalize(Map<String, Integer> dateMap) {
|
||||
Pair<Integer, Integer> maxIn = getMinAndMax(dateMap.values().stream().toList());
|
||||
dateMap.replaceAll(
|
||||
(k, v) ->
|
||||
getNormalizedValue(
|
||||
v.doubleValue(), maxIn.getRight().doubleValue(), maxIn.getLeft().doubleValue())
|
||||
.intValue());
|
||||
}
|
||||
|
||||
public static int getNumberOfDays(AppSchedule appSchedule) {
|
||||
AppSchedule.ScheduleTimeline timeline = appSchedule.getScheduleType();
|
||||
switch (timeline) {
|
||||
case HOURLY:
|
||||
return 0;
|
||||
case DAILY:
|
||||
return 1;
|
||||
case WEEKLY:
|
||||
return 7;
|
||||
case MONTHLY:
|
||||
return 30;
|
||||
case CUSTOM:
|
||||
if (!CommonUtil.nullOrEmpty(appSchedule.getCronExpression())) {
|
||||
Trigger triggerQrz =
|
||||
CronScheduleBuilder.cronSchedule(appSchedule.getCronExpression()).build();
|
||||
Date previousFire =
|
||||
triggerQrz.getPreviousFireTime() == null
|
||||
? triggerQrz.getStartTime()
|
||||
: triggerQrz.getPreviousFireTime();
|
||||
Date nextFire = triggerQrz.getFireTimeAfter(previousFire);
|
||||
Period period =
|
||||
Period.between(
|
||||
previousFire.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
|
||||
nextFire.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
|
||||
return period.getDays();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Missing Cron Expression for Custom Schedule.");
|
||||
}
|
||||
private Pair<Integer, Integer> getMinAndMax(List<Integer> integers) {
|
||||
Optional<Integer> minOptional = integers.stream().min(Integer::compareTo);
|
||||
Optional<Integer> maxOptional = integers.stream().max(Integer::compareTo);
|
||||
int min = minOptional.orElseThrow(() -> new IllegalArgumentException("List is empty"));
|
||||
int max = maxOptional.orElseThrow(() -> new IllegalArgumentException("List is empty"));
|
||||
|
||||
return Pair.of(min, max);
|
||||
}
|
||||
|
||||
private Double getNormalizedValue(Double value, Double max, Double min) {
|
||||
if (max - min == 0) {
|
||||
return 0d;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid Trigger Type, Can only be Scheduled.");
|
||||
return ((value - min) / (max - min) * 50);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ import org.openmetadata.service.workflows.searchIndex.PaginatedEntitiesSource;
|
||||
import org.quartz.JobExecutionContext;
|
||||
|
||||
@Slf4j
|
||||
@SuppressWarnings("unused")
|
||||
public class SearchIndexApp extends AbstractNativeApplication {
|
||||
|
||||
private static final String ALL = "all";
|
||||
|
||||
@ -7,6 +7,7 @@ import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||
import org.openmetadata.service.search.SearchRepository;
|
||||
|
||||
@Slf4j
|
||||
@SuppressWarnings("unused")
|
||||
public class NoOpTestApplication extends AbstractNativeApplication {
|
||||
|
||||
@Override
|
||||
|
||||
@ -15,6 +15,7 @@ package org.openmetadata.service.events.scheduled.template;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DataInsightDescriptionAndOwnerTemplate {
|
||||
public enum MetricType {
|
||||
DESCRIPTION,
|
||||
@ -36,6 +37,7 @@ public class DataInsightDescriptionAndOwnerTemplate {
|
||||
private String completeMessage;
|
||||
private int numberOfDaysChange;
|
||||
private Map<String, Double> tierMap;
|
||||
private Map<String, Integer> dateMap;
|
||||
|
||||
public DataInsightDescriptionAndOwnerTemplate(
|
||||
MetricType metricType,
|
||||
@ -46,7 +48,8 @@ public class DataInsightDescriptionAndOwnerTemplate {
|
||||
boolean isKpiAvailable,
|
||||
String numberOfDaysLeft,
|
||||
int numberOfDaysChange,
|
||||
Map<String, Double> tierMap) {
|
||||
Map<String, Double> tierMap,
|
||||
Map<String, Integer> dateMap) {
|
||||
this.percentCompleted = String.format("%.2f", percentCompleted);
|
||||
this.targetKpi = targetKpi;
|
||||
this.percentChange = String.format("%.2f", percentChange);
|
||||
@ -54,6 +57,7 @@ public class DataInsightDescriptionAndOwnerTemplate {
|
||||
this.numberOfDaysLeft = numberOfDaysLeft;
|
||||
this.tierMap = tierMap;
|
||||
this.numberOfDaysChange = numberOfDaysChange;
|
||||
this.dateMap = dateMap;
|
||||
String color = "#BF0000";
|
||||
if (percentChange > 0) {
|
||||
color = "#008510";
|
||||
@ -86,7 +90,7 @@ public class DataInsightDescriptionAndOwnerTemplate {
|
||||
case NOT_MET -> "The Target set for KPIs was not met it’s time to restructure your goals and progress faster.";
|
||||
};
|
||||
}
|
||||
return "You have not set any KPIS yet, it’s time to restructure your goals, set KPIs and progress faster.";
|
||||
return "You have not set any KPIs yet, it’s time to restructure your goals, set KPIs and progress faster.";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@ -150,4 +154,12 @@ public class DataInsightDescriptionAndOwnerTemplate {
|
||||
public void setNumberOfDaysChange(int numberOfDaysChange) {
|
||||
this.numberOfDaysChange = numberOfDaysChange;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getDateMap() {
|
||||
return dateMap;
|
||||
}
|
||||
|
||||
public void setDateMap(Map<String, Integer> dateMap) {
|
||||
this.dateMap = dateMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,17 +13,25 @@
|
||||
|
||||
package org.openmetadata.service.events.scheduled.template;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DataInsightTotalAssetTemplate {
|
||||
private String totalDataAssets;
|
||||
private String percentChangeTotalAssets;
|
||||
private String completeMessage;
|
||||
private int numberOfDaysChange;
|
||||
private Map<String, Integer> dateMap;
|
||||
|
||||
public DataInsightTotalAssetTemplate(
|
||||
Double totalDataAssets, Double percentChangeTotalAssets, int numberOfDaysChange) {
|
||||
Double totalDataAssets,
|
||||
Double percentChangeTotalAssets,
|
||||
int numberOfDaysChange,
|
||||
Map<String, Integer> dateMap) {
|
||||
this.totalDataAssets = String.format("%.2f", totalDataAssets);
|
||||
this.percentChangeTotalAssets = String.format("%.2f", percentChangeTotalAssets);
|
||||
this.numberOfDaysChange = numberOfDaysChange;
|
||||
this.dateMap = dateMap;
|
||||
String color = "#BF0000";
|
||||
if (percentChangeTotalAssets > 0) {
|
||||
color = "#008510";
|
||||
@ -65,4 +73,12 @@ public class DataInsightTotalAssetTemplate {
|
||||
public void setNumberOfDaysChange(int numberOfDaysChange) {
|
||||
this.numberOfDaysChange = numberOfDaysChange;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getDateMap() {
|
||||
return dateMap;
|
||||
}
|
||||
|
||||
public void setDateMap(Map<String, Integer> dateMap) {
|
||||
this.dateMap = dateMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,6 +337,8 @@ public class EmailUtil {
|
||||
|
||||
public static void sendDataInsightEmailNotificationToUser(
|
||||
Set<String> emails,
|
||||
String startDate,
|
||||
String endDate,
|
||||
DataInsightTotalAssetTemplate totalAssetObj,
|
||||
DataInsightDescriptionAndOwnerTemplate descriptionObj,
|
||||
DataInsightDescriptionAndOwnerTemplate ownerShipObj,
|
||||
@ -346,6 +348,8 @@ public class EmailUtil {
|
||||
throws IOException, TemplateException {
|
||||
if (Boolean.TRUE.equals(getSmtpSettings().getEnableSmtpServer())) {
|
||||
Map<String, Object> templatePopulator = new HashMap<>();
|
||||
templatePopulator.put("startDate", startDate);
|
||||
templatePopulator.put("endDate", endDate);
|
||||
templatePopulator.put("totalAssetObj", totalAssetObj);
|
||||
templatePopulator.put("descriptionObj", descriptionObj);
|
||||
templatePopulator.put("ownershipObj", ownerShipObj);
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
package org.openmetadata.service.util;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Utilities {
|
||||
private Utilities() {}
|
||||
|
||||
public static List<String> getLastSevenDays(long currentEpochTimestampInMilli) {
|
||||
List<String> lastSevenDays = new ArrayList<>();
|
||||
|
||||
// Create a formatter for the date
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d");
|
||||
|
||||
// Calculate and add the dates for the last seven days
|
||||
for (int i = 6; i >= 0; i--) {
|
||||
long dayEpochTimestamp =
|
||||
currentEpochTimestampInMilli
|
||||
- ((long) i * 24 * 60 * 60 * 1000); // Subtracting seconds for each day
|
||||
LocalDateTime dateTime =
|
||||
LocalDateTime.ofInstant(
|
||||
Instant.ofEpochMilli(dayEpochTimestamp), java.time.ZoneId.systemDefault());
|
||||
lastSevenDays.add(dateTime.format(formatter));
|
||||
}
|
||||
|
||||
return lastSevenDays;
|
||||
}
|
||||
|
||||
public static String getMonthAndDateFromEpoch(long epochTimestamp) {
|
||||
return getFormattedDateFromEpoch(epochTimestamp, "MMM d");
|
||||
}
|
||||
|
||||
public static String getDateFromEpoch(long epochTimestampInMilli) {
|
||||
return getFormattedDateFromEpoch(epochTimestampInMilli, "d");
|
||||
}
|
||||
|
||||
private static String getFormattedDateFromEpoch(long epochTimestamp, String format) {
|
||||
Instant instant = Instant.ofEpochMilli(epochTimestamp);
|
||||
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
|
||||
// Define a custom date formatter
|
||||
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(format);
|
||||
|
||||
return dateTime.format(dateFormat);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user