LOG4J - EAR 中不同战争的独立日志文件
LOG4J - Separate log files for different wars in EAR
我有以下场景:一个 EAR,有 3 个 WARs(销售模块、内联网模块和主应用程序 - 一个 lms 系统)。每个 WAR 都有它 log4j.properties 配置单独的日志文件,组织并更容易发现每个系统上的问题。
问题是,这 3 个 war 共享一个依赖项 - 一个核心 jar,与我的服务层(实体、存储库、服务等)。该 jar 没有 log4.properties,此处进行的所有日志记录都转到 server.log。我想避免它。
当我过去单独部署 war 时,一切都很好 - 因为 jar 在 war 中并且与 log4j.properties 一起。所以:
Request -> Intranet.war -> Core JAR -> all logging here goes to intranet.log
Request -> LMS.war -> Core JAR -> all logging here goes to lms.log
Request -> Sales.war -> Core JAR -> all logging here goes to sales.log
现在我在 EAR 的 lib/ 文件夹中只有一个核心 jar,由他们共享。
问题是:如何仍然根据war调用核心来组织日志?
我的意思是,如果我在 EAR 中调用 intranet.war,所有 core.jar 的登录仍然会转到 intranet.log。 LMS 和销售相同。
我正在考虑为整个 EAR 创建一个唯一的 log4j.properties 文件,但我如何在文件中分离?我可以使用包方法(例如 xxx.lms.yyy 转到 lms.log),但是核心 jar 中的包是共享的。
有什么想法吗?
提前致谢!
我找到了一种使其与 CDI 和 ThreadLocal 一起工作的方法。
每个request关联一个thread,所以我做了一个CDI Producer方法,逻辑很简单:当前threadlocal是否有Logger?如果是,return它。如果没有,从 SLF4J LoggerFactory 获取一个,将其保存在 ThreadLocal 中并 return 它。
然后,为了在 wars 和核心 jar 中获取记录器,我这样做:
@Inject @MyQualifier private Logger logger;
//I created a specific qualifier because one of the frameworks I use also have a Logger Producer
生产者方法:
@Produces @MyQualifier
public Logger getLogger(InjectionPoint ip){
ThreadLocal<Logger> t = new ThreadLocal<>();
if(t.get() == null) {
Class<?> clazz = ip.getMember().getDeclaringClass();
t.set(org.slf4j.LoggerFactory.getLogger(clazz));
}
return t.get();
}
很有魅力!我的 services/daos 类 都是@requestscoped,所以对于每个请求,我只有一个关联的记录器,它在 WAR 中实例化 - log4j.properties 配置为我想要的那个语境。
但是,有一种情况它不起作用:EJB 中的@Schedule 方法。在这种情况下,线程 "created " 不在 war 中,但已经在 jar 上下文中。对于这些情况,我在 EAR 的 META-INF 文件夹中创建了另一个 log4j.properties。现在一切正常。
我有以下场景:一个 EAR,有 3 个 WARs(销售模块、内联网模块和主应用程序 - 一个 lms 系统)。每个 WAR 都有它 log4j.properties 配置单独的日志文件,组织并更容易发现每个系统上的问题。
问题是,这 3 个 war 共享一个依赖项 - 一个核心 jar,与我的服务层(实体、存储库、服务等)。该 jar 没有 log4.properties,此处进行的所有日志记录都转到 server.log。我想避免它。
当我过去单独部署 war 时,一切都很好 - 因为 jar 在 war 中并且与 log4j.properties 一起。所以:
Request -> Intranet.war -> Core JAR -> all logging here goes to intranet.log
Request -> LMS.war -> Core JAR -> all logging here goes to lms.log
Request -> Sales.war -> Core JAR -> all logging here goes to sales.log
现在我在 EAR 的 lib/ 文件夹中只有一个核心 jar,由他们共享。
问题是:如何仍然根据war调用核心来组织日志?
我的意思是,如果我在 EAR 中调用 intranet.war,所有 core.jar 的登录仍然会转到 intranet.log。 LMS 和销售相同。
我正在考虑为整个 EAR 创建一个唯一的 log4j.properties 文件,但我如何在文件中分离?我可以使用包方法(例如 xxx.lms.yyy 转到 lms.log),但是核心 jar 中的包是共享的。
有什么想法吗?
提前致谢!
我找到了一种使其与 CDI 和 ThreadLocal 一起工作的方法。
每个request关联一个thread,所以我做了一个CDI Producer方法,逻辑很简单:当前threadlocal是否有Logger?如果是,return它。如果没有,从 SLF4J LoggerFactory 获取一个,将其保存在 ThreadLocal 中并 return 它。
然后,为了在 wars 和核心 jar 中获取记录器,我这样做:
@Inject @MyQualifier private Logger logger;
//I created a specific qualifier because one of the frameworks I use also have a Logger Producer
生产者方法:
@Produces @MyQualifier
public Logger getLogger(InjectionPoint ip){
ThreadLocal<Logger> t = new ThreadLocal<>();
if(t.get() == null) {
Class<?> clazz = ip.getMember().getDeclaringClass();
t.set(org.slf4j.LoggerFactory.getLogger(clazz));
}
return t.get();
}
很有魅力!我的 services/daos 类 都是@requestscoped,所以对于每个请求,我只有一个关联的记录器,它在 WAR 中实例化 - log4j.properties 配置为我想要的那个语境。
但是,有一种情况它不起作用:EJB 中的@Schedule 方法。在这种情况下,线程 "created " 不在 war 中,但已经在 jar 上下文中。对于这些情况,我在 EAR 的 META-INF 文件夹中创建了另一个 log4j.properties。现在一切正常。