Logging 将${xd.job.name}和${xd.stream.name}添加到Spring xd日志中
我们正在SpringXDV1.0.0.0版本上运行几个流和作业。 相应的流和作业模块将消息记录到SpringXD的全局日志文件中,$XD_HOME/logs下 我们需要区分每个作业和流创建的日志消息。用${xd.job.name}或${xd.stream.name}值标记每个日志行应该对我们有用。比如说, 1在配置文件Spring XD config、XML上下文文件、Java类中。。。无论如何,设置一个Java上下文变量:Logging 将${xd.job.name}和${xd.stream.name}添加到Spring xd日志中,logging,spring-batch,spring-integration,spring-xd,Logging,Spring Batch,Spring Integration,Spring Xd,我们正在SpringXDV1.0.0.0版本上运行几个流和作业。 相应的流和作业模块将消息记录到SpringXD的全局日志文件中,$XD_HOME/logs下 我们需要区分每个作业和流创建的日志消息。用${xd.job.name}或${xd.stream.name}值标记每个日志行应该对我们有用。比如说, 1在配置文件Spring XD config、XML上下文文件、Java类中。。。无论如何,设置一个Java上下文变量: if(moduleType == "job") { name =
if(moduleType == "job") {
name = ${xd.job.name};
} else if(moduleType == "stream") {
name = ${xd.stream.name};
} else {
name = "XD";
}
2相应地在$XD_HOME/config下配置log4j属性文件:
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2} [${name}] - %m%n
3运行作业XD.job.name=fooJob和流XD.stream.name=barStream的Spring XD的日志输出:
4其他库(例如Spring Data、Apache Commons)记录的任何消息,无论是什么,都应该具有[fooJob]、[barStream]或[XD]中的一个,与调用库的作业或流的值相同
到目前为止,我们提出的唯一不成熟的解决方案是在log4j中设置$name,但我们不知道如何在每个流或每个作业的基础上设置它,而在每个线程的基础上设置MDC和NDC
有没有办法将作业或流名称添加到相应的日志行中?我们在看到您的 我们还讨论了MDC,我们可以在总线实现中设置它,但它只适用于处理器和接收器。我们需要SpringIntegration/SpringBatch中的代码,以使其也适用于源代码和作业 这也是许多人不希望的开销,因此它必须是可选的 底线是我们还没有一个解决方案,但请随意打开一个新功能 编辑:回应你下面的评论 嗯。。。对于处理器和接收器,您可以向输入通道添加一个ChannelInterceptor,并在preSend中推送名称,在postSend中弹出名称。对于源,您可以在输出通道上执行相同的操作 唯一的问题是,如果在preSend之后抛出异常,则不会调用postSend。SpringIntegration4.1应该在下周发布;当前可用作调用interceptor.AfterEndCompletion的函数,无论是否发生异常,都会调用该函数 注意:当获取对通道的引用时,要添加拦截器,必须使用ChannelInterceptorAware,因为bean可能被代理
如果这是可行的,你会愿意的,我们会很乐意考虑的。 我最终创建了一个自定义的Logback 由保存环境实例的bean支持:
@Service
public class SpringLogbackPropertyResolver {
private static volatile SpringLogbackPropertyResolver instance;
private final Environment env;
private final Map<String, String> map;
public SpringLogbackPropertyResolver(@Autowired Environment env) {
this.env = env;
this.map = new ConcurrentHashMap<>();
this.instance = this;
}
public String getProperty(String key, String defaultValue){
return map.computeIfAbsent(key, k -> env.getProperty(key, defaultValue));
}
public static SpringLogbackPropertyResolver getInstance() {
return instance;
}
}
然后可以在日志模式中使用它,其spring前缀为%spring{xd.stream.name:-bar}谢谢您的帮助。我在考虑创建一个XD插件来修改AOP?模块上下文流或作业的每个bean,通过向每个bean的每个方法添加before和after通知。它们应该分别执行NDC.push$name和NDC.pop。在运行流或作业时,每次bean方法开始或结束时,其线程都会被标记或取消标记,相应的日志消息也会被标记或取消标记。我不知道这是否可能,在我看来,这是一个丑陋的黑客。你能提供一些帮助吗?再次感谢你,你的看起来是一个更好的解决方案流,也许沿着这些路线的东西也可以工作-嗯。。。。当你进入基于反应器的流处理器时,这会变得更加棘手——基本上是由任何东西包装的。代码在单独的线程中运行,因此MDC/NDC可能无法工作。我们也在试图找到解决办法。。。
public class SpringPropertyConverter extends ClassicConverter {
private String key;
private String defaultValue = "";
@Override
public void start() {
String[] keyInfo = extractDefaultReplacement(getFirstOption());
key = keyInfo[0];
if (keyInfo[1] != null) {
defaultValue = keyInfo[1];
}
super.start();
}
@Override
public void stop() {
key = null;
super.stop();
}
@Override
public String convert(ILoggingEvent event) {
SpringLogbackPropertyResolver resolver = SpringLogbackPropertyResolver.getInstance();
if (resolver == null) {
return defaultValue;
}
return resolver.getProperty(key, defaultValue);
}
}
@Service
public class SpringLogbackPropertyResolver {
private static volatile SpringLogbackPropertyResolver instance;
private final Environment env;
private final Map<String, String> map;
public SpringLogbackPropertyResolver(@Autowired Environment env) {
this.env = env;
this.map = new ConcurrentHashMap<>();
this.instance = this;
}
public String getProperty(String key, String defaultValue){
return map.computeIfAbsent(key, k -> env.getProperty(key, defaultValue));
}
public static SpringLogbackPropertyResolver getInstance() {
return instance;
}
}
conversionRule("spring", SpringPropertyConverter)