2017-04-10 60 views
0

我有一條消息可以說我想用log4j2登錄delay=1, name=Ash。我想這是JSON格式一樣,logj4消息給json

{"@timestamp": 1234, "delay"=1, "name"="Ash"} 

@timestamp場我的日誌文件的每一行是由記錄儀,而delayname字段是消息的領域所產生的時間戳。

有沒有辦法做到這一點?通過使用JsonLayout我知道我可以使用json格式記錄每個輸出,但仍然沒有找到操作日誌消息的方法,以便我可以將它的不同部分放在不同的字段中。

+0

AFAIK你只能擁有完整的消息作爲一個JSON場。 – Fildor

+0

理想情況下,我想避免這種情況,但要知道沒有辦法也是有幫助的。 – LetsPlayYahtzee

+0

時間戳是消息本身的元信息的一部分,您實際上希望將消息移動到元數據中。你嘗試過MDC嗎? - >如果你使用PatternLayout,你可以把例如上下文中的當前用戶並在消息中重複使用它。如果這不起作用,那麼沒有人會提出解決方案,我會建議實施自己的JsonLayout ... – slowy

回答

0

你可以使用log4j2 JSONLayout來做到這一點。

  • 首先,你必須指定jsonlayout

例子:

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="WARN"> 
    <Appenders> 
     <Console name="Console" target="SYSTEM_OUT"> 
      <JSONLayout compact="true" eventEol="true" properties="true"/> 
     </Console> 
    </Appenders> 
    <Loggers> 
     <Root level="info"> 
      <AppenderRef ref="Console"/> 
     </Root> 
    </Loggers> 
</Configuration> 

在這裏,如果你設置緊湊=假,JSON將打印在prity格式

  • 二您可以ThreadContext將pu值作爲關鍵值對。

例子:

for (int i = 0; i < 5; i++) { 
    ThreadContext.clearAll(); 
    ThreadContext.put("delay", String.valueOf(i)); 
    ThreadContext.put("name", "Ash " + i); 
    LOGGER.info("Testing ", "k1", "v1", "k2", "v2"); 
} 

這裏ThreadContext把所有的鍵值對,直到你清楚了。

輸出:

{"timeMillis":1491819918389,"thread":"main","level":"INFO","loggerName":"com.ashraful.ilpexp.LogTest","message":"Testing ","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","contextMap":{"delay":"0","name":"Ash 0"},"threadId":1,"threadPriority":5} 
{"timeMillis":1491819918504,"thread":"main","level":"INFO","loggerName":"com.ashraful.ilpexp.LogTest","message":"Testing ","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","contextMap":{"delay":"1","name":"Ash 1"},"threadId":1,"threadPriority":5} 
{"timeMillis":1491819918504,"thread":"main","level":"INFO","loggerName":"com.ashraful.ilpexp.LogTest","message":"Testing ","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","contextMap":{"delay":"2","name":"Ash 2"},"threadId":1,"threadPriority":5} 
{"timeMillis":1491819918505,"thread":"main","level":"INFO","loggerName":"com.ashraful.ilpexp.LogTest","message":"Testing ","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","contextMap":{"delay":"3","name":"Ash 3"},"threadId":1,"threadPriority":5} 
{"timeMillis":1491819918505,"thread":"main","level":"INFO","loggerName":"com.ashraful.ilpexp.LogTest","message":"Testing ","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","contextMap":{"delay":"4","name":"Ash 4"},"threadId":1,"threadPriority":5} 
0

試試這個:

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration> 
    <Appenders> 
     <Console name="STDOUT" target="SYSTEM_OUT"> 
      <PatternLayout pattern='{"@timestamp": %d{UNIX_MILLIS}, "delay"=%X{delay}, "name"="%X{name}"}%n'/> 
     </Console> 
    </Appenders> 
    <Loggers> 
     <Root level="info"> 
      <AppenderRef ref="STDOUT"/> 
     </Root> 
    </Loggers> 
</Configuration> 

Utils.java

public class Utils { 

    private static final Logger logger = LogManager.getLogger(); 

    public static void logMsg(long delay, String name) { 
    ThreadContext.put("delay", delay + ""); 
    ThreadContext.put("name", name); 
    logger.info(""); 
    } 
} 

輸出

{"@timestamp": 1491821218548, "delay"=1, "name"="hello"} 

UPDATE

其實,我更喜歡在代碼中直接建立日誌消息字符串。

例如

public static void logMsg(long delay, String name) { 
    String s = String.format("{\"@timestamp\":%s, \"delay\"=%s, \"name\"=\"%s\"}", System.currentTimeMillis(), delay, name); 
    logger.info(s); 
} 

注意:改變log4j2.xml圖案佈局,以

<PatternLayout pattern='%msg%n'/> 
+0

你的第二個例子不適用於你的第一個配置,在這種情況下,應該看起來像'patern =% m%n'我猜。 – LetsPlayYahtzee

+0

是的,我只想盡可能簡單地回答我的答案。 – wangyuntao