ใƒญใ‚ฐใ‚’ 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 ใ‚’ๆง‹ๆˆใ—ใพใ™ใ€‚

ๆณจ:

  • https://logging.apache.org/log4j/log4j-2.2/log4j-to-slf4j/index.html ใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซใ€log4j-slf4j-impl.jar ใŒไฝฟ็”จใ•ใ‚Œใฆใ„ใชใ„ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚
  • ใ“ใฎ็งป่กŒใฎ็ตๆžœใ€Log4j 2 ใ‚ณใƒณใƒ•ใ‚ฃใ‚ฎใƒฅใƒฌใƒผใ‚ทใƒงใƒณใƒ•ใ‚กใ‚คใƒซใฏไฝฟ็”จใ•ใ‚Œใชใใชใ‚Šใพใ™ใ€‚Log4j ใƒˆใƒฉใƒณใ‚นใƒฌใƒผใ‚ฟใƒผ ใ‚’ไฝฟ็”จใ—ใฆ log4j.properties ใƒ•ใ‚กใ‚คใƒซใ‚’ logback.xml ใซ็งป่กŒใ—ใฆใใ ใ•ใ„ใ€‚

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 ใฏๆ–‡ๅญ—ๅˆ—ใ‚ฟใ‚คใƒ—ใฎใฟใ‚’่จฑๅฏใ™ใ‚‹ใŸใ‚ใ€ๆ•ฐๅ€คใƒกใƒˆใƒชใ‚ฏใ‚นใซใฏไฝฟ็”จใ—ใชใ„ใงใใ ใ•ใ„ใ€‚

ใใฎไป–ใฎๅ‚่€ƒ่ณ‡ๆ–™