web-dev-qa-db-ja.com

logback auto-load logback.xmlの前にログバック変数/プロパティを定義する方法は?

私の会社には、Javaでプログラムで環境からプロパティを検索できる環境管理ツールがあります。このツールを活用して、ログバックを構成したいと思います。たとえば、次のようなlogback.xmlがあるとします(特にファイルアペンダーセクション)。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- console appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd/HH:mm:ss.SSS} [%thread] %-5level %logger{20}: %msg%n</pattern>
        </encoder>
    </appender>

    <!-- file appender -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${LOG_FILE:-/default/log/file/path</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd/HH:mm:ss.SSS} [%thread] %-5level %logger{20}: %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
</configuration>

したがって、この場合、LOG_FILEプロパティを環境(またはOS)から取得し、logbackがlogback.xmlを読み込む前にlogbackに渡して、LOG_FILE。それで、どうすればそれを達成できますか?ところで、私はプログラムでファイルアペンダーを定義する方法を知っていますが、それはここで欲しいものではありません。

どうもありがとうございました。

23
JBT

かなり頭をかいた後、私は次の解決策で落ち着いています。

まず、logbackが自動的に何もロードしないように、logback.xmlをクラスパスの外側に配置します。

次に、環境の設定をシステムプロパティに追加し、logback.xmlの解析時にlogbackがそれらを検索できるようにします。

第三に、アプリケーションコードでログバックをプログラムで構成します。 (公式のログバックドキュメントには 1つの素敵な例 があります。)

できた.

11
JBT

プロパティの定義 in logback.xmlそして、それを「コンテキスト」にロードします。

<property scope="context" name="logfolder" value="${location.of.the.log.folder}" />

次に、プロパティを参照するアペンダーを定義します。

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${logfolder}/logfile.log</file>
    <append>true</append>
    <encoder>
        <pattern>[%d{ISO8601}] [%p] [%t] [%c] [%m]%n</pattern>
    </encoder>
</appender>

ドキュメント から:

コンテキストスコープを持つプロパティはコンテキストに挿入され、コンテキストが続く限り、またはクリアされるまで続きます。定義されると、コンテキストスコープのプロパティはコンテキストの一部になります。そのため、シリアル化を介してリモートホストに送信されたイベントを含む、すべてのログイベントで使用できます。

したがって、「ローカル」であるデフォルトのスコープで十分かもしれません。

15

環境(または、必要に応じてOS)からLOG_FILEプロパティを検索したい

代替手段は次のとおりです。

  1. environment で、一般的に 環境変数 として知られているものを意味する場合、構成ファイルで直接 参照できます 多くの手間なし。

  2. 環境変数ではなく、アクセスするためにカスタムコードを必要とするものを意味する場合は、 カスタムch.qos.logback.core.spi.PropertyDefiner を実装して、値。

    例えば.

    public class MyCompanyEnvironmentGrabber extends PropertyDefinerBase {
    
        @Override
        public String getPropertyValue() {
            return ...; // grab the value from company environment
        }
    }
    
  3. 見かけ上 のレポートがあり、logback.xmlがロードされる前に、loggerへの呼び出しの前に変数を設定し、ClassLoaderのロード順序に注意して変数を設定できる...しかし、static loggerを使用しないと、コードベースが複雑になると制御が非常に難しくなるため、これは非常に脆弱だと思います。

logback.xmlはJavaインスタンスが開始された直後にロードされるため、変数に値を動的に設定する安全な方法は次のように制限されているようです。

  1. 環境変数またはシステムプロパティ(-D)を使用して、シェルスクリプトの呼び出しなどを介して、Javaプログラムの外部で設定).
  2. ch.qos.logback.core.spi.PropertyDefinerコールバックを介してそれを返します。
  3. この回答で行ったようにch.qos.logback.classic.spi.LoggerContextListenerで設定 します
  4. OPが回答で行った方法としてのlogback.xmlのロードを人為的に遅らせます
10
antak