読者です 読者をやめる 読者になる 読者になる

Log4j 2 の SyslogAppender で syslog メッセージを送信する

Log4j 2 の SyslogAppender で syslog メッセージを送信するってことをやってみました。その時のメモです。

Log4jLog4j 2 Appenders - Apache Log4j 2
- SyslogAppender
http://logging.apache.org/log4j/2.x/manual/appenders.html#SyslogAppender

■ syslog の設定

ひとまず、syslog ( rsyslog ですが、、、 ) 側の設定から。/etc/rsyslog.conf を下記の通り修正しておきます。

■ /etc/rsyslog.conf

# 以下をコメントアウトする
$ModLoad imudp.so
$UDPServerRun 514

# 以下を追記する
local0.* /var/log/local0.log

設定を反映するために rsyslog を再起動しておきます。

# service rsyslog restart
システムロガーを停止中:                                    [  OK  ]
システムロガーを起動中:                                    [  OK  ]

念のため、netstat で 514 ポートが LISTEN しているかも確認しておきます。

# netstat -an | grep 514  
udp        0      0 0.0.0.0:514                 0.0.0.0:*                               
udp        0      0 :::514                      :::*     


Log4j 2 の設定、コード

次に、Log4j 2 側の設定ファイル、コードの作成です。

■ log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Syslog name="syslog" host="***.***.***.***" port="514" protocol="UDP"/>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="syslog"/>
    </Root>
  </Loggers>
</Configuration>

■ Log4j2SyslogTest.java

package test.syslog;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2SyslogTest {
  private static final Logger logger = LogManager.getLogger(Log4j2SyslogTest.class);
  
  public static void main(String[] args) {
    logger.info("syslog test !!");
  }
}


やることは以上になります。あとは、Log4j2SyslogTest.java を実行すると /var/log/local0.log に以下のようなログが出力されるはずです。

Jan 28 00:18:29 *****-PC syslog test !!


(*) 備考

ちょっと備考を。Log4j の SyslogAppender では Log4j 1.x ではできなかったメッセージのエンコーディングを任意に指定が可能な charset なるパラメータが用意されています。ただ、こいつは format パラメータに "RFC5424" を指定しなかった場合のみ有効なパラメータっぽいです。

SyslogAppernder.java のコードを見ると format パラメータが "RFC5424" なら Rfc5424Layout が使われますが、こいつに charset パラメータの値が渡されてません ( "RFC5424" じゃなければ SyslogLayout が使われて、こいつには charset パラメータが渡されてます )。

    @PluginFactory
    public static SyslogAppender createAppender(
 ・・・略 ・・・
    @PluginAttribute("format") final String format,
 ・・・略 ・・・
    @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName,
 ・・・略 ・・・
  final Layout<? extends Serializable> layout = RFC5424.equalsIgnoreCase(format) ?
            Rfc5424Layout.createLayout(facility, id, enterpriseNumber, includeMdc, mdcId, mdcPrefix, eventPrefix, newLine,
                escapeNL, appName, msgId, excludes, includes, required, exceptionPattern, useTlsMessageFormat, loggerFields,
                config) :
            SyslogLayout.createLayout(facility, newLine, escapeNL, charsetName);

で、Rfc5424Layout.java のコードを見ると StandardCharsets.UTF_8 みたいな感じで UTF-8 でハードコードされてる感じです。

    @PluginFactory
    public static Rfc5424Layout createLayout(
 ・・・略 ・・・
    return new Rfc5424Layout(config, facility, id, enterpriseNumber, includeMDC, newLine, escapeNL, mdcId,
                mdcPrefix, eventPrefix, appName, msgId, excludes, includes, required, StandardCharsets.UTF_8,
                exceptionPattern, useTlsMessageFormat, loggerFields);

おそらく RFC の以下の記載を踏まえた実装になっているということかと思われます。

RFC 5424 - The Syslog Protocol
- 6.3. STRUCTURED-DATA
https://tools.ietf.org/html/rfc5424#section-6.3

An exception is the PARAM-VALUE field (see Section 6.3.3), in which UTF-8 encoding MUST be used.


以上です。

[ 環境情報 ]
Windows 7 SP1
Java SE 8 Update 25
Log4j 2.5