Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@sesame

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

概要

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

3
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What is going on with this article?