Format JSON payloads for readable HTTP logging
All checks were successful
Deploy Gateway / deploy (push) Successful in 1m34s

This commit is contained in:
2026-08-18 15:55:00 +09:00
parent 0a21031a42
commit 787489f6c1
3 changed files with 30 additions and 6 deletions

View File

@@ -58,7 +58,7 @@ public class HttpToolClient implements ToolClient {
request.toolName(),
request.version(),
request.endpoint(),
request.arguments());
prettyJson(request.arguments()));
RestClient.RequestBodySpec spec = requestSpec(request, context);
var entity =
spec.retrieve()
@@ -68,12 +68,13 @@ public class HttpToolClient implements ToolClient {
throw statusException(response.getStatusCode().value(), request.toolName());
})
.toEntity(String.class);
JsonNode responseBody = parseResponse(entity.getBody(), entity.getHeaders().getContentType()); log.info(
JsonNode responseBody = parseResponse(entity.getBody(), entity.getHeaders().getContentType());
log.info(
"TEMP_TOOL_HTTP_RESPONSE_BODY direction=tool_server_to_mcp toolName={} version={} statusCode={} body={}",
request.toolName(),
request.version(),
entity.getStatusCode().value(),
responseBody);
prettyJson(responseBody));
return new ToolResponse(entity.getStatusCode().value(), responseBody);
} catch (ToolClientException exception) {
throw exception;
@@ -88,6 +89,17 @@ public class HttpToolClient implements ToolClient {
}
}
/**
* 임시 Tool 본문 로그를 보기 쉽게 출력하기 위해 JSON 값을 개행된 문자열로 변환합니다.
* 직렬화 실패 시에도 Tool 호출 결과는 바꾸지 않고 문자열 변환 결과만 로그에 남깁니다.
*/
private String prettyJson(JsonNode value) {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
} catch (Exception exception) {
return String.valueOf(value);
}
}
/**
* URI, bypass 헤더와 JSON body를 조합해 실행 직전 POST 요청 객체를 만듭니다. Agent Builder가 보낸 correlation·사원 식별자는 이름과 값을 바꾸지 않고 그대로 실어 보냅니다. 사원 식별자는 암호문이며 MCP는 복호화하지 않으므로, 이
* 경계에서는 전달만 하고 해석하지 않습니다.

View File

@@ -95,7 +95,7 @@ public class McpController {
*/
private String toJson(Object value) {
try {
return objectMapper.writeValueAsString(value);
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
} catch (Exception exception) {
return String.valueOf(value);
}

View File

@@ -107,12 +107,13 @@ public class McpExchangeFilter extends OncePerRequestFilter {
"path",
request.getRequestURI(),
"mcpMethod",
mcpMethod); log.info(
mcpMethod);
log.info(
"TEMP_MCP_HTTP_REQUEST_BODY direction=agent_to_mcp httpMethod={} path={} mcpMethod={} body={}",
request.getMethod(),
request.getRequestURI(),
mcpMethod,
cachedRequest.bodyText());
prettyJson(cachedRequest.bodyText()));
try {
protocolVersionValidator.validatePostInitializeRequest(request, mcpMethod);
@@ -176,6 +177,17 @@ public class McpExchangeFilter extends OncePerRequestFilter {
*
* @return method 이름. 읽을 수 없으면 {@code null}
*/
/**
* 임시 요청 본문 로그를 보기 쉽게 출력하기 위해 JSON이면 개행된 문자열로 변환합니다.
* JSON 파싱이 실패하면 원문 문자열을 그대로 돌려 요청 처리 흐름에는 영향을 주지 않습니다.
*/
private String prettyJson(String body) {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectMapper.readTree(body));
} catch (Exception exception) {
return body;
}
}
private String extractMethod(CachedBodyHttpServletRequest request) {
try {
JsonNode envelope = objectMapper.readTree(request.getInputStream());