fluent-mixin-type-converter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ vendor/*
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.1.0
5
+ - 2.0.0
6
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fluent-mixin-type-converter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2014- Kentaro Yoshida
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
14
+
data/README.md ADDED
@@ -0,0 +1,164 @@
1
+ ## Fluent::Mixin::TypeConverter [![Build Status](https://travis-ci.org/y-ken/fluent-mixin-type-converter.png?branch=master)](https://travis-ci.org/y-ken/fluent-mixin-type-converter)
2
+
3
+ ## Overview
4
+
5
+ Fluentd mixin plugin to provides type conversion function as like as in_tail plugin. It acts calling [Fluent::TextParser::TypeConverter](https://github.com/fluent/fluentd/blob/master/lib/fluent/parser.rb) as mixin. It will let you get easy to implement type conversion for your own plugins.
6
+
7
+ ## Function
8
+
9
+ It supportes these type conversion.
10
+
11
+ - string
12
+ - integer
13
+ - float
14
+ - bool
15
+ - time
16
+ - array
17
+
18
+ #### Option
19
+
20
+ * `types_delimiter`
21
+ [default] `,`
22
+
23
+ * `types_label_delimiter`
24
+ [default] `:`
25
+
26
+ ## Configuration
27
+
28
+ Adding this mixin plugin, it will enabled to use these type conversion in your plugins.
29
+
30
+ ```xml
31
+ # input plugin example
32
+ <source>
33
+ type foo_bar
34
+ tag test.message
35
+
36
+ # type conversion with this rule before emit.
37
+ types member_id:int,temperature:float
38
+ </source>
39
+ ```
40
+
41
+ ```xml
42
+ # output plugin example
43
+ <match test.foo>
44
+ type foo_bar
45
+ tag test.message
46
+
47
+ # type conversion with this rule before emit.
48
+ types member_id:int,temperature:float
49
+ </match>
50
+ ```
51
+
52
+ Another examples are written in [unit test](https://github.com/y-ken/fluent-mixin-type-converter/blob/master/test/mixin/test_type_converter).
53
+
54
+ ## Usage
55
+
56
+ #### 1. edit gemspec
57
+
58
+ add dependency for .gemspec file like below. For more detail, see [gemspec example](https://github.com/y-ken/fluent-plugin-watch-process/blob/master/fluent-plugin-watch-process.gemspec)
59
+
60
+ ```ruby
61
+ spec.add_runtime_dependency "fluent-mixin-type-converter"
62
+ ```
63
+
64
+ #### 2. activate fluent-mixin-type-converter for your plugin
65
+
66
+ It is the instruction in the case of adding `fluent-plugin-foobar`.
67
+
68
+ ```
69
+ $ cd fluent-plugin-foobar
70
+ $ vim fluent-plugin-foobar.gemspec # edit gemspec
71
+ $ bundle install --path vendor/bundle # or just type `bundle install`
72
+ ```
73
+
74
+ #### 3. edit your plugin to implement
75
+
76
+ It is a quick guide to enable your plugin to use TypeConverter Mixin.
77
+ The key points of basic implmentation is just like below.
78
+
79
+ * add `require 'fluent/mixin/type_converter'` at the top of source
80
+ * in the case of output plugin, add `include Fluent::HandleTagNameMixin` (recommend)
81
+ this is required if you will use kind of 'remove_tag_prefix' option together
82
+ * add `include Fluent::Mixin::TypeConverter` in intput/output class after HandleTagNameMixin
83
+ * add `emit_tag = tag.dup` and `filter_record(emit_tag, time, record)` before `Engine.emit`
84
+
85
+ ##### implement example for input plugin
86
+
87
+ ```ruby
88
+ require 'fluent/mixin/type_converter
89
+
90
+ module Fluent
91
+ class FooBarInput < Fluent::Input
92
+ Plugin.register_input('foo_bar', self)
93
+
94
+ # ...snip...
95
+
96
+ include Fluent::Mixin::TypeConverter
97
+ config_param :types, :string, :default => nil
98
+ config_param :types_delimiter, :string, :default => ','
99
+ config_param :types_label_delimiter, :string, :default => ':'
100
+
101
+ # ...snip...
102
+
103
+ def emit_message(tag, message)
104
+ emit_tag = tag.dup
105
+ filter_record(emit_tag, Engine.now, message)
106
+ Engine.emit(emit_tag, Engine.now, message)
107
+ end
108
+
109
+ # ...snip...
110
+
111
+ end
112
+ end
113
+ ```
114
+
115
+ ##### implement example for output plugin
116
+
117
+ ```ruby
118
+ require 'fluent/mixin/type_converter
119
+
120
+ class Fluent
121
+ class FooBarOutput < Fluent::Output
122
+ Fluent::Plugin.register_output('foo_bar', self)
123
+
124
+ # ...snip...
125
+
126
+ include Fluent::Mixin::TypeConverter
127
+ config_param :types, :string, :default => nil
128
+ config_param :types_delimiter, :string, :default => ','
129
+ config_param :types_label_delimiter, :string, :default => ':'
130
+
131
+ # ...snip...
132
+
133
+ def emit(tag, es, chain)
134
+ es.each do |time, record|
135
+ emit_tag = tag.dup
136
+ filter_record(emit_tag, time, record)
137
+ Fluent::Engine.emit(emit_tag, time, record)
138
+ end
139
+ chain.next
140
+ end
141
+
142
+ # ...snip...
143
+
144
+ end
145
+ end
146
+ ```
147
+
148
+ ## Case Study
149
+
150
+ These cool plugins are using this mixin!
151
+
152
+ * [fluent-plugin-watch-process](https://github.com/y-ken/fluent-plugin-watch-process/)
153
+
154
+ ## TODO
155
+
156
+ Pull requests are very welcome!!
157
+
158
+ ## Copyright
159
+
160
+ Copyright © 2014- Kentaro Yoshida ([@yoshi_ken](https://twitter.com/yoshi_ken))
161
+
162
+ ## License
163
+
164
+ Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ Rake::TestTask.new(:test) do |test|
4
+ test.libs << 'lib' << 'test'
5
+ test.pattern = 'test/**/test_*.rb'
6
+ test.verbose = true
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-mixin-type-converter"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Kentaro Yoshida"]
9
+ spec.email = ["y.ken.studio@gmail.com"]
10
+ spec.summary = %q{Fluentd mixin plugin to provides type conversion function as like as in_tail plugin. It acts calling Fluent::TextParser::TypeConverter as mixin. It will let you get easy to implement type conversion for your own plugins.}
11
+ spec.homepage = "https://github.com/y-ken/fluent-mixin-type-converter"
12
+ spec.license = "Apache License, Version 2.0"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler"
20
+ spec.add_development_dependency "rake"
21
+ spec.add_development_dependency "fluent-mixin-rewrite-tag-name"
22
+ spec.add_runtime_dependency "fluentd"
23
+ end
@@ -0,0 +1,31 @@
1
+ module Fluent
2
+ module Mixin
3
+ module TypeConverter
4
+ include Configurable
5
+ include RecordFilterMixin
6
+ include Fluent::TextParser::TypeConverter
7
+
8
+ attr_accessor :types, :types_delimiter, :types_label_delimiter
9
+
10
+ def configure(conf)
11
+ super
12
+
13
+ end
14
+
15
+ def filter_record(tag, time, record)
16
+ super
17
+ if @types
18
+ convert_field_type!(record)
19
+ end
20
+ end
21
+
22
+ def convert_field_type!(record)
23
+ record.each { |key, value|
24
+ record[key] = convert_type(key, value)
25
+ }
26
+ self
27
+ end
28
+
29
+ end
30
+ end
31
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+
15
+ require 'fluent/test'
16
+ unless ENV.has_key?('VERBOSE')
17
+ nulllogger = Object.new
18
+ nulllogger.instance_eval {|obj|
19
+ def method_missing(method, *args)
20
+ # pass
21
+ end
22
+ }
23
+ $log = nulllogger
24
+ end
25
+
26
+ require 'fluent/mixin/type_converter'
27
+ require_relative 'plugin'
28
+
29
+ class Test::Unit::TestCase
30
+ end
@@ -0,0 +1,93 @@
1
+ require 'helper'
2
+
3
+ class TypeConverterMixinTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ tag log.${tag}
10
+ remove_tag_prefix apache.
11
+ types code:integer,response_time:float
12
+ ]
13
+
14
+ def create_driver(conf=CONFIG,tag='test')
15
+ Fluent::Test::OutputTestDriver.new(Fluent::TypeConverterMixinOutput, tag).configure(conf)
16
+ end
17
+
18
+ def test_configure
19
+ assert_raise(Fluent::ConfigError) {
20
+ d = create_driver('')
21
+ }
22
+ assert_raise(Fluent::ConfigError) {
23
+ d = create_driver('unknown_keys')
24
+ }
25
+ d = create_driver(CONFIG)
26
+ puts d.instance.inspect
27
+ assert_equal 'code:integer,response_time:float', d.instance.config['types']
28
+ end
29
+
30
+ def test_emit
31
+ d1 = create_driver(CONFIG, 'apache.access')
32
+ d1.run do
33
+ d1.emit({
34
+ 'code' => '200',
35
+ 'response_time' => '0.03'
36
+ })
37
+ end
38
+ emits = d1.emits
39
+ assert_equal 1, emits.length
40
+ p emits[0]
41
+ assert_equal 'log.access', emits[0][0] # tag
42
+ assert_equal 200, emits[0][2]['code']
43
+ assert_equal 0.03, emits[0][2]['response_time']
44
+ end
45
+
46
+ def test_emit_with_custom_delimiter
47
+ d1 = create_driver(%[
48
+ tag test.message
49
+ types code:integer|response_time:float
50
+ types_delimiter |
51
+ types_label_delimiter :
52
+ ], 'apache.access')
53
+ d1.run do
54
+ d1.emit({
55
+ 'code' => '200',
56
+ 'response_time' => '0.03'
57
+ })
58
+ end
59
+ emits = d1.emits
60
+ assert_equal 1, emits.length
61
+ p emits[0]
62
+ assert_equal 'test.message', emits[0][0] # tag
63
+ assert_equal 200, emits[0][2]['code']
64
+ assert_equal 0.03, emits[0][2]['response_time']
65
+ end
66
+
67
+ def test_emit_all_types
68
+ d1 = create_driver(%[
69
+ tag test.message
70
+ types string:string,integer:integer,float:float,bool:bool,time:time,array:array
71
+ ], 'apache.access')
72
+ d1.run do
73
+ d1.emit({
74
+ 'string' => 'foo',
75
+ 'integer' => '500',
76
+ 'float' => '0.5',
77
+ 'bool' => 'true',
78
+ 'time' => '2014-01-21 12:29:44 +0900',
79
+ 'array' => 'foo,1,2.0,true'
80
+ })
81
+ end
82
+ emits = d1.emits
83
+ assert_equal 1, emits.length
84
+ p emits[0]
85
+ assert_equal 'test.message', emits[0][0] # tag
86
+ assert_equal 'foo', emits[0][2]['string']
87
+ assert_equal 500, emits[0][2]['integer']
88
+ assert_equal 0.5, emits[0][2]['float']
89
+ assert_equal true, emits[0][2]['bool']
90
+ assert_equal 1390274984, emits[0][2]['time']
91
+ assert_equal ["foo", "1", "2.0", "true"], emits[0][2]['array']
92
+ end
93
+ end
data/test/plugin.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'fluent/mixin/rewrite_tag_name'
2
+
3
+ class Fluent::TypeConverterMixinOutput < Fluent::Output
4
+ Fluent::Plugin.register_output('type_converter_mixin', self)
5
+
6
+ config_param :tag, :string, :default => nil
7
+ config_param :types, :string, :default => nil
8
+ config_param :types_delimiter, :string, :default => ','
9
+ config_param :types_label_delimiter, :string, :default => ':'
10
+
11
+ include Fluent::HandleTagNameMixin
12
+ include Fluent::Mixin::RewriteTagName
13
+ include Fluent::Mixin::TypeConverter
14
+
15
+ def configure(conf)
16
+ super
17
+
18
+ if ( !@tag && !@remove_tag_prefix && !@remove_tag_suffix && !@add_tag_prefix && !@add_tag_suffix )
19
+ raise Fluent::ConfigError, "RewriteTagNameMixin: missing remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
20
+ end
21
+ end
22
+
23
+ def emit(tag, es, chain)
24
+ es.each do |time, record|
25
+ emit_tag = tag.dup
26
+ filter_record(emit_tag, time, record)
27
+ Fluent::Engine.emit(emit_tag, time, record)
28
+ end
29
+ chain.next
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-mixin-type-converter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kentaro Yoshida
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: fluent-mixin-rewrite-tag-name
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: fluentd
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description:
79
+ email:
80
+ - y.ken.studio@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - .travis.yml
87
+ - Gemfile
88
+ - LICENSE
89
+ - README.md
90
+ - Rakefile
91
+ - fluent-mixin-type-converter.gemspec
92
+ - lib/fluent/mixin/type_converter.rb
93
+ - test/helper.rb
94
+ - test/mixin/test_type_converter.rb
95
+ - test/plugin.rb
96
+ homepage: https://github.com/y-ken/fluent-mixin-type-converter
97
+ licenses:
98
+ - Apache License, Version 2.0
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.23
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Fluentd mixin plugin to provides type conversion function as like as in_tail
121
+ plugin. It acts calling Fluent::TextParser::TypeConverter as mixin. It will let
122
+ you get easy to implement type conversion for your own plugins.
123
+ test_files:
124
+ - test/helper.rb
125
+ - test/mixin/test_type_converter.rb
126
+ - test/plugin.rb