Spring boot 记录Spring Boot web应用程序的推荐方法是什么?
我用Spring Boot开发了一个web应用程序。我已经在AWS ElasticBeanstalk上部署了它。 我现在正在开发一个基于SpringAOP的日志系统。我创建了一个方面,它拦截@Service、@Repository和@Controller映射的类的所有方法调用。这是一节课:Spring boot 记录Spring Boot web应用程序的推荐方法是什么?,spring-boot,logging,Spring Boot,Logging,我用Spring Boot开发了一个web应用程序。我已经在AWS ElasticBeanstalk上部署了它。 我现在正在开发一个基于SpringAOP的日志系统。我创建了一个方面,它拦截@Service、@Repository和@Controller映射的类的所有方法调用。这是一节课: @Aspect @Component public class LoggingAspect { @Autowired(required = false) private HttpServle
@Aspect
@Component
public class LoggingAspect {
@Autowired(required = false)
private HttpServletRequest request;
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Pointcut that matches all repositories, services and Web REST endpoints.
*/
@Pointcut("within(@org.springframework.stereotype.Repository *)" +
" || within(@org.springframework.stereotype.Service *)" +
" || within(@org.springframework.stereotype.Controller *)")
public void springBeanPointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Pointcut that matches all Spring beans in the application's main packages.
*/
@Pointcut("within(com.mywebapp..*)" +
" || within(com.mywebapp.service..*)" +
" || within(com.mywebapp.controller..*)")
public void applicationPackagePointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Advice that logs methods throwing exceptions.
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
String s = "";
if(joinPoint.getArgs() != null)
s = Arrays.toString(joinPoint.getArgs());
log.error("Exception in {}.{}({}) with cause = {}",
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(),
s,
e.getCause() != null ? e.getCause() : "NULL");
}
/**
* Advice that logs when a method is entered and exited.
*
* @param joinPoint join point for advice
* @return result
* @throws Throwable throws IllegalArgumentException
*/
@Around("applicationPackagePointcut() && springBeanPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
if(request != null && joinPoint.getSignature().toString().contains("controller")){
log.info("Request: {} {} from {}",
request.getMethod(),
request.getRequestURI(),
request.getRemoteAddr());
}
log.info("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
try {
Object result = joinPoint.proceed();
String printResult = "";
if(result instanceof InputStream)
printResult = "InputStream type found!";
else
printResult = result.toString();
log.info("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), printResult);
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
}
它工作得很好。我可以在日志中看到所有信息。现在我的问题是:保存所有这些信息的最佳做法是什么?将它们保存在默认的Spring日志文件中就足够了吗?还是最好创建一个NoSql文档并以更可读的方式保存所有这些格式化的信息。
例如,我创建了这个简单的对象,可以使用mongodb以更好的方式存储这些信息:
@Document
public class LogEvent {
private String requestUrl;
private String ipAddress;
private String type;
private String message;
public LogEvent(String requestUrl, String ipAddress, String type, String message) {
this.requestUrl = requestUrl;
this.ipAddress = ipAddress;
this.type = type;
this.message = message;
}
}
type将是error或info,message将是签名、参数名称和每个方法调用的结果,例如:
Request: GET /pages/who-is from 0:0:0:0:0:0:0:1
Enter: com.mywebapp.controller.PageController.getWhoIs() with argument[s] = []
Exit: com.mywebapp.controller.PageController.getWhoIs() with result = who-is
您不想在服务器日志文件和文本文件中进行挖掘,最好将应用程序生成的日志从服务器中取出,放入某种存储中,这样您就可以以一种定义良好且易于理解的方式进行查询、聚合和处理。正如您所提到的,将其存储在Mongo中是可能的,但还有许多其他解决方案 然后问题是,您是想运行和管理自己的日志管理堆栈,还是想使用托管服务?您是想为服务付费,还是用自己的时间付费?日志的高可用性有多重要?例如,在您的Mongo示例中,如果Mongo发生中断,您是否对应用程序日志记录视而不见?这样行吗?为了能够查询和报告正在生成的日志,可以接受的端到端延迟是多少?这些问题的答案将有助于推动您的方法 有许多“日志即服务”产品,这取决于您预期的数据量以及这些产品对任何安全需求的要求等。对于将数据从应用程序中取出并放入存储器,这是一种被广泛采用的方法,它允许您控制日志模式并与大多数解决方案很好地集成 还有一些完全管理的服务,例如Azure application insights for Java,在这些服务中,数据的收集和管理都是为您完成的,您只需为输入的每GB数据付费 我建议您查看其中一个免费产品,看看它们是否符合您的要求——我已经成功地在小型、非关键应用程序中使用过 在数据量更大、延迟时间和可用性要求更严格的情况下,我更喜欢托管服务,因为这是一个大数据问题,我不想管理TB级的数据—我希望有人为我这样做: