본문 바로가기

개발자를 벗어나긴 글렀다./Spring boot

Spring boot + Asp 로 request / response logging

특정 I/F에 해당하는 request / response 로그를 저장하여, 모니터링 할수 있는 프로그램을 만들고자 아래와 같은 Aspect를 만들었다.

해당기능은 시작시점 DB저장, 성공/실패 시 DB 저장 하고 오류까지 저장하는 것이다.


구조는 간단하다. Before / After / Throwing 3개 함수로 시작전에 request를 저장하고, 성공 실패시 다시 저장한다.

다만, 그 2개를 이어주는 키가 필요하여 세션에 저장하여 사용한다.(SESSION_IF_KEY)


@Aspect
@Order(1)
@Component
@Slf4j
@ConditionalOnExpression("${endpoint.aspect.enabled:true}")
public class EndpointAspect {

private static final String SESSION_IF_KEY = "INTERFACE_HISTORY_KEY";

@Pointcut("execution(* com.rest.*Controller.*ByInterface(..))") //원하는 규칙
private void ifControllerMethod(){}

@Autowired
InterfaceHistoryRepository historyRepository;

@Before(value ="ifControllerMethod()")
public void endpointBefore(JoinPoint p) {
String methodName = p.getSignature().toShortString();

log.debug("[Aspect] Controlloer Call Info START");
log.debug("[Aspect] " + methodName + " START");

Object[] signatureArgs = p.getArgs();
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest().getSession();

try {
if (signatureArgs != null) {

StringBuilder argValueBuf = new StringBuilder();
int i = 0;
for (Object argument : signatureArgs) {
if (argument != null) {
argValueBuf.append("arg").append(i).append(" : ").append(argument.toString()).append("\n");
} else {
argValueBuf.append("arg").append(i).append(" : null\n");
}
}
if(session != null){
String key = (String)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
InterfaceHistory interfaceHistory = new InterfaceHistory( key, methodName, argValueBuf.toString());
InterfaceHistory newInterfaceHistory = historyRepository.save(interfaceHistory);
session.setAttribute(SESSION_IF_KEY, newInterfaceHistory.getLogSq());
}

}
} catch ( Exception e) {
log.debug(e.getMessage());
}
}

@AfterReturning(value = "ifControllerMethod()", returning = "returnValue")
public void endpointAfterReturning(JoinPoint p, Object returnValue) {

log.debug("[Aspect] Controlloer Call Info END");
ObjectMapper mapper = new ObjectMapper();
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest().getSession();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
try {
log.debug("\nResponse object: \n" + mapper.writeValueAsString(returnValue));
String responseObject = mapper.writeValueAsString(returnValue);

for(Object o : p.getArgs()){
if(session.getAttribute(SESSION_IF_KEY) != null){
long logSq = (long)session.getAttribute(SESSION_IF_KEY);
InterfaceHistory interfaceHistory = historyRepository.findOne(logSq);
interfaceHistory.setEndDate(new Timestamp(System.currentTimeMillis()));
interfaceHistory.setOutBound(responseObject);
interfaceHistory.setIsSuccess("Y");
historyRepository.save(interfaceHistory);
}
}
} catch (Exception e) {
log.debug(e.getMessage());
} finally{
session.removeAttribute(SESSION_IF_KEY);
}
}


@AfterThrowing(value = "ifControllerMethod()", throwing = "e")
public void endpointAfterThrowing(JoinPoint p, Exception e) throws Exception {

log.debug("[Aspect] Controlloer Call Info ERROR");
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest().getSession();

if(session.getAttribute(SESSION_IF_KEY) != null){
Long logSq = (Long)session.getAttribute(SESSION_IF_KEY);
InterfaceHistory interfaceHistory = historyRepository.findOne(logSq);
interfaceHistory.setEndDate(new Timestamp(System.currentTimeMillis()));
interfaceHistory.setIsSuccess("N");
interfaceHistory.setErrorMsg(Throwables.getStackTraceAsString(e));
historyRepository.save(interfaceHistory);
}
session.removeAttribute(SESSION_IF_KEY);
}
}