특정 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);
}
}
'개발자를 벗어나긴 글렀다. > Spring boot' 카테고리의 다른 글
springboot 2.1.x에서 2.3.x 버전으로 업그레이드 (0) | 2020.09.10 |
---|---|
Spring Boot + ES 연계방식 탐구 (0) | 2020.09.09 |
Spring boot + WebSocket (0) | 2019.01.10 |
Spring boot + Elastic Search (0) | 2019.01.10 |
Spring boot + Spring kafka(Consumer) (2) | 2019.01.09 |