Skip to content

Commit

Permalink
Add details for 'coverage period missing or year,month query incorrec…
Browse files Browse the repository at this point in the history
…t' log statements (#1418)

## 🎫 Ticket

- https://jira.cms.gov/browse/AB2D-6418
- https://jira.cms.gov/browse/AB2D-6425

## 🛠 Changes

Add details to log message for `coverage period missing or year,month
query incorrect` error messages.

## ℹ️ Context

When we receive a Slack notification of a failed job, the relevant
details (e.g. coverage month and year) are not present in Splunk. This
PR adds those details for debugging purposes.

![image](https://github.com/user-attachments/assets/87cfcea5-c673-4198-a65d-fb6315cb5f9b)

## 🧪 Validation

Added unit tests that verified additional statements were printed to the
logs

![image](https://github.com/user-attachments/assets/b7b29df6-7cf8-46e7-8128-846537ed2a99)
  • Loading branch information
bennavapbc authored Nov 21, 2024
1 parent 554c4ee commit 628532b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -562,22 +562,28 @@ public CoveragePagingResult pageCoverage(Job job, ContractDTO contract) {
}

ZonedDateTime startDateTime = getStartDateTime(contract);

// Additional details to log in the event of exception
Optional<String> additionalDetails = Optional.empty();
try {
// Check that all coverage periods necessary are present before beginning to page
while (startDateTime.isBefore(now)) {
additionalDetails = Optional.of(String.format("contract='%s' month='%s', year='%s'",
contract.getContractNumber(),
startDateTime.getMonthValue(),
startDateTime.getYear()));
// Will throw exception if it doesn't exist
coverageService.getCoveragePeriod(mapping.map(contract), startDateTime.getMonthValue(), startDateTime.getYear());
startDateTime = startDateTime.plusMonths(1);
}
additionalDetails = Optional.empty();

// Make initial request which returns a result and a request starting at the next cursor
CoveragePagingRequest request = new CoveragePagingRequest(PAGING_SIZE, null, mapping.map(contract), job.getCreatedAt());

additionalDetails = Optional.of(request.toString());
// Make request for coverage metadata
return coverageService.pageCoverage(request);
} catch (Exception exception) {
log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier");
log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier - {}", additionalDetails.orElse(""));
throw new CoverageDriverException("coverage driver failing preconditions", exception);
}
}
Expand Down Expand Up @@ -632,7 +638,7 @@ public CoveragePagingResult pageCoverage(CoveragePagingRequest request) {
try {
return coverageService.pageCoverage(request);
} catch (Exception exception) {
log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier");
log.error("coverage period missing or year,month query incorrect, driver should have resolved earlier - {}", request.toString());
throw new CoverageDriverException("coverage driver failing preconditions", exception);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import javax.persistence.EntityNotFoundException;

import gov.cms.ab2d.worker.service.coveragesnapshot.CoverageSnapshotService;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -36,6 +37,8 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.test.util.ReflectionTestUtils;


Expand All @@ -60,7 +63,7 @@
/**
* Tests for paging coverage which are much easier using mocked resources
*/
@ExtendWith(MockitoExtension.class)
@ExtendWith({MockitoExtension.class, OutputCaptureExtension.class})
class CoverageDriverUnitTest {

@Mock
Expand Down Expand Up @@ -229,9 +232,30 @@ void pageRequestWhenSinceDateAfterNow() {
assertNotNull(result);
}

@DisplayName("Paging coverage fails when all coverage periods are present but CoverageService#pageCoverage throws exception")
@Test
void failPagingWhenCoveragePeriodsPresentButUnderlyingMethodThrowsException(CapturedOutput output) {
when(coverageService.getCoveragePeriod(any(ContractForCoverageDTO.class), anyInt(), anyInt())).thenAnswer((invocationOnMock) -> {
CoveragePeriod period = new CoveragePeriod();
period.setContractNumber((invocationOnMock.getArgument(0).toString()));
period.setMonth(invocationOnMock.getArgument(1));
period.setYear(invocationOnMock.getArgument(2));
return period;
});

when(coverageService.pageCoverage(any())).thenThrow(RuntimeException.class);

Job job = new Job();
ContractDTO contract = new ContractDTO(null, "Contract-0", null, AB2D_EPOCH.toOffsetDateTime(), null, 0, 0);
when(mapping.map(any(ContractDTO.class))).thenReturn(new ContractForCoverageDTO("Contract-0", contract.getAttestedOn(), ContractForCoverageDTO.ContractType.NORMAL));

assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(job, contract));
assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - CoveragePagingRequest(jobStartTime=null, contract=ContractForCoverageDTO(contractNumber=Contract-0, attestedOn=2020-01-01T00:00-05:00, contractType=NORMAL), pageSize=10000, cursor=Optional.empty)"));
}

@DisplayName("Paging coverage fails when coverage periods are missing")
@Test
void failPagingWhenCoveragePeriodMissing() {
void failPagingWhenCoveragePeriodMissing(CapturedOutput output) {

when(coverageService.getCoveragePeriod(any(), anyInt(), anyInt())).thenThrow(new EntityNotFoundException());

Expand All @@ -240,6 +264,7 @@ void failPagingWhenCoveragePeriodMissing() {

CoverageDriverException startDateInFuture = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(job, contract));
assertEquals(EntityNotFoundException.class, startDateInFuture.getCause().getClass());
assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - contract='null' month='1', year='2020'"));
}

@DisplayName("Paging coverage periods")
Expand Down Expand Up @@ -354,16 +379,18 @@ void failureToLockCoverageAvailableFailsQuietly() {

@DisplayName("When paging coverage fails throw coverage driver exception")
@Test
void failureToPageCausesExceptions() {
void failureToPageCausesExceptions(CapturedOutput output) {
when(coverageService.pageCoverage(any())).thenThrow(RuntimeException.class);

CoverageDriver driver = new CoverageDriverImpl(null, null, coverageService, null, null, null,null, snapshotService);

ContractForCoverageDTO contract = new ContractForCoverageDTO();
contract.setContractNumber("contractNum");

CoverageDriverException exception = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(new CoveragePagingRequest( 1000, null, contract, OffsetDateTime.now())));
val coveragePagingRequest = new CoveragePagingRequest( 1000, null, contract, AB2D_EPOCH.toOffsetDateTime());
CoverageDriverException exception = assertThrows(CoverageDriverException.class, () -> driver.pageCoverage(coveragePagingRequest));
assertTrue(exception.getMessage().contains("coverage driver failing preconditions"));
assertTrue(output.getOut().contains("coverage period missing or year,month query incorrect, driver should have resolved earlier - CoveragePagingRequest(jobStartTime=2020-01-01T00:00-05:00, contract=ContractForCoverageDTO(contractNumber=contractNum, attestedOn=null, contractType=null), pageSize=1000, cursor=Optional.empty"));
}

@DisplayName("When loading a mapping job exit early if conditions not met")
Expand Down

0 comments on commit 628532b

Please sign in to comment.