Edited at

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

More than 1 year has passed since last update.

古いサーバのリプレース作業中に、行数の多い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部分を修正することも試してみたいと思います。