Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
* <p>The advice is scoped to the synchronous and durable-job ETL controllers; unrelated
* controllers retain their existing exception contracts. Every client-visible field is fixed by a
* typed definition. Raw exception messages, SQL details, credentials, paths, causes, and stack
* traces are never copied into the HTTP body. Covered responses use
* traces are never copied into the HTTP body. Ordinary failure logs keep bounded classifications
* without request resource paths or owner-scoped identifiers. Covered responses use
* {@code Cache-Control: no-store} so authenticated operational failures are not retained by shared
* or private caches. Spring MVC routing and response-negotiation failures are deliberately not
* captured by a broad exception handler and therefore retain their framework-owned status
Expand Down Expand Up @@ -58,11 +59,7 @@ public ResponseEntity<ProblemDetail> handleRequestFailure(
HttpServletRequest request
) {
EtlRequestError error = exception.error();
log.debug(
"Rejected ETL request path={} code={}",
request.getRequestURI(),
error.errorCode()
);
log.debug("Rejected ETL request code={}", error.errorCode());
return problem(
error.status(),
error.type(),
Expand All @@ -86,8 +83,7 @@ public ResponseEntity<ProblemDetail> handleUnreadableBody(
HttpServletRequest request
) {
log.debug(
"Rejected unreadable ETL request path={} exceptionType={}",
request.getRequestURI(),
"Rejected unreadable ETL request exceptionType={}",
exception.getClass().getName()
);
EtlRequestError error = EtlRequestError.INVALID_JSON;
Expand All @@ -114,8 +110,7 @@ public ResponseEntity<ProblemDetail> handleTransientTargetFailure(
HttpServletRequest request
) {
log.warn(
"Transient ETL target failure path={} exceptionType={}",
request.getRequestURI(),
"Transient ETL target failure exceptionType={}",
exception.getClass().getName()
);
return problem(
Expand All @@ -141,8 +136,7 @@ public ResponseEntity<ProblemDetail> handleTargetFailure(
HttpServletRequest request
) {
log.error(
"ETL target failure path={} exceptionType={}",
request.getRequestURI(),
"ETL target failure exceptionType={}",
exception.getClass().getName()
);
return problem(
Expand All @@ -168,8 +162,7 @@ public ResponseEntity<ProblemDetail> handleUnexpectedFailure(
HttpServletRequest request
) {
log.error(
"Unexpected ETL failure path={} exceptionType={}",
request.getRequestURI(),
"Unexpected ETL failure exceptionType={}",
exception.getCause().getClass().getName()
);
return problem(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.xtrmetl.etl.controller;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.mock.web.MockHttpServletRequest;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Verifies that ordinary ETL failure logs retain bounded classifications without resource IDs.
*/
@ExtendWith(OutputCaptureExtension.class)
class EtlApiProblemHandlerLoggingTest {

private static final String JOB_RECORD_ID = "0198f4cf-41c8-7f52-9e5d-private-job-marker";

@Test
void targetFailureLogDoesNotRepublishOwnerScopedResourceIdentifier(CapturedOutput output) {
MockHttpServletRequest request = new MockHttpServletRequest(
"GET",
"/api/etl/jobs/" + JOB_RECORD_ID
);
EtlApiProblemHandler handler = new EtlApiProblemHandler();

handler.handleTargetFailure(
new DataIntegrityViolationException("synthetic database diagnostic"),
request
);

String logs = output.getOut() + output.getErr();
assertTrue(logs.contains("ETL target failure"));
assertFalse(logs.contains(JOB_RECORD_ID));
}
}
Loading