Stormにおける標準のログファイル出力機構についてのメモ。
基本ルール
-
Stormではlog出力機構としてはslf4j+logbackが利用されている。
- logback自身がローテーションおよび消し込みをしてくれる。
- Stormでは性能面を考えて
FixedWindowRollingPolicy
(Size100MB毎)を 利用している。
<configuration scan="true" scanPeriod="60 seconds">
<appender name="A1" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/storm/${logfile.name}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/storm/${logfile.name}-%d{yyyy-MM-dd}.%i</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>1MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>9</maxHistory>
</rollingPolicy>
<!--
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>/var/log/storm/${logfile.name}.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>9</maxIndex>
</rollingPolicy>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
</rollingPolicy>
-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n</pattern>
</encoder>
</appender>
- この場合、
nimbus.log-2014-08-07.1
のような名前でローテーションする。 -
maxHistory
は日数でカウントされ、同日中にサイズ起因でファイル数がmaxHistory
を越えても消されるわけではない。 - 大抵のまともなシステムの場合、何日間分は保存するみたいなシステム仕様があったりするので上記設定だと力不足かも。
access.log
backtype.storm.security.auth.authorizer
パッケージ配下のクラスが出すログが出力されるファイル。
このパッケージは0.9.2-incubatingでは利用されていないがcluster.xml
に設定があるため0バイトのファイルができる。
(現在、stormのsecurity機能が活発に開発されているのでそのあたりで使うのかトポロジ側から使うものなのかはちゃんと調べていない。)
nimbus.log
nimbusのログ。stormコマンド中に-Dlogfile.name=nimbus.log
とハードコードされているためこの名前になる。
変更はstormコマンドをいじらないと綺麗にはできない。おなくじ、logbackの設定ファイル名も同様にコマンド中にハードコードされているので変更はやや難しい。
あまり変えたくなることも無いのでいいか、という感じ。
supervisor.log, ui.log, drpc.log
nimbusと同様。
worker-(port番号).log
supervisor.cljの中から起動される際にコード中の文字列リテラルで指定されるため名前は変更不可。
(defmethod launch-worker
:distributed [supervisor storm-id port worker-id]
(let [conf (:conf supervisor)
storm-home (System/getProperty "storm.home")
stormroot (supervisor-stormdist-root conf storm-id)
jlp (jlp stormroot conf)
stormjar (supervisor-stormjar-path stormroot)
storm-conf (read-supervisor-storm-conf conf storm-id)
classpath (add-to-classpath (current-classpath) [stormjar])
worker-childopts (when-let [s (conf WORKER-CHILDOPTS)]
(substitute-worker-childopts s port))
topo-worker-childopts (when-let [s (storm-conf TOPOLOGY-WORKER-CHILDOPTS)]
(substitute-worker-childopts s port))
logfilename (str "worker-" port ".log") <- ここ
command (concat
[(java-cmd) "-server"]
worker-childopts
topo-worker-childopts
[(str "-Djava.library.path=" jlp)
(str "-Dlogfile.name=" logfilename)
(str "-Dstorm.home=" storm-home)
(str "-Dlogback.configurationFile=" storm-home "/logback/cluster.xml")
(str "-Dstorm.id=" storm-id)
(str "-Dworker.id=" worker-id)
(str "-Dworker.port=" port)
"-cp" classpath
"backtype.storm.daemon.worker"
storm-id
(:assignment-id supervisor)
port
worker-id])
command (->> command (map str) (filter (complement empty?)))
shell-cmd (->> command
(map #(str \' (clojure.string/escape % {\' "\\'"}) \'))
(clojure.string/join " "))]
(log-message "Launching worker with command: " shell-cmd)
(launch-process command :environment {"LD_LIBRARY_PATH" jlp})
))
ただし、worker.childopts
やtopology.worker.childopts
プロパティに記載された%ID%という文字列はworkerのポート番号に自動的に差し替えをしてくれる。
(defn- substitute-worker-childopts [value port]
(let [sub-fn (fn [s] (.replaceAll s "%ID%" (str port)))]
(if (list? value)
(map sub-fn value)
(-> value sub-fn (.split " ")))))
nimbus.out, supervisor.out, ui.out, drpc.out
これらのファイルはlogback経由で出力されるわけではなく、デーモンプロセス自体の標準出力である点に注意。
stormプロジェクトは/etc/init.d
配下のスタートストップスクリプト等は配布していないので自分でnohup
コマンド等を利用して必要に応じて取る必要がある。
もちろん、ローテーションや消し込みも自分で実装する必要あり。
stormのスタートストップスクリプトを配布している人もチラホラいるようなのでそこから取ってくれば楽かも。
worker-(port番号).gc
workerはsupervisorプロセスが内部で起動するので -Xloggc:filename
等のJVMオプションをworker.childoptsプロパティ等に指定してできる範囲のログ保存しかできない。
port番号の部分は、worker-(port番号).logと同様に%ID%という文字を使って差し替えると良い。