概要
out_fileプラグインで出力先を指定する際、
ファイル名に年月日情報を含めずに、固定のファイル名としたい。
公式ドキュメントに例として載っている通りのplaceholdersを使う
方法ではうまくいくがplaceholdersを使わない方法ではうまくいかなかったので調査した。
https://docs.fluentd.org/configuration/buffer-section#placeholders
結論: 固定ファイル名にする方法
- out_fileプラグインを利用する
- bufferセクションの引数にtagを指定する
- 出力先のpathを指定する際にplaceholdersを記述する
- append trueを設定する
なお、bufferセクションの引数にtag
を指定した場合について調べたのだが、
time
を指定しなければ、同様の結果になると思われる。
1. out_fileプラグインを利用する
<match log.*>
@type file # @typeにfileを指定
path /data/${tag}/access.log #=> "/data/log.map/access.log"
<buffer tag>
# ...
</buffer>
</match>
2. bufferセクションの引数にtagを指定する
<match log.*>
@type file # @typeにfileを指定
path /data/${tag}/access.log #=> "/data/log.map/access.log"
<buffer tag> # bufferセクションの引数にtagを渡す
# ...
</buffer>
</match>
上記例では、tag
を引数として指定している。
out_fileプラグインは、buffer系プラグインから
timkeyパラメータの値を引いてくるが、timekeyパラメータに
値が設定されていると、出力先ファイルに年月日情報(time_placeholders
)を含めるように
path_template
を生成する。
if timekey
if time_slice_format
"#{original}.#{time_slice_format}#{index_placeholder}#{path_suffix}#{comp_suffix}"
else
time_placeholders = timekey_to_timeformat(timekey)
if time_placeholders.scan(/../).any?{|ph| original.include?(ph) }
raise Fluent::ConfigError, "insufficient timestamp placeholders in path" if time_placeholders.scan(/../).any?{|ph| !original.include?(ph) }
"#{original}#{index_placeholder}#{path_suffix}#{comp_suffix}"
else
"#{original}.#{time_placeholders}#{index_placeholder}#{path_suffix}#{comp_suffix}"
end
end
else
# ここに入りたい
"#{original}#{index_placeholder}#{path_suffix}#{comp_suffix}"
end
bufferセクションの引数にtagを指定するとtimekeyがnilの状態になるようだ。
なお、bufferセクションの引数を空にした場合も試したが、timekeyにデフォルト値である86400
が
入ってしまい、出力ファイル名に年月日情報が含まれてしまいうまくいかなかった。
blank-chunk-keys
https://docs.fluentd.org/configuration/buffer-section#blank-chunk-keys
3. 出力先のpathを指定する際にplaceholdersを記述する
bufferセクションの引数にtagを指定した場合、
このpath
部分に${tag}
もしくは${tag[0]}
などのtag placeholderが
存在しないと、ConfigErrorが発生してしまうのを回避するために、
tag placeholderを記述する。
Fluent::ConfigError error="Parameter 'path: /var/log/td-agent/dummy_test.log' doesn't have tag placeholder"
<match log.*>
@type file
path /data/${tag}/access.log #=> "/data/log.map/access.log"
<buffer tag> # bufferセクションの引数にtagを渡す
# ...
</buffer>
</match>
tag placeholder
tag
として、dummy.test
が渡ってくる場合。
tag
のplaceholdersは、以下が対応する。
-
${tag}
は、tag
そのままの文字列(dummy.test
)が返る。 -
${tag[0]}
のようにindexのような情報をいれると"dummy.test".split(".")[0] #=> "dummy"
が返る。
4.append trueを設定する
出力ファイル名に連番がつくのを避けるためにappend trueを設定する。
<match log.*>
@type file
path /data/${tag}/access.log #=> "/data/log.map/access.log"
append true # 連番回避
<buffer tag>
# ...
</buffer>
</match>
logrotate周り
出力ファイル名を固定すると、logrotateを実施する必要があるが
出力先ファイルをプロセスがオープンしたまま握っているとまずい。
参考
logrotateの設定とファイルのアクセスモードについて
https://medium.com/@catatsuy/logrotate%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-f9719352dadalogrotateがプロセスにHUP送る理由を調べてみた
https://masudak.hatenablog.jp/entry/20110914/1315999265
def write_without_compression(path, chunk)
File.open(path, "ab", @file_perm) do |f|
chunk.write_to(f)
end
end
ファイルに書き込みを行うタイミングで、毎回パスを指定して
オープンしなおしているので、logrotate側でファイルをmvしても
移動後のファイルに出力される。
次の書き込みタイミングでpath情報からファイルを改めてオープンするので、
ここで出力先ファイルがpath情報のファイルに切り替わるため問題なし。
logrotateのタイミングで、fluentdにkill -USR1
シグナルを送る必要があるかに
ついては、出力先ファイルの切り替え目的では必要ないのだが、
バッファのフラッシュ目的に実施しておいても良さそう。
なお、fluentd自体のログ出力先ファイルについては、fluentdが握りっぱなしになるので、
logrotation時に、SIGUSR1を送信する必要がある。
参考: td-agentのlogrotateのひな形
/var/log/<%= project_name %>/<%= project_name %>.log {
daily
rotate 30
compress
delaycompress
notifempty
create 640 <%= project_name %> <%= project_name %>
sharedscripts
postrotate
pid=/var/run/<%= project_name %>/<%= project_name %>.pid
if [ -s "$pid" ]
then
kill -USR1 "$(cat $pid)"
fi
endscript
}