Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring boot 记录Spring Boot web应用程序的推荐方法是什么?_Spring Boot_Logging - Fatal编程技术网

Spring boot 记录Spring Boot web应用程序的推荐方法是什么?

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

我用Spring Boot开发了一个web应用程序。我已经在AWS ElasticBeanstalk上部署了它。 我现在正在开发一个基于SpringAOP的日志系统。我创建了一个方面,它拦截@Service、@Repository和@Controller映射的类的所有方法调用。这是一节课:

@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级的数据—我希望有人为我这样做: