ドキュメント

§ロギングの設定

PlayはロギングにSLF4Jを使用し、デフォルトのロギングエンジンとしてLogbackをサポートしています。設定の詳細については、Logbackのドキュメントを参照してください。

§デフォルト設定

開発モードでは、Playは次のデフォルト設定を使用します

<?xml version="1.0" encoding="UTF-8" ?>
<!--
   Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
-->

<!DOCTYPE configuration>

<!-- The default logback configuration that Play uses in dev mode if no other configuration is provided -->
<configuration>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.core.ConsoleAppender"/>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%highlight(%-5level) %logger{15} - %message%n%xException{10}</pattern>
    </encoder>
  </appender>

  <logger name="play" level="INFO"/>
  <logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF"/>

  <root level="WARN">
    <appender-ref ref="STDOUT"/>
  </root>

</configuration>

本番環境では、Playは次のデフォルト設定を使用します

<?xml version="1.0" encoding="UTF-8" ?>
<!--
   Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
-->

<!DOCTYPE configuration>

<!-- The default logback configuration that Play uses if no other configuration is provided -->
<configuration>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.classic.AsyncAppender"/>
  <import class="ch.qos.logback.core.ConsoleAppender"/>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%highlight(%-5level) %logger{15} - %message%n%xException{10}</pattern>
    </encoder>
  </appender>

  <appender name="ASYNCSTDOUT" class="AsyncAppender">
    <!-- increases the default queue size -->
    <queueSize>512</queueSize>
    <!-- don't discard messages -->
    <discardingThreshold>0</discardingThreshold>
    <!-- block when queue is full -->
    <neverBlock>false</neverBlock>
    <appender-ref ref="STDOUT"/>
  </appender>

  <logger name="play" level="INFO"/>
  <logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF"/>

  <root level="WARN">
    <appender-ref ref="ASYNCSTDOUT"/>
  </root>

</configuration>

これらの設定に関する注意事項

ファイルロガーを追加するには、次のアペンダーをconf/logback.xmlファイルに追加します

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${application.home:-.}/logs/application.log</file>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
    </encoder>
</appender>

必要に応じて、非同期アペンダーを使用してFileAppenderをラップします

<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="FILE" />
</appender>

必要なアペンダーをルートに追加します

<root level="WARN">
    <appender-ref ref="ASYNCFILE" />
    <appender-ref ref="ASYNCSTDOUT" />
</root>

§セキュリティロギング

Playのセキュリティ関連操作のためにセキュリティマーカーが追加され、失敗したセキュリティチェックは、セキュリティマーカーが設定された状態でWARNレベルでログに記録されるようになりました。これにより、開発者は特定のリクエストが失敗した理由を常に把握できます。これは、Playでセキュリティフィルターがデフォルトで有効になっているため重要です。

セキュリティマーカーを使用すると、通常のロギングとは別にセキュリティ障害をトリガーまたはフィルターすることもできます。たとえば、SECURITYマーカーが設定されているすべてのロギングを無効にするには、次の行をlogback.xmlファイルに追加します

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    <Marker>SECURITY</Marker>
    <OnMatch>DENY</OnMatch>
</turboFilter>

さらに、セキュリティマーカーを使用したログイベントは、セキュリティ情報とイベント管理(SEIM)エンジンにメッセージをトリガーして、さらに処理することもできます。

§カスタムアプリケーションローダーの使用

デフォルトのGuiceApplicationLoaderを拡張しないカスタムアプリケーションローダーを使用する場合(たとえば、コンパイル時依存性注入を使用する場合)、カスタム設定を取得するためにLoggerConfiguratorを手動で呼び出す必要があります。これは、次のコードで実行できます

class MyApplicationLoaderWithInitialization extends ApplicationLoader {
  def load(context: Context) = {
    LoggerConfigurator(context.environment.classLoader).foreach {
      _.configure(context.environment, context.initialConfiguration, Map.empty)
    }
    new MyComponents(context).application
  }
}

§カスタム設定

カスタム設定を行うには、独自のLogback設定ファイルを指定する必要があります。

§プロジェクトソースからの設定ファイルの使用

conf/logback.xmlファイルを指定することで、デフォルトのロギング設定を提供できます。

§外部設定ファイルの使用

システムプロパティを介して設定ファイルを指定することもできます。これは、設定ファイルがアプリケーションソースの外部で管理される可能性のある本番環境で特に役立ちます。

:ロギングシステムは、システムプロパティで指定された設定ファイル、次にconfディレクトリ内のファイル、最後にデフォルトの設定ファイルを優先します。これにより、アプリケーションのロギング設定をカスタマイズし、特定の環境または開発者の設定でオーバーライドすることができます。

§-Dlogger.resourceの使用

クラスパスからロードする設定ファイルを指定します

$ start -Dlogger.resource=prod-logger.xml

§-Dlogger.fileの使用

ファイルシステムからロードする設定ファイルを指定します

$ start -Dlogger.file=/opt/prod/logger.xml

:使用されているファイルを確認するには、システムプロパティをデバッグ用に設定します:-Dlogback.debug=true

§

ローリングファイルアペンダーと、アクセスログを出力するための別のアペンダーを使用する設定の例を次に示します

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"/>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.core.rolling.RollingFileAppender"/>
  <import class="ch.qos.logback.core.filter.EvaluatorFilter"/>
  <import class="ch.qos.logback.core.FileAppender"/>
  <import class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"/>

  <appender name="FILE" class="RollingFileAppender">
    <file>${application.home:-.}/logs/application.log</file>
    <rollingPolicy class="TimeBasedRollingPolicy">
      <!-- Daily rollover with compression -->
      <fileNamePattern>${application.home:-.}/logs/application-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
      <!-- keep 30 days worth of history -->
      <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder class="PatternLayoutEncoder">
      <pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} [%level] from %logger in %thread - %message%n%xException</pattern>
    </encoder>
  </appender>

  <appender name="SECURITY_FILE" class="FileAppender">
    <filter class="EvaluatorFilter">
      <evaluator class="OnMarkerEvaluator">
        <marker>SECURITY</marker>
      </evaluator>
      <onMismatch>DENY</onMismatch>
      <onMatch>ACCEPT</onMatch>
    </filter>
    <file>${application.home:-.}/logs/security.log</file>
    <encoder class="PatternLayoutEncoder">
      <pattern>%date [%level] [%marker] from %logger in %thread - %message%n%xException</pattern>
    </encoder>
  </appender>

  <appender name="ACCESS_FILE" class="RollingFileAppender">
    <file>${application.home:-.}/logs/access.log</file>
    <rollingPolicy class="TimeBasedRollingPolicy">
      <!-- daily rollover with compression -->
      <fileNamePattern>${application.home:-.}/logs/access-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
      <!-- keep 1 week worth of history -->
      <maxHistory>7</maxHistory>
    </rollingPolicy>
    <encoder class="PatternLayoutEncoder">
      <pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} %message%n</pattern>
      <!-- this quadruples logging throughput -->
      <immediateFlush>false</immediateFlush>
    </encoder>
  </appender>

  <!-- additivity=false ensures access log data only goes to the access log -->
  <logger name="access" level="INFO" additivity="false">
    <appender-ref ref="ACCESS_FILE"/>
  </logger>

  <root level="INFO">
    <appender-ref ref="FILE"/>
    <appender-ref ref="SECURITY_FILE"/>
  </root>

</configuration>

これは、いくつかの便利な機能を示しています

fileタグは省略可能であり、ファイルの名前変更を避けたい場合は省略できます。詳細については、Logbackドキュメントを参照してください。

§プロパティのインクルード

デフォルトでは、プロパティapplication.homeのみがロギングフレームワークにエクスポートされます。つまり、ファイルはPlayアプリケーションを基準にして参照できます

 <file>${application.home:-}/example.log</file>

application.confファイルで定義されているプロパティを参照する場合は、application.confファイルにplay.logger.includeConfigProperties=trueを追加します。アプリケーションの起動時に、設定で定義されているすべてのプロパティがロガーで使用できるようになります

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>context = ${my.property.defined.in.application.conf} %message%n</pattern>
    </encoder>
</appender>

§Akkaロギング設定

Akkaシステムのロギングは、org.apache.pekkoロガーをINFOに変更することで実行できます。

<!-- Set logging for all Pekko library classes to INFO -->
<logger name="org.apache.pekko" level="INFO" />
<!-- Set a specific actor to DEBUG -->
<logger name="actors.MyActor" level="DEBUG" />

スレッドやアクターアドレスなどの有用なプロパティを含むAkkaロガーのアペンダーを設定することもできます。LogbackとSlf4jの統合の詳細を含む、Akkaのロギングの設定の詳細については、Akkaのドキュメントを参照してください。

§カスタムロギングフレームワークの使用

PlayはデフォルトでLogbackを使用しますが、SLF4Jアダプターがあれば、Playを別のロギングフレームワークを使用するように設定できます。これを行うには、disablePluginsを使用してPlayLogback sbtプラグインを無効にする必要があります

lazy val root = (project in file("."))
  .enablePlugins(PlayScala)
  .disablePlugins(PlayLogback)

そこから、カスタムロギングフレームワークを使用できます。ここでは、Log4J 2を例として使用します。

libraryDependencies ++= Seq(
  "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.19.0",
  "org.apache.logging.log4j" % "log4j-api" % "2.19.0",
  "org.apache.logging.log4j" % "log4j-core" % "2.19.0"
)

ライブラリとSLF4Jアダプターがロードされると、通常どおりコマンドラインでlog4j.configurationFileシステムプロパティを設定できます。

Playのモードに依存するカスタム設定が必要な場合は、LoggerConfiguratorを使用して追加のカスタマイズを行うことができます。これを行うには、logger-configurator.propertiesをクラスパスに追加します。

play.logger.configurator=Log4J2LoggerConfigurator

そして、LoggerConfiguratorをカスタマイズして拡張します

Java
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import play.Environment;
import play.LoggerConfigurator;
import play.Mode;
import play.api.PlayException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.config.Configurator;

public class JavaLog4JLoggerConfigurator implements LoggerConfigurator {

  private ILoggerFactory factory;

  @Override
  public void init(File rootPath, Mode mode) {
    Map<String, String> properties = new HashMap<>();
    properties.put("application.home", rootPath.getAbsolutePath());

    String resourceName = "log4j2.xml";
    URL resourceUrl = this.getClass().getClassLoader().getResource(resourceName);
    configure(properties, Optional.ofNullable(resourceUrl));
  }

  @Override
  public void configure(Environment env) {
    Map<String, String> properties =
        LoggerConfigurator.generateProperties(env, ConfigFactory.empty(), Collections.emptyMap());
    URL resourceUrl = env.resource("log4j2.xml");
    configure(properties, Optional.ofNullable(resourceUrl));
  }

  @Override
  public void configure(
      Environment env, Config configuration, Map<String, String> optionalProperties) {
    // LoggerConfigurator.generateProperties enables play.logger.includeConfigProperties=true
    Map<String, String> properties =
        LoggerConfigurator.generateProperties(env, configuration, optionalProperties);
    URL resourceUrl = env.resource("log4j2.xml");
    configure(properties, Optional.ofNullable(resourceUrl));
  }

  @Override
  public void configure(Map<String, String> properties, Optional<URL> config) {
    try {
      LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
      loggerContext.setConfigLocation(config.get().toURI());

      factory = LoggerFactory.getILoggerFactory();
    } catch (URISyntaxException ex) {
      throw new PlayException(
          "log4j2.xml resource was not found",
          "Could not parse the location for log4j2.xml resource",
          ex);
    }
  }

  @Override
  public ILoggerFactory loggerFactory() {
    return factory;
  }

  @Override
  public void shutdown() {
    LoggerContext loggerContext = (LoggerContext) LogManager.getContext();
    Configurator.shutdown(loggerContext);
  }
}
Scala
import java.io.File
import java.net.URI
import java.net.URL

import play.api.{Mode, Configuration, Environment, LoggerConfigurator}

import org.slf4j.ILoggerFactory

import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.core._
import org.apache.logging.log4j.core.config.Configurator

import org.slf4j.ILoggerFactory
import org.slf4j.LoggerFactory
import play.api.Configuration
import play.api.Environment
import play.api.LoggerConfigurator
import play.api.Mode

class Log4J2LoggerConfigurator extends LoggerConfigurator {
  private var factory: ILoggerFactory = _

  override def init(rootPath: File, mode: Mode): Unit = {
    val properties   = Map("application.home" -> rootPath.getAbsolutePath)
    val resourceName = "log4j2.xml"
    val resourceUrl  = Option(this.getClass.getClassLoader.getResource(resourceName))
    configure(properties, resourceUrl)
  }

  override def shutdown(): Unit = {
    val context = LogManager.getContext().asInstanceOf[LoggerContext]
    Configurator.shutdown(context)
  }

  override def configure(env: Environment): Unit = {
    val properties  = LoggerConfigurator.generateProperties(env, Configuration.empty, Map.empty)
    val resourceUrl = env.resource("log4j2.xml")
    configure(properties, resourceUrl)
  }

  override def configure(
      env: Environment,
      configuration: Configuration,
      optionalProperties: Map[String, String]
  ): Unit = {
    // LoggerConfigurator.generateProperties enables play.logger.includeConfigProperties=true
    val properties  = LoggerConfigurator.generateProperties(env, configuration, optionalProperties)
    val resourceUrl = env.resource("log4j2.xml")
    configure(properties, resourceUrl)
  }

  override def configure(properties: Map[String, String], config: Option[URL]): Unit = {
    val context = LogManager.getContext(false).asInstanceOf[LoggerContext]
    context.setConfigLocation(config.get.toURI)

    factory = LoggerFactory.getILoggerFactory
  }

  override def loggerFactory: ILoggerFactory = factory
}

次:WS SSLの設定


このドキュメントに誤りを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインをお読みいただいた後、プルリクエストを送信してください。質問やアドバイスがありましたら、コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。