我想添加字符串到我所有的日志来实现这一点,我计划使用aop,但我不能为我所有的logger对象声明切入点。
Logger logger = LoggerFactory.getLogger(InterviewService.class);
logger.error(ex.getMessage(),ex);
字符串
的数据
我试图在ss中拦截logger,所以在打印日志之前,我可以改变消息中的参数并添加我的文本,我稍微改变了我的代码,目前我可以捕获抛出的异常,但仍然不能在方面方法中拦截logger.error(“一些错误日志”)消息。
@Pointcut("within(org.apache.logging.log4j.*)")
public void logPointcut() {}
@Pointcut("within(*..Log4jLogger.*)")
public void logPointcuts() {}
@Pointcut("execution(* *.error(*))")
public void logPointcutsMethod() {}
@Pointcut("within(*.error)")
public void logPointcutsMethodw() {}
@Around("logPointcutsMethod() || logPointcuts() || logPointcut() || logPointcutsMethodw()")
public Object logError(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = joinPoint.proceed();
String user = "";
if (state)
user = getUser();
logger.error(
"Exception in {} User :{}.{}() with cause = {}",
joinPoint.getSignature().getDeclaringTypeName(),
user,
joinPoint.getSignature().getName()
);
return result;
}
型
总而言之,我想为每个logger.error调用创建切入点,这样我就可以将字符串添加到每条消息中
2条答案
按热度按时间laawzig21#
这里有一个完整的MCVE,用于如何在原生的Apache J中解决这个问题,使用Apache J编译器的 inpath 上的Slf 4J和Log4J库使用加载时编织或编译时编织。因为Spring AOP只能拦截Spring beans/组件内的方法,但Slf 4j和Log4j都不是Spring组件,所以您需要一个面向成人的AOP框架,不是像Spring AOP那样的AOP lite解决方案。幸运的是,Spring有一个非常好的AOP J集成,并且在它的手册中也解释了它。
个字符
控制台日志:
型
这是最简单的解决方案。如果您需要日志输出中的更多信息,例如调用者或异常的特殊信息,则可以很容易地调整切入点。此外,
Logger.error(..)
有许多重载。我的示例切入点仅捕获第一个参数为String
的那些,例如error(String)
或error(String, Throwable)
。如果您需要其他信息,你需要调整这个方面。但这是它基本上是如何工作的。请注意,这将拦截所有错误日志,甚至是从应用程序外部调用的错误日志。如果你想将其限制在应用程序的基本包中,你必须再次调整切入点,并使用
call()
而不是execution()
,类似于within(my.base.pkg..*) && call(void org.slf4j.Logger.error(String, ..)) && args(msg, ..)
。有这么多的方法来调整这个解决方案,这将需要几个小时的时间来列出例子。
mzmfm0qo2#
我找到了另一种方法,但上面的解决方案是更合适和更好的方法来做这件事
我在Spring Aop中使用了ThreadContext。下面的代码部分属于我的Spring Aop类,所以我为每个端点调用创建了一个Pointcut。当有一个API调用时,它会进入logAround方法,我在其中声明ThreadContext
字符串
并像这样将用户前缀添加到log4j模式中
型
通过这种方式,在每次API调用之前,我将username添加到线程上下文,然后log4j为每个logger使用此user参数。error(这取决于你如何安排你的log4j.xml文件。从这一点上,你可以添加到跟踪或信息或你的自定义日志级别)和API调用后,我必须删除这个用户名从线程上下文,因为如果你不删除这个值从线程上下文,这个线程将进入线程池,并将被另一个进程调用,它也将携带你添加的值,在我的情况下,它是username。所以,如果我不删除我的值,我可以看到一个username,username不应该被看到