2015/07/09(木)LogbackでプロセスIDを出力
2015/07/09 13:25 	
Java1.7 + logback-1.1.3
あまりいい方法が見つからなかったが、とりあえず出りゃいいやまではできた。
起動コマンドなりスクリプトなりがいじれるのなら、SystemProperty経由で設定・取得する方法が使える。
[起動コマンド]
exec java -Dpid=$$ -jar /foo/bar.jar[logback.xml]
<pattern>%d{yyyy/MM/dd HH:mm:ss} [${pid}] %level %msg%n</pattern>
 -Dpid=$$で、プロパティ:pidにプロセスIDをセット、patternに${pid}と記述してやるとlobackの機能で出力できる。もちろんUnix環境限定。
なお、シェル側のプロセスIDがほしい場合は、execを外し直接javaコマンドをたたく。
java -Dpid=$$ -jar /foo/bar.jarWebアプリケーションで動いている場合は、何がしかプロセスIDに相当するものがSystemPropertyにいると思うので${}でそれを拾えばいい(はず)。
本当なら、ManagementFactory.getRuntimeMXBean()で取得するのが正解のようだが、その場合PatternLayoutをカスタムしてコンバータをいじって… とやらなければいけない気がする。規模によってはさすがに大仰か。
[参考]
Igor Minar's Blog: How a Java Application Can Discover its Process ID (PID)
2015/07/09(木)logbackでサイズローテートしない
2015/07/09 14:53 	
Java1.7 + logback-1.1.3
条件は実行時間が短いバッチのようなプログラム。
もともと↓の記述にしていたのだが、ローテートしてくれなかった。
[logback.xml]
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>./logs/hoge.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>./logs/hoge.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>
    
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger\(%F[%L]\) - %msg %n</pattern>
      <charset>Shift_JIS</charset>
    </encoder>
  </appender>
調べてみると、logbackのSizeBasedTriggeringPolicyはI/O負荷対策のためファイルサイズを毎度チェックしにいかない。デフォルトでは16回に1回であり、16回ログ出力して初めてサイズチェックに行く。ログ出力の頻度が多いと間隔を開け、頻度が少ないと間隔を狭める。今回のプログラムは16回ログを出すフローがほとんどない。実行時間も短いため、間隔調整の恩恵も受ける暇がない。親切ではあるのだが、プロセス内の初回はチェックするなど対策が必要に思う。
このプログラムごく短時間で起動->終了し、ログの出力回数・起動頻度とも高くない。毎回チェックとしたい。
[logback.xml]
    <triggeringPolicy class="foo.bar.CustomSizeBasedTriggeringPolicy">
[カスタムクラス]
package foo.bar;
import java.io.File;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import ch.qos.logback.core.util.FileSize;
public class CustomSizeBasedTriggeringPolicy<E> extends SizeBasedTriggeringPolicy<E> {
	String maxFileSizeAsString = Long.toString(DEFAULT_MAX_FILE_SIZE);
	FileSize maxFileSize;
	public CustomSizeBasedTriggeringPolicy() {
	}
	public CustomSizeBasedTriggeringPolicy(final String maxFileSize) {
		setMaxFileSize(maxFileSize);
	}
	@Override
	public boolean isTriggeringEvent(final File activeFile, final E event) {
		//オリジナルのisTriggeringEventでは発火しないことがあるため、ログ書き出しごとにチェックする
		return (activeFile.length() >= maxFileSize.getSize());
	}
	@Override
	public String getMaxFileSize() {
		return maxFileSizeAsString;
	}
	@Override
	public void setMaxFileSize(String maxFileSize) {
		this.maxFileSizeAsString = maxFileSize;
		this.maxFileSize = FileSize.valueOf(maxFileSize);
	}
}
isTriggeringEventだけいじったクラスを作成してやって、logback.xmlでそちらを見るようにしてやる。とりあえずこれで動くことは動く。