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