1. 程式人生 > 實用技巧 >Logstash結合log4j收集tomcat日誌

Logstash結合log4j收集tomcat日誌

https://www.kancloud.cn/hanxt/elk/158471

翻譯,原文地址:https://blog.lanyonm.org/articles/2015/12/29/log-aggregation-log4j-spring-logstash.html

解析原始日誌檔案是Logstash攝取資料的好方法,有好幾種方法可以將同樣的資訊轉送到Logstash。選擇這些方法需要做一下權衡,它們或多或少只適合特定的場景。之前我已經發布了關於多行的tomcat日誌解析,這篇博文是嘗試比較它和一些其他的方法:log4j-JSON格式,log4j-TCP 和 原始的log4j的多行編解碼器。

這些例子是在一臺機器上開發的,但設計目的是使您的ELK棧執行在不同的機器/例項/容器上。在多機環境Filebeat(原logstash-forwarder)將在使用檔案輸入的情況下使用。

下面是這次測試中,使用到的軟體版本

  • Java 7u67
  • Spring 4.2.3
  • Logstash 2.1.0
  • Elasticsearch 2.1.1
  • Kibana 4.3.1

我第一次開始創作這篇博文是在,2014年11月28日,所以請原諒有些選項可能不再好用。此外,你會發現,SLF4J被用作一個log4j的抽象在程式碼示例中使用。

Log4j As JSON

這種方法用於JSON格式的log4j日誌,然後用Logstash的檔案輸入一個JSON編解碼器攝取資料。這將使用避免不必要的解析和執行緒不安全多行過濾器。Seeing json-formatted logs can be jarring for a Java dev (no pun intended), but reading individual log files should be a thing of the past once you’re up and running with log aggregation.如果您有足夠的磁碟空間,你可以執行兩個並聯的追加程式。

比起使用複雜的PatternLayout,讓我們一起來看看log4j-jsonevent-layou。一個完全基於配置的符合需求的解決方案。

pom.xml中包含如下的依賴項:

<dependency>
    <groupId>net.logstash.log4j</groupId>
    <artifactId>jsonevent-layout</artifactId>
    <version>1.7</version>
</dependency>

log4j.properties 看起來很熟悉

log4j.rootLogger=debug,json

log4j.appender.json=org.apache.log4j.DailyRollingFileAppender
log4j.appender.json.File=target/app.log
log4j.appender.json.DatePattern=.yyyy-MM-dd
log4j.appender.json.layout=net.logstash.log4j.JSONEventLayoutV1
log4j.appender.json.layout.UserFields=application:playground,environment:dev

Logstash的配置如你所想:

input {
  file {
    codec => json
    type => "log4j-json"
    path => "/path/to/target/app.log"
  }
}
output {
  stdout {}
}

The values set in the UserFields are important because they allow the additional log metadata (taxonomy) to be set in the application configuration. This is information about the application and environment that will allow the log aggregation system to categorize the data. Because we’re using the file input plugin we could also use add_field, but this would require separate file plugins statements for every application. Certainly possible, but even with configuration management more of a headache than the alternative. Also, the path parameter of the file plugin is an array so we can specify multiple files with ease.

如果所有的事情都做對, 在kibana中的log資訊應該如下所示:

A log message from Playground using log4j-jsonevent-layout
As you can see, the UserFields are parsed into Logstash fields. If you prefer these values to be set via command line and environment variable, the library provides a way that will override anything set in the log4j.properties.

Log4j over TCP

這種方法使用log4j的SocketAppender和Logstash的log4j input。日誌事件被轉換成可經由SocketAppender二進位制格式並傳輸到log4j input。這裡的好處是,新的Log4j追加可無需額外的依賴,而且我們能夠避免處理額外的多行過濾器。在深入挖掘這種方法的缺點之前,讓我們來看看它如何實現。

這裡的log4j.properties的一個片段:

log4j.rootLogger=debug,tcp

log4j.appender.tcp=org.apache.log4j.net.SocketAppender
log4j.appender.tcp.Port=3456
log4j.appender.tcp.RemoteHost=localhost
log4j.appender.tcp.ReconnectionDelay=10000
log4j.appender.tcp.Application=playground

對應的 Logstash配置片段如:

input {
  log4j {
    mode => "server"
    host => "0.0.0.0"
    port => 3456
    type => "log4j"
  }
}
output {
  stdout {}
}

採用上面的log4j的配置,你將無法看到日誌的application欄位。當此引數被設定,Logstash將它解析為一個event欄位。這是非常方便的,但它無法滿足你進行日誌分類- 揭露這種方法的缺點之一:用application和環境識別資訊對日誌事件打標籤。在Logstash配置時需要使用一個輸入外掛add_field。這種做法將意味著對於每一個Java應用程式,將傳送日誌到不同的輸入 外掛/埠 - 對於擴充套件應用來說,這真的不好玩!

對映診斷上下文(Mapped Diagnostic Context)

對映診斷上下文(MDC)提供了一種方法,通過設定一組你感興趣的資訊的map鍵值對,來豐富標準日誌資訊。值得慶幸的是log4j的外掛將解析MDC到日誌事件欄位中。MDC在每個執行緒中單獨管理,但是子執行緒自動繼承父執行緒的MDC的副本。這意味著日誌分類可以在應用程式的主執行緒設定為MDC,並影響其整個生命週期的每個日誌宣告。

下面是一個簡單的例子:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class LoggingTaxonomy {

    private static final Logger log = LoggerFactory.getLogger(LoggingTaxonomy.class);

    static public void main(String[] args) {
        MDC.put("environment", System.getenv("APP_ENV"));
        // run the app
        log.debug("the app is running!");
    }
}

一個樣式如%d{ABSOLUTE} %5p %c{1}:%L - %X{environment} - %m%n的PatternLayout,並且設定APP_ENV為dev,你將看到如下輸出:

15:23:03,698 DEBUG LoggingTaxonomy:34 - dev - the app is running!

在何時何地整合MDC很大程度上決定於你的應用使用的框架。但是我曾經用過的每一個框架都有一個地方可以設定這個資訊。在Spring MVC中,可以放在應用初始化方法中。

如果所有的事情都做對, 在kibana中的log資訊應該如下所示:

使用這種方法需要注意幾個事情:

    • The logging level is stored in priority, not level as is with log4j-jsonevent-layout
    • 沒有 source_host 欄位, 所以你需要通過MDC方式自行新增