ログを Datadog に送信するには、ファイルにログを記録し、そのファイルを Datadog Agent で tail します。
一般的な Java ログのスタックトレースは複数の行に分割されているため、元のログイベントに関連付けることが困難です。例:
//1 つのはずのイベントに、4 つのイベントが生成される
Exception in thread "main" java . lang . NullPointerException
at com . example . myproject . Book . getTitle ( Book . java : 16 )
at com . example . myproject . Author . getBookTitles ( Author . java : 25 )
at com . example . myproject . Bootstrap . main ( Bootstrap . java : 14 )
この問題を解決するには、ログを JSON 形式で生成するようにログライブラリを構成します。JSON にログすると、次のことができます。
スタックトレースがログイベントに適切にラップされることを確実にします。 すべてのログイベント属性 (重大度、ロガー名、スレッド名など) が適切に抽出されることを確実にします。 マップされた診断コンテキスト (MDC) 属性にアクセスできます。この属性は、任意のログイベントにアタッチできます。カスタムパースルール が不要になります。次の手順は、Log4j、Log4j 2、および Logback ログライブラリのセットアップ例を示しています。
ロガーの構成 JSON 形式 Log4j の場合、SLF4J モジュール log4j-over-slf4j を Logback と組み合わせて使用して JSON 形式でログします。log4j-over-slf4j
は、アプリケーションの Log4j を完全に置き換えるため、コードを変更する必要はありません。
pom.xml
ファイルで、log4j.jar
依存関係を log4j-over-slf4j.jar
依存関係に置き換え、Logback 依存関係を追加します。例:
<dependency>
<groupId> org.slf4j</groupId>
<artifactId> log4j-over-slf4j</artifactId>
<version> 1.7.32</version>
</dependency>
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId> logback-classic</artifactId>
<version> 1.2.9</version>
</dependency>
<dependency>
<groupId> net.logstash.logback</groupId>
<artifactId> logstash-logback-encoder</artifactId>
<version> 6.6</version>
</dependency>
logback.xml
で JSON レイアウトを使用するアペンダーを構成してください。ファイルとコンソール向けのサンプル構成は以下を参照してください。
ファイル:
<configuration>
<appender name= "FILE" class= "ch.qos.logback.core.FileAppender" >
<file> logs/app.log</file>
<encoder class= "net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level= "INFO" >
<appender-ref ref= "FILE" />
</root>
</configuration>
コンソール:
<configuration>
<appender name= "CONSOLE" class= "ch.qos.logback.core.ConsoleAppender" >
<encoder class= "ch.qos.logback.classic.encoder.JsonEncoder" />
</appender>
<root>
<level value= "DEBUG" />
<appender-ref ref= "CONSOLE" />
</root>
</configuration>
Log4j 2 には JSON レイアウトが含まれています。
log4j2.xml
で JSON レイアウトを使用するアペンダーを構成してください。ファイルおよびコンソールアペンダー向けのサンプル構成は以下を参照してください。Log4j プラグインのより詳細な説明については、Log4j Plugin リファレンス をご覧ください。Copy
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name= "FILE" fileName= "logs/app.log" >
<JsonTemplateLayout eventTemplateUri= "classpath:MyLayout.json" />
</File>
</Appenders>
<Loggers>
<Root level= "INFO" >
<AppenderRef ref= "FILE" />
</Root>
</Loggers>
</Configuration>
Copy
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name= "console" target= "SYSTEM_OUT" >
<JsonTemplateLayout eventTemplateUri= "classpath:MyLayout.json" />
</Console>
</Appenders>
<Loggers>
<Root level= "INFO" >
<AppenderRef ref= "console" />
</Root>
</Loggers>
</Configuration>
JSON レイアウトの依存関係を pom.xml
に追加します。例:<dependency>
<groupId> org.apache.logging.log4j</groupId>
<artifactId> log4j-core</artifactId>
<version> 2.17.1</version>
</dependency>
<dependency>
<groupId> com.fasterxml.jackson.core</groupId>
<artifactId> jackson-core</artifactId>
<version> 2.13.0</version>
</dependency>
<dependency>
<groupId> com.fasterxml.jackson.core</groupId>
<artifactId> jackson-databind</artifactId>
<version> 2.13.0</version>
</dependency>
<dependency>
<groupId> com.fasterxml.jackson.core</groupId>
<artifactId> jackson-annotations</artifactId>
<version> 2.13.0</version>
</dependency>
Logback の JSON 形式のログには、logstash-logback-encoder を使用します。
logback.xml
の JSON レイアウトを使用してファイルアペンダーを構成します。例:
<configuration>
<appender name= "FILE" class= "ch.qos.logback.core.FileAppender" >
<file> logs/app.log</file>
<encoder class= "net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level= "INFO" >
<appender-ref ref= "FILE" />
</root>
</configuration>
Logstash エンコーダの依存関係を pom.xml
ファイルに追加します。例:
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId> logback-classic</artifactId>
<version> 1.2.9</version>
</dependency>
<dependency>
<groupId> net.logstash.logback</groupId>
<artifactId> logstash-logback-encoder</artifactId>
<version> 6.6</version>
</dependency>
Tinylog 公式ドキュメント に基づいて、JSON ライターの構成を作成します。
tinylog.properties
ファイルでは次の形式を使用してください。
writer = json
writer.file = log.json
writer.format = LDJSON
writer.level = info
writer.field.level = level
writer.field.source = {class}.{method}()
writer.field.message = {message}
writer.field.dd.trace_id = {context: dd.trace_id}
writer.field.dd.span_id = {context: dd.span_id}
writer.field.dd.service = {context: dd.service}
writer.field.dd.version = {context: dd.version}
writer.field.dd.env = {context: dd.env}
ログへのトレース ID の挿入 このアプリケーションで APM が有効になっている場合は、トレース ID インジェクションを有効にすることで、ログとトレースを相互に関連付けることができます。詳細については、Java ログとトレースの接続 を参照してください。
未加工の形式 log4j.xml
でファイルアペンダーを構成します。例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender name= "FILE" class= "org.apache.log4j.FileAppender" >
<param name= "File" value= "logs/app.log" />
<param name= "Append" value= "true" />
<layout class= "org.apache.log4j.PatternLayout" >
<param name= "ConversionPattern" value= "%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %X{dd.trace_id} %X{dd.span_id} - %m%n" />
</layout>
</appender>
<root>
<priority value= "INFO" />
<appender-ref ref= "FILE" />
</root>
</log4j:configuration>
log4j2.xml
でファイルアペンダーを構成します。例:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name= "FILE" fileName= "logs/app.log" >
<PatternLayout pattern= "%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %X{dd.trace_id} %X{dd.span_id} - %m%n" />
</File>
</Appenders>
<Loggers>
<Root level= "INFO" >
<AppenderRef ref= "FILE" />
</Root>
</Loggers>
</Configuration>
logback.xml
でファイルアペンダーを構成します。例:
<configuration>
<appender name= "FILE" class= "ch.qos.logback.core.FileAppender" >
<file> ${dd.test.logfile}</file>
<append> false</append>
<immediateFlush> true</immediateFlush>
<encoder>
<pattern> %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %X{dd.trace_id} %X{dd.span_id} - %m%n</pattern>
</encoder>
</appender>
<root level= "INFO" >
<appender-ref ref= "FILE" />
</root>
</configuration>
公式 Tinylog ドキュメント に基づき、ファイルへ出力するためのライター構成を作成してください。
tinylog.properties
ファイルでは以下の形式を使用してください。
writer = file
writer.level = debug
writer.format = {level} - {message} - "dd.trace_id":{context: dd.trace_id} - "dd.span_id":{context: dd.span_id}
writer.file = log.txt
ログへのトレース ID の挿入 このアプリケーションで APM が有効になっている場合は、トレース ID インジェクションを有効にすることで、ログとトレースを相互に関連付けることができます。Java ログとトレースの接続 を参照してください。
ログとトレースを相関させていない場合は、上記の構成例に含まれているログパターンから MDC プレースホルダー (%X{dd.trace_id} %X{dd.span_id}
) を削除できます。
Datadog Agent の構成 ログ収集が有効 になったら、ログファイルを追跡して Datadog に送信するカスタムログ収集 を設定します。
java.d/
フォルダーを conf.d/
Agent 構成ディレクトリ に作成します。
java.d/
に以下の内容で conf.yaml
ファイルを作成します。
#Log section
logs :
- type : file
path : "<path_to_your_java_log>.log"
service : <service_name>
source : java
sourcecategory : sourcecode
# For multiline logs, if they start by the date with the format yyyy-mm-dd uncomment the following processing rule
#log_processing_rules:
# - type: multi_line
# name: new_log_start_with_date
# pattern: \d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])
Agent を再起動します 。
Agent の status サブコマンド を実行し、Checks
セクションで java
を探し、ログが Datadog に正常に送信されることを確認します。
ログが JSON 形式の場合、Datadog は自動的にログメッセージをパース し、ログ属性を抽出します。ログエクスプローラー を使用して、ログを表示し、トラブルシューティングを行うことができます。
エージェントレスのログ収集 アクセスできない、またはファイルにログを記録できないマシンでアプリケーションが実行されている例外的なケースでは、ログを Datadog または Datadog Agent に直接ストリーミングすることができます。アプリケーションが接続の問題を処理する必要があるため、これは推奨される設定ではありません。
ログを Datadog に直接ストリーミングするには
Logback ログライブラリをコードに追加するか、現在のロガーを Logback にブリッジ します。 Logback を構成 して Datadog にログを送信します。Java ロギングライブラリから Logback へのブリッジ まだ Logback を使用していない場合、ほとんどの一般的なログライブラリは Logback にブリッジすることができます。
SLF4J モジュール log4j-over-slf4j を Logback とともに使用して、ログを別のサーバーに送信します。log4j-over-slf4j
は、アプリケーションの Log4j を完全に置き換えるため、コードを変更する必要はありません。
pom.xml
ファイルで、log4j.jar
依存関係を log4j-over-slf4j.jar
依存関係に置き換え、Logback 依存関係を追加します。例:<dependency>
<groupId> org.slf4j</groupId>
<artifactId> log4j-over-slf4j</artifactId>
<version> 1.7.32</version>
</dependency>
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId> logback-classic</artifactId>
<version> 1.2.9</version>
</dependency>
<dependency>
<groupId> net.logstash.logback</groupId>
<artifactId> logstash-logback-encoder</artifactId>
<version> 6.6</version>
</dependency>
Logback を構成します。 注: この変更の結果、Log4j コンフィギュレーションファイルは使用されなくなります。Log4j トランスレーター を使用して log4j.properties
ファイルを logback.xml
に移行してください。
Log4j 2 では、リモートホストへのログ記録が可能ですが、ログの前に API キーを付ける機能はありません。このため、SLF4J モジュール log4j-over-slf4j と Logback を使用してください。log4j-to-slf4j.jar
は、アプリケーションの Log4j 2 を完全に置き換えるため、コードを変更する必要はありません。これを使用するには
pom.xml
ファイルで、log4j.jar
依存関係を log4j-over-slf4j.jar
依存関係に置き換え、Logback 依存関係を追加します。例:<dependency>
<groupId> org.apache.logging.log4j</groupId>
<artifactId> log4j-to-slf4j</artifactId>
<version> 2.17.1</version>
</dependency>
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId> logback-classic</artifactId>
<version> 1.2.9</version>
</dependency>
<dependency>
<groupId> net.logstash.logback</groupId>
<artifactId> logstash-logback-encoder</artifactId>
<version> 6.6</version>
</dependency>
Logback を構成します。 注:
Logback を構成する
logstash-logback-encoder ログライブラリを Logback と一緒に使用して、ログを Datadog に直接ストリーミングします。
logback.xml
ファイルに TCP アペンダーを構成します。この構成では、API キーは環境変数 DD_API_KEY
から取得されます。あるいは、コンフィギュレーションファイルに直接 API キーを挿入することもできます。
以下の構成を使用する際は、<YOUR REGION INTAKE>
をご利用の地域に応じたインテーク (
) に置き換えてください。
US1 : intake.logs.datadoghq.com:10516
EU : tcp-intake.logs.datadoghq.eu:443
<configuration>
<appender name= "FILE" class= "ch.qos.logback.core.FileAppender" >
<file> logs/app.log</file>
<encoder class= "net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<appender name= "JSON_TCP" class= "net.logstash.logback.appender.LogstashTcpSocketAppender" >
<destination><YOUR REGION INTAKE ></destination>
<keepAliveDuration> 20 seconds</keepAliveDuration>
<encoder class= "net.logstash.logback.encoder.LogstashEncoder" >
<prefix class= "ch.qos.logback.core.encoder.LayoutWrappingEncoder" >
<layout class= "ch.qos.logback.classic.PatternLayout" >
<pattern> ${DD_API_KEY} %mdc{keyThatDoesNotExist}</pattern>
</layout>
</prefix>
</encoder>
<ssl />
</appender>
<root level= "DEBUG" >
<appender-ref ref= "FILE" />
<appender-ref ref= "JSON_TCP" />
</root>
</configuration>
注: XML コンフィギュレーションで空白が削除されるため、%mdc{keyThatDoesNotExist}
が追加されます。プレフィックスパラメータの詳細については、Logback ドキュメント を参照してください。
Logstash エンコーダの依存関係を pom.xml
ファイルに追加します。例:
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId> logback-classic</artifactId>
<version> 1.2.9</version>
</dependency>
<dependency>
<groupId> net.logstash.logback</groupId>
<artifactId> logstash-logback-encoder</artifactId>
<version> 6.6</version>
</dependency>
補足説明 ログイベントをコンテキスト属性で補完することができます。
キー値パーサーの使用 キー値パーサー は、ログイベント内で認識された <KEY>=<VALUE>
パターンを抽出します。
Java のログイベントを補完するには、コードでメッセージを書き直し、<キー>=<値>
のシーケンスを挿入します。
たとえば、次のメッセージがあるとします。
logger . info ( "Emitted 1001 messages during the last 93 seconds for customer scope prod30" );
これを次のように変更します。
logger . info ( "Emitted quantity=1001 messages during the last durationInMs=93180 ms for customer scope=prod30" );
キー値パーサーを有効にすると、各ペアが JSON から抽出されます。
{
"message" : "Emitted quantity=1001 messages during the last durationInMs=93180 ms for customer scope=prod30" ,
"scope" : "prod30" ,
"durationInMs" : 93180 ,
"quantity" : 1001
}
これで、scope をフィールド、durationInMs と quantity をログメジャーとして利用できます。
MDC ログを補完するもう 1 つの方法として、Java の マップされた診断コンテキスト (MDC) の利用があります。
SLF4J を使用する場合は、次の Java コードを使用してください。
...
MDC . put ( "scope" , "prod30" );
logger . info ( "Emitted 1001 messages during the last 93 seconds" );
...
この JSON を生成するには
{
"message" : "過去 93 秒間に 1001 メッセージを送信" ,
"scope" : "prod30"
}
注 : MDC は文字列タイプのみを許可するため、数値メトリクスには使用しないでください。
その他の参考資料