LoginSignup
6
3

More than 3 years have passed since last update.

Fluentd out_fileプラグインで出力ファイル名を固定する

Last updated at Posted at 2020-07-18

概要

out_fileプラグインで出力先を指定する際、
ファイル名に年月日情報を含めずに、固定のファイル名としたい。

公式ドキュメントに例として載っている通りのplaceholdersを使う
方法ではうまくいくがplaceholdersを使わない方法ではうまくいかなかったので調査した。

https://docs.fluentd.org/configuration/buffer-section#placeholders

結論: 固定ファイル名にする方法

  1. out_fileプラグインを利用する
  2. bufferセクションの引数にtagを指定する
  3. 出力先のpathを指定する際にplaceholdersを記述する
  4. 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

https://github.com/fluent/fluentd/blob/b593e6f4adb08dd9f2d2fd69f83fe7a6a1514d43/lib/fluent/plugin/out_file.rb#L281

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-f9719352dada

logrotateがプロセスに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情報のファイルに切り替わるため問題なし。

https://github.com/fluent/fluentd/blob/b593e6f4adb08dd9f2d2fd69f83fe7a6a1514d43/lib/fluent/plugin/out_file.rb#L210

logrotateのタイミングで、fluentdにkill -USR1シグナルを送る必要があるかに
ついては、出力先ファイルの切り替え目的では必要ないのだが、
バッファのフラッシュ目的に実施しておいても良さそう。

https://docs.fluentd.org/deployment/signals#sigusr1

なお、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
}

https://github.com/fluent-plugins-nursery/td-agent-builder/blob/691412a88493a663c5e7796dcc7dfce9f3a0c4a7/td-agent/templates/etc/logrotate.d/td-agent

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3