LoginSignup
1
1

More than 5 years have passed since last update.

fluentdのconfのDSL記法は通常のconfからinclude出来ない

Last updated at Posted at 2017-12-08

古いサーバのリプレース作業中に、行数の多いfluentdのconfを見つけました。
中身はsource指定で多数のログファイルをtailしている部分が大部分を占めているため、
Ruby DSL記法で書くと良いかもしれない、と試してみました。
参考: FluentdでRuby DSLを使う
以下のようになりました(架空のものです)

config.rb
sources = %w(device request response)

sources.each do |log_type|
    source {
        type :tail
        path "/var/log/game/#{log_type}.%Y%m%d"
        tag log_type
    }
end

書きつつコマンドラインから-cで指定して、読み込ませて想定通りのconfになっていることを確認し
いざ配置してみるとエラー、スタックトレースを見ると…
あれ?通常のconf用のv1_parserが動いてる?

実はこのサーバの大本のconfでは最低限の設定を記述し、各サーバで必要な部分については別ファイルに書いたものをincludeするようにされていました。
通常のconfを読み取るv1_parserのソースを見てみると

v1_parser.rb
def eval_include(attrs, elems, uri)
  u = URI.parse(uri)
  if u.scheme == 'file' || (!u.scheme.nil? && u.scheme.length == 1) || u.path == uri # file path
    # When the Windows absolute path then u.scheme.length == 1
    # e.g. C:
    path = u.path
    if path[0] != ?/
      pattern = File.expand_path("#{@include_basepath}/#{path}")
    else
      pattern = path
    end
    Dir.glob(pattern).sort.each { |entry|
      basepath = File.dirname(entry)
      fname = File.basename(entry)
      data = File.read(entry)
      data.force_encoding('UTF-8')
      ss = StringScanner.new(data)
      V1Parser.new(ss, basepath, fname, @eval_context).parse_element(true, nil, attrs, elems)
    }
  else
    require 'open-uri'
    basepath = '/'
    fname = path
    data = open(uri) { |f| f.read }
    data.force_encoding('UTF-8')
    ss = StringScanner.new(data)
    V1Parser.new(ss, basepath, fname, @eval_context).parse_element(true, nil, attrs, elems)
end

https://github.com/fluent/fluentd/blob/master/lib/fluent/config/v1_parser.rb
と、includeされたファイルをV1Parserに渡していました。
一方DSLパーサのソースでは

dsl.rb
def include(*args)
  ::Kernel.raise ::ArgumentError, "#{name} block requires arguments for include path" if args.nil? || args.size != 1
  if args.first =~ /\.rb$/
    path = File.expand_path(args.first)
    data = File.read(path)
    self.instance_eval(data, path)
  else
    ss = StringScanner.new('')
    Config::V1Parser.new(ss, @proxy.include_basepath, '', nil).eval_include(@attrs, @elements, args.first)
  end
end

https://github.com/fluent/fluentd/blob/master/lib/fluent/config/dsl.rb
のように、includeされるファイル名の末尾を見て、V1Parserに渡すかDSLに渡すかを分けていました。

今回のケースでは、ベースのconfから個別のconfをincludeする運用は変更したくなかったため、
DSL記法を止め、confの整理をすることとしました。
v1_parserのinclude部分を修正することも試してみたいと思います。

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