Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce New Plugin Classes #866

Merged
merged 36 commits into from
Apr 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
19caf7b
use latest ruby for CI
tagomoris Apr 18, 2016
f601453
fix plugin base API to add "owned" plugins by other (input/output/fil…
tagomoris Apr 18, 2016
5c237ac
add some utility methods to write plugins
tagomoris Apr 18, 2016
e2cb738
fix to use plugin base class only for tests
tagomoris Apr 18, 2016
36e13f6
add utility method to overwrite system config in tests
tagomoris Apr 18, 2016
6912c05
fix to reset internal state (especially for tests)
tagomoris Apr 18, 2016
4087110
add module/mixin to handle unique_id in right way (not to implement i…
tagomoris Apr 18, 2016
e54b5bb
add v0.14 Buffer API
tagomoris Apr 18, 2016
0fffaf3
add MemoryBuffer implementation for v0.14 API
tagomoris Apr 18, 2016
2612e9f
add FileBuffer implementation for v0.14 Buffer API
tagomoris Apr 18, 2016
013ea4d
add tests for v0.14 plugin base class
tagomoris Apr 18, 2016
44e2bdc
add Input plugin for v0.14 plugin API
tagomoris Apr 18, 2016
e82c40d
add tests for Input plugin for v0.14 API
tagomoris Apr 18, 2016
1f53273
add Output plugin implementation (including buffering) for v0.14 plug…
tagomoris Apr 18, 2016
1ef535f
add tests for Buffer plugin for v0.14 API
tagomoris Apr 18, 2016
9ae1fc6
add tests for Output pluginn for v0.14 API
tagomoris Apr 18, 2016
682b574
fix tests to wait callbacks surely
tagomoris Apr 18, 2016
80c014d
add requirement explicitly (Travis fails to build on ruby 2.1)
tagomoris Apr 18, 2016
58f508c
fix to show logs in flushing threads when expected situation is not s…
tagomoris Apr 18, 2016
3e62883
fix to use parsed local time to check internal event time from logs
tagomoris Apr 18, 2016
2c825e8
specify osx_image to enable latest ruby on osx environment
tagomoris Apr 18, 2016
a169cf7
update flexmock (now it is missing on rubygems.org)
tagomoris Apr 18, 2016
0a6cd4f
install dependencies explicitly
tagomoris Apr 18, 2016
db19c73
omit parameters same with defaults
tagomoris Apr 18, 2016
3a98938
remove useless check
tagomoris Apr 18, 2016
f458123
fix tests not to be affected by logger formatting
tagomoris Apr 18, 2016
fe56d93
add workaround to prohibit to pass arguments to thread_create helper …
tagomoris Apr 18, 2016
dbb3492
fix wrong test code
tagomoris Apr 19, 2016
d773e01
add comment for paths
tagomoris Apr 19, 2016
11db673
getting file handler of metadata is required to close it cleanly (esp…
tagomoris Apr 19, 2016
db901fa
add mode not to convert newlines on Windows
tagomoris Apr 19, 2016
a3f3a7f
fix tests for Windows environment
tagomoris Apr 19, 2016
ff4212b
add more tests for buffer path configuration and #resume
tagomoris Apr 19, 2016
14d19d0
omit tests about file permissions on Windows
tagomoris Apr 19, 2016
af735c1
fix tests to cleanup generated files
tagomoris Apr 19, 2016
e96dcdd
omit tests for permissions on Windows
tagomoris Apr 19, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
language: ruby
cache: bundler

rvm:
- 2.1
- 2.2.3
- 2.3.0
- ruby-head
- rbx
# http://rubies.travis-ci.org/
# See here for osx_image -> OSX versions: https://docs.travis-ci.com/user/languages/objective-c
matrix:
include:
- rvm: 2.1.10
os: linux
- rvm: 2.2.4
os: linux
- rvm: 2.3.0
os: linux
- rvm: ruby-head
os: linux
- rvm: 2.1.0
os: osx
osx_image: xcode7.3 # OSX 10.11
- rvm: 2.2.4
os: osx
osx_image: xcode7.1 # OSX 10.10
- rvm: ruby-head
os: osx
osx_image: xcode 7.3 # OSX 10.11
allow_failures:
- rvm: ruby-head

os:
- linux
- osx
# no valid version/env for ruby 2.3 right now
# - rvm: 2.3.0
# os: osx
# osx_image: ....

branches:
only:
Expand All @@ -18,16 +37,9 @@ branches:
- v0.12
- v0.14

gemfile:
- Gemfile

script: bundle exec rake

sudo: false

matrix:
allow_failures:
- rvm: ruby-head
- rvm: rbx
- rvm: 2.3.0
os: osx
addons:
apt:
packages:
- libgmp3-dev
2 changes: 1 addition & 1 deletion fluentd.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Gem::Specification.new do |gem|
gem.add_runtime_dependency("strptime", [">= 0.1.7"])

gem.add_development_dependency("rake", [">= 0.9.2"])
gem.add_development_dependency("flexmock", ["~> 1.3.3"])
gem.add_development_dependency("flexmock", ["~> 2.0.5"])
gem.add_development_dependency("parallel_tests", [">= 0.15.3"])
gem.add_development_dependency("simplecov", ["~> 0.6.4"])
gem.add_development_dependency("rr", [">= 1.0.0"])
Expand Down
35 changes: 34 additions & 1 deletion lib/fluent/config/configure_proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
module Fluent
module Config
class ConfigureProxy
attr_accessor :name, :final, :param_name, :init, :required, :multi, :alias, :argument, :params, :defaults, :descriptions, :sections
attr_accessor :name, :final, :param_name, :init, :required, :multi, :alias, :configured_in_section
attr_accessor :argument, :params, :defaults, :descriptions, :sections
# config_param :desc, :string, :default => '....'
# config_set_default :buffer_type, :memory
#
Expand Down Expand Up @@ -50,6 +51,11 @@ def initialize(name, opts = {})

raise "init and required are exclusive" if @init && @required

# specify section name for viewpoint of owner(parent) plugin
# for buffer plugins: all params are in <buffer> section of owner
# others: <storage>, <format> (formatter/parser), ...
@configured_in_section = nil

@argument = nil # nil: ignore argument
@params = {}
@defaults = {}
Expand Down Expand Up @@ -89,6 +95,9 @@ def merge(other) # self is base class, other is subclass
if overwrite?(other, :alias)
raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: alias"
end
if overwrite?(other, :configured_in_section)
raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: configured_in"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configured_in_section instead of configured_in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. This message is for authors of plugins, and plugins use configured_in method to specify this value.

end

options = {}
# param_name is used not to ovewrite plugin's instance
Expand All @@ -103,6 +112,9 @@ def merge(other) # self is base class, other is subclass

merged = self.class.new(other.name, options)

# configured_in MUST be kept
merged.configured_in_section = self.configured_in_section

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This space is needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is not for plugin itself, but for internal handling about overwriting default values. It should be separated from argument/params/defaults/sections.

merged.argument = other.argument || self.argument
merged.params = other.params.merge(self.params)
merged.defaults = self.defaults.merge(other.defaults)
Expand Down Expand Up @@ -144,6 +156,9 @@ def merge_for_finalized(other)
if overwrite?(other, :alias)
raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: alias"
end
if overwrite?(other, :configured_in_section)
raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: configured_in"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

end

options = {}
options[:param_name] = other.param_name
Expand All @@ -155,6 +170,8 @@ def merge_for_finalized(other)

merged = self.class.new(other.name, options)

merged.configured_in_section = self.configured_in_section

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

merged.argument = self.argument || other.argument
merged.params = other.params.merge(self.params)
merged.defaults = other.defaults.merge(self.defaults)
Expand All @@ -175,6 +192,15 @@ def merge_for_finalized(other)
merged
end

def overwrite_defaults(other) # other is owner plugin's corresponding proxy
self.defaults = self.defaults.merge(other.defaults)
self.sections.keys.each do |section_key|
if other.sections.has_key?(section_key)
self.sections[section_key].overwrite_defaults(other.sections[section_key])
end
end
end

def parameter_configuration(name, *args, &block)
name = name.to_sym

Expand Down Expand Up @@ -213,6 +239,13 @@ def parameter_configuration(name, *args, &block)
[name, block, opts]
end

def configured_in(section_name)
if @configured_in_section
raise ArgumentError, "#{self.name}: configured_in called twice"
end
@configured_in_section = section_name.to_sym
end

def config_argument(name, *args, &block)
if @argument
raise ArgumentError, "#{self.name}: config_argument called twice"
Expand Down
13 changes: 13 additions & 0 deletions lib/fluent/configurable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def self.included(mod)
end

def initialize
super
# to simulate implicit 'attr_accessor' by config_param / config_section and its value by config_set_default
proxy = self.class.merged_configure_proxy
proxy.params.keys.each do |name|
Expand All @@ -51,6 +52,14 @@ def configure(conf)
proxy = self.class.merged_configure_proxy
conf.corresponding_proxies << proxy

if self.respond_to?(:owner) && self.owner
owner_proxy = owner.class.merged_configure_proxy
if proxy.configured_in_section
owner_proxy = owner_proxy.sections[proxy.configured_in_section]
end
proxy.overwrite_defaults(owner_proxy) if owner_proxy
end

# In the nested section, can't get plugin class through proxies so get plugin class here
plugin_class = Fluent::Plugin.lookup_type_from_class(proxy.name.to_s)
root = Fluent::Config::SectionGenerator.generate(proxy, conf, logger, plugin_class)
Expand Down Expand Up @@ -97,6 +106,10 @@ def configure_proxy(mod_name)
map[mod_name]
end

def configured_in(section_name)
configure_proxy(self.name).configured_in(section_name)
end

def config_param(name, *args, &block)
configure_proxy(self.name).config_param(name, *args, &block)
attr_accessor name
Expand Down
10 changes: 10 additions & 0 deletions lib/fluent/log.rb
Original file line number Diff line number Diff line change
Expand Up @@ -390,5 +390,15 @@ def configure(conf)
@log.optional_attrs = {}
end
end

def start
@log.reset
super
end

def terminate
super
@log.reset
end
end
end
39 changes: 23 additions & 16 deletions lib/fluent/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ module Plugin
# plugins for fluentd plugins: fluent/plugin/type/NAME.rb
# ex: storage, buffer chunk, ...

# first class plugins (instantiated by Engine)
INPUT_REGISTRY = Registry.new(:input, 'fluent/plugin/in_')
OUTPUT_REGISTRY = Registry.new(:output, 'fluent/plugin/out_')
FILTER_REGISTRY = Registry.new(:filter, 'fluent/plugin/filter_')

# feature plugin: second class plugins (instanciated by Plugins or Helpers)
BUFFER_REGISTRY = Registry.new(:buffer, 'fluent/plugin/buf_')
PARSER_REGISTRY = Registry.new(:parser, 'fluent/plugin/parser_')
FORMATTER_REGISTRY = Registry.new(:formatter, 'fluent/plugin/formatter_')
Expand Down Expand Up @@ -105,28 +108,28 @@ def self.new_filter(type)
new_impl('filter', FILTER_REGISTRY, type)
end

def self.new_buffer(type)
new_impl('buffer', BUFFER_REGISTRY, type)
def self.new_buffer(type, parent: nil)
new_impl('buffer', BUFFER_REGISTRY, type, parent)
end

def self.new_parser(type)
def self.new_parser(type, parent: nil)
require 'fluent/parser'

if type[0] == '/' && type[-1] == '/'
# This usage is not recommended for new API... create RegexpParser directly
require 'fluent/parser'
Fluent::TextParser.lookup(type)
else
new_impl('parser', PARSER_REGISTRY, type)
new_impl('parser', PARSER_REGISTRY, type, parent)
end
end

def self.new_formatter(type)
new_impl('formatter', FORMATTER_REGISTRY, type)
def self.new_formatter(type, parent: nil)
new_impl('formatter', FORMATTER_REGISTRY, type, parent)
end

def self.new_storage(type)
new_impl('storage', STORAGE_REGISTRY, type)
def self.new_storage(type, parent: nil)
new_impl('storage', STORAGE_REGISTRY, type, parent)
end

def self.register_impl(kind, registry, type, value)
Expand All @@ -138,17 +141,21 @@ def self.register_impl(kind, registry, type, value)
nil
end

def self.new_impl(kind, registry, type)
def self.new_impl(kind, registry, type, parent=nil)
# "'type' not found" is handled by registry
obj = registry.lookup(type)
case
when obj.is_a?(Class)
obj.new
when obj.respond_to?(:call) && obj.arity == 0
obj.call
else
raise Fluent::ConfigError, "#{kind} plugin '#{type}' is not a Class nor callable (without arguments)."
impl = case
when obj.is_a?(Class)
obj.new
when obj.respond_to?(:call) && obj.arity == 0
obj.call
else
raise Fluent::ConfigError, "#{kind} plugin '#{type}' is not a Class nor callable (without arguments)."
end
if parent && impl.respond_to?("owner=")
impl.owner = parent
end
impl
end
end
end
Loading