ログを 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 を完全に置き換えるため、コードを変更する必要はありません。

  1. 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> 
  2. 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 レイアウトが含まれています。

  1. log4j2.xml で JSON レイアウトを使用するアペンダーを構成してください。ファイルおよびコンソールアペンダー向けのサンプル構成は以下を参照してください。Log4j プラグインのより詳細な説明については、Log4j Plugin リファレンスをご覧ください。

log4j2.xml

<?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>

log4j2.xml

  <?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>
  1. 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 を使用します。

  1. 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> 
  2. 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 に送信するカスタムログ収集を設定します。

  1. java.d/ フォルダーを conf.d/ Agent 構成ディレクトリに作成します。

  2. 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]) 
  3. Agent を再起動します

  4. Agent の status サブコマンドを実行し、Checks セクションで java を探し、ログが Datadog に正常に送信されることを確認します。

ログが JSON 形式の場合、Datadog は自動的にログメッセージをパースし、ログ属性を抽出します。ログエクスプローラーを使用して、ログを表示し、トラブルシューティングを行うことができます。

エージェントレスのログ収集

アクセスできない、またはファイルにログを記録できないマシンでアプリケーションが実行されている例外的なケースでは、ログを Datadog または Datadog Agent に直接ストリーミングすることができます。アプリケーションが接続の問題を処理する必要があるため、これは推奨される設定ではありません。

ログを Datadog に直接ストリーミングするには

  1. Logback ログライブラリをコードに追加するか、現在のロガーを Logback にブリッジします。
  2. Logback を構成して Datadog にログを送信します。

Java ロギングライブラリから Logback へのブリッジ

まだ Logback を使用していない場合、ほとんどの一般的なログライブラリは Logback にブリッジすることができます。

SLF4J モジュール log4j-over-slf4j を Logback とともに使用して、ログを別のサーバーに送信します。log4j-over-slf4j は、アプリケーションの Log4j を完全に置き換えるため、コードを変更する必要はありません。

  1. 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> 
  2. Logback を構成します。

注: この変更の結果、Log4j コンフィギュレーションファイルは使用されなくなります。Log4j トランスレーター を使用して log4j.properties ファイルを logback.xml に移行してください。

Log4j 2 では、リモートホストへのログ記録が可能ですが、ログの前に API キーを付ける機能はありません。このため、SLF4J モジュール log4j-over-slf4j と Logback を使用してください。log4j-to-slf4j.jar は、アプリケーションの Log4j 2 を完全に置き換えるため、コードを変更する必要はありません。これを使用するには

  1. 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> 
  2. Logback を構成します。

注:

Logback を構成する

選択した Datadog サイト () では、TCP エンドポイントはサポートされていません。ロギングエンドポイントのリストについては、ログ収集とインテグレーションをご覧ください。

logstash-logback-encoder ログライブラリを Logback と一緒に使用して、ログを Datadog に直接ストリーミングします。

  1. 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 ドキュメントを参照してください。

  2. 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 は文字列タイプのみを許可するため、数値メトリクスには使用しないでください。

その他の参考資料