[英]Add ${xd.job.name} and ${xd.stream.name} to Spring XD logs
我們正在Spring XD v1.0.0.RELEASE上運行多個流和作業。
相應的流和作業模塊將消息記錄到Spring XD的全局日志文件中的$ XD_HOME / logs下
我們需要區分每個作業和流創建的日志消息。 用$ {xd.job.name}或$ {xd.stream.name}的值標記每個日志行應該對我們有用 。 例如,
1)在一個配置文件(Spring XD配置,XML上下文文件,Java類……等等)中,設置一個Java context(?)變量:
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的日志輸出:
...
13:07:41,169 DEBUG task-scheduler-1 myjobimpl.TransactionManager [fooJob] - Initiating transaction commit
...
13:08:43,215 INFO task-scheduler-15 mystreamimpl.JsonDecoder [barStream] - Decoding JSON: {...}
...
14:08:42,569 INFO DeploymentsPathChildrenCache-0 monitor.IntegrationMBeanExporter [XD] - Summary on shutdown: MessageChannelMonitor: [name=input, sends=0]
4)其他庫(例如Spring Data,Apache Commons等)記錄的任何消息都應具有[ fooJob ],[ barStream ]或[ XD ]中的一個,其值與調用該庫的作業或流相同。
到目前為止,我們提出的唯一半生半熟的解決方案是在log4j的MDC或NDC中設置$ name ,但是我們不知道如何在每個流或每個作業的基礎上設置它(MDC和NDC在每個線程基礎)。
有什么方法可以將作業或流名稱添加到其相應的日志行?
我們還討論了MDC,可以在總線實現中設置它,但它僅適用於處理器和接收器。 我們需要Spring Integration / Spring Batch中的代碼以使其也適用於源代碼和作業。
許多人不希望這樣做也會產生開銷,因此它必須是可選的。
最重要的是,我們還沒有解決方案,但是請隨時打開JIRA Issue的新功能。
編輯:在下面回應您的評論...
嗯...對於處理器和接收器,您可以將ChannelInterceptor
添加到input
通道,然后在preSend()
推送名稱,然后在postSend()
其彈出。 對於信號源,您可以在output
通道上執行相同的操作。
與唯一的問題是, postSend()
如果一個異常拋出后不叫preSend()
Spring Integration 4.1(應該在下周發布;當前可以作為候選發布版本 ) 增加了對調用interceptor.afterSendCompletion()
支持 ,無論是否發生異常,該調用都會被調用。
注意:在獲取對通道的引用時,要添加攔截器,則必須使用ChannelInterceptorAware
進行此操作,因為可能會代理該bean。
如果這行得通,並且您想貢獻它,我們很樂意考慮。
我最終創建了一個自定義的Logback 格式轉換器 。
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);
}
}
由包含Environment
實例的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;
}
}
然后在xd-container-logback.groovy
中注冊該轉換器:
conversionRule("spring", SpringPropertyConverter)
然后可以在帶有spring
前綴%spring{xd.stream.name:-bar}
的日志模式中使用它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.