package gov.nysenate.openleg.service.spotcheck.base; import com.google.common.collect.MapMaker; import com.google.common.eventbus.EventBus; import gov.nysenate.openleg.config.Environment; import gov.nysenate.openleg.model.notification.Notification; import gov.nysenate.openleg.model.notification.NotificationType; import gov.nysenate.openleg.model.spotcheck.SpotCheckAbortException; import gov.nysenate.openleg.model.spotcheck.SpotCheckRefType; import gov.nysenate.openleg.model.spotcheck.SpotCheckReport; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.Map; @Service public class SpotCheckNotificationService { private static final Logger logger = LoggerFactory.getLogger(SpotCheckNotificationService.class); @Autowired private EventBus eventBus; @Autowired private Environment env; /** * Sends out a notification reporting the given spotcheck exception * * @param ex Exception - an exception that was raised during a spotcheck action * @param duringReport - true if the exception occurred during a report run */ public void handleSpotcheckException(Exception ex, boolean duringReport) { if (!(ex instanceof SpotCheckAbortException)) { logger.error("Spotcheck Error:\n{}", ExceptionUtils.getStackTrace(ex)); eventBus.post(new Notification( NotificationType.SPOTCHECK_EXCEPTION, LocalDateTime.now(), "Spotcheck Error: " + ExceptionUtils.getStackFrames(ex)[0], "An error occurred while " + (duringReport ? "running a spotcheck report" : "processing spotcheck data") + " at " + LocalDateTime.now() + ":\n" + ExceptionUtils.getStackTrace(ex) )); } } /** * Generates and sends a notification for a new daybreak spotcheck report * * @param daybreakReport SpotCheckReport< */ public void spotcheckCompleteNotification(SpotCheckReport<?> daybreakReport) { String summary = "New " + daybreakReport.getReportId().getReferenceType() + " spotcheck report: " + daybreakReport.getReportDateTime(); StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append(summary) .append("\n") .append(env.getUrl()) .append("/admin/report/spotcheck/") .append(daybreakReport.getReferenceType().getRefName()) .append("/") .append(daybreakReport.getReportDateTime()) .append("\n") .append(StringUtils.isNotBlank(daybreakReport.getNotes()) ? "Notes: " + daybreakReport.getNotes() : "") .append("\n\n") .append("Total open errors: ") .append(daybreakReport.getOpenMismatchCount(false)) .append("\n"); daybreakReport.getMismatchStatusTypeCounts(false).forEach((status, typeCounts) -> { long totalTypeCounts = typeCounts.values().stream().reduce(0L, (a, b) -> a + b); messageBuilder.append(status) .append(": ") .append(totalTypeCounts) .append("\n"); typeCounts.forEach((type, count) -> messageBuilder.append("\t") .append(type) .append(": ") .append(count) .append("\n")); }); long ignoredCount = daybreakReport.getOpenMismatchCount(true); if (ignoredCount > 0) { messageBuilder.append("IGNORED: ") .append(ignoredCount) .append("\n"); } NotificationType type = daybreakReport.getOpenMismatchCount(false) > 0 ? daybreakReport.getReferenceType().getNotificationType() : NotificationType.SPOTCHECK_ALL_CLEAR; Notification notification = new Notification(type, daybreakReport.getReportDateTime(), summary, messageBuilder.toString()); eventBus.post(notification); } }