# pidfile # td-agent: /var/run/td-agent/td-agent.pid # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/systemd/td-agent.service.erb#L18 # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/init.d/deb/td-agent#L24 # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/init.d/rpm/td-agent#L24 # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/td-agent/logrotate.d/td-agent.logrotate#L10 # fluentd: nothing (or --daemon PIDFILE) # # logfile # td-agent: /var/log/td-agent/td-agent.log # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/systemd/td-agent.service.erb#L21 # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/init.d/deb/td-agent#L23 # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/init.d/rpm/td-agent#L23 # fluentd: stdout (or --log LOGFILE) # # config file # td-agent: /etc/td-agent/td-agent.conf # - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/systemd/td-agent.service.erb#L14 # fluentd: /etc/fluent/fluent.conf (created by fluentd -s) require "strscan" class Fluentd class Agent module Common attr_reader :extra_options def self.included(base) base.include(Fluentd::Agent::ProcessOperation) end # define these methods on each Agent class %w(start stop restart version).each do |method| define_method(method) do raise NotImplementedError, "'#{method}' method is required to be defined" end end def initialize(options = {}) @extra_options = options end def pid_file extra_options[:pid_file] || self.class.default_options[:pid_file] end def log_file extra_options[:log_file] || self.class.default_options[:log_file] end def log @log ||= FluentdLog.new(log_file) end def config_file extra_options[:config_file] || self.class.default_options[:config_file] end # -- config def config File.read(config_file) end def config_write(content) backup_config File.open(config_file, "w") do |f| f.write content end end def config_append(content) backup_config File.open(config_file, "a") do |f| f.write "\n" f.write content end end def config_merge(content) if content.start_with?("}) label, sections = parse_label_section(label_content, started) contents["label:#{label}"] << { label: label, pos: started, sections: sections, size: label_content.size } else raise TypeError, "Unknown section: #{started}: #{section_type}" end end contents end def parse_label_section(content, offset) scanner = StringScanner.new(content) scanner.scan_until(/^/) label = scanner[1] sections = Hash.new {|h, k| h[k] = [] } loop do break if scanner.match?(%r{\s+?}) pos = scanner.pos header = scanner.scan_until(/^\s*<(filter|match)/) type = scanner[1] source = header + scanner.scan_until(%r{^\s*}) sections[type] << { label: label, pos: pos + offset, content: source.sub(/\n+/, "") } end return label, sections end def dump_parsed_config(parsed_config) content = "".dup sources = parsed_config["source"] || [] filters = parsed_config["filter"] || [] matches = parsed_config["match"] || [] labels = parsed_config.select do |key, sections| key.start_with?("label:") end labels = labels.values.flatten sorted_sections = (sources + filters + matches + labels).sort_by do |section| section[:pos] end sorted_sections.each do |section| if section.key?(:label) label = section[:label] sub_filters = section.dig(:sections, "filter") || [] sub_matches = section.dig(:sections, "match") || [] sub_sections = (sub_filters + sub_matches).sort_by do |sub_section| sub_section[:pos] end content << "\n\n" else content << section[:content] << "\n\n" end end content.chomp end end end end