簡體   English   中英

將$ {xd.job.name}和$ {xd.stream.name}添加到Spring XD日志

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM