fluent-mixin-type-converter 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE +14 -0
- data/README.md +164 -0
- data/Rakefile +9 -0
- data/fluent-mixin-type-converter.gemspec +23 -0
- data/lib/fluent/mixin/type_converter.rb +31 -0
- data/test/helper.rb +30 -0
- data/test/mixin/test_type_converter.rb +93 -0
- data/test/plugin.rb +31 -0
- metadata +126 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
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 [](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,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
|