fluent-plugin-split_record 0.12.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0887090cebdf0de99fa03fcd83c7702a9013cf44
4
+ data.tar.gz: ffd3606d5bb4a9f0a563102b1d6e39fbd0243e40
5
+ SHA512:
6
+ metadata.gz: 84593232bdea75447f1d3dba891f464eca40392902918796efd28dfcadad6ee8b23d5f49a76ea909f9a3ce4e4cfd468db4dddbd1af08e70ddbe576aeacc276ac
7
+ data.tar.gz: 0888ea9208dad158790fce11fc0fe4168f996f754ad07af53fb1d430f8b73f96330131cf75cb7f9d982a2f2e9ca050010c7034053d90c28bcea2f0a03607d52d
@@ -0,0 +1,19 @@
1
+ *~
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2013 Masahiro Sano
2
+ Copyright (c) 2017 Michael Adams
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ # fluent-plugin-split_record
2
+
3
+ Fluentd filter plugin to split a record into multiple records with key/value pair. Compatible with 0.12 and 0.14 versions of fluentd.
4
+
5
+ ## Overview
6
+ This plugin splits a record and parses each results to make key/value pairs; Logstash's [kv filter](https://www.elastic.co/guide/en/logstash/current/plugins-filters-kv.html) is a good example of this. It is a successor to [fluent-plugin-split](https://github.com/kazegusuri/fluent-plugin-split/); a 0.10 output plugin. This is NOT the current 0.12+ [fluent-plugin-split](https://github.com/toyama0919/fluent-plugin-split/): that one is what currently installs with ruby-gem, and splits CSV-style content.
7
+
8
+ Normally you can use a regular expression to parse a record. It is difficult to parse a record which has ambiguous numbers of data like a following record.
9
+
10
+ **Before**
11
+ ```json
12
+ {"message":"key1=val1 key2=val2 key3=val3"}
13
+ ```
14
+
15
+ **After**
16
+ ```json
17
+ {"key1":"val1","key2":"val2","key3":"val3"}
18
+ ```
19
+
20
+ ## Installation
21
+
22
+ ### Local/Build
23
+ ```
24
+ $ git clone https://github.com/unquietwiki/fluent-plugin-split_record.git && cd fluent-plugin-split_record
25
+ $ td-agent-gem build fluent-plugin-split_record.gemspec
26
+ $ td-agent-gem install fluent-plugin-split_record-0.12.1.gem
27
+ ```
28
+
29
+ ### Online
30
+ ```
31
+ $ td-agent-gem install fluent-plugin-split_record
32
+ ```
33
+
34
+ ## Configuration
35
+
36
+ ### Parameters
37
+
38
+ |parameter|description|default|
39
+ |---|---|---|
40
+ |tag| key name for tag | |
41
+ |format| regexp to parse a record after split | '(?<key>\S*)=(?<value>\S*)' |
42
+ |substring_format| regexp used to identify substrings | '(?<key>\S*)=\\"(?<value>.*?)\\"' |
43
+ |key_name| key name to be split | |
44
+ |out_key| key name of json object which includes divided records | nil |
45
+ |reserve_msg| if original message is reserved or not | nil |
46
+ |keys_prefix| if set, all extracted keys names will be preceded by this string | nil |
47
+
48
+ ### Example
49
+
50
+ You may want to pre-process with the [regexp parser](https://docs.fluentd.org/v0.12/articles/parser_regexp) to remove/tag other elements first; this is a requirement if working with [SonicWall syslog input](http://software.sonicwall.com/manual/232-001835-00_rev_a_sonicos_log_event_reference_guide.pdf), which is otherwise an array of key-value pairs.
51
+
52
+ ```
53
+ <source>
54
+ @type udp
55
+ port 514
56
+ format /\<(?<prefix>[0-9]{1,3})\>(?<extradata>.+)$\z/
57
+ tag FW
58
+ </source>
59
+
60
+ <filter FW.**>
61
+ @type split_record
62
+ tag FW
63
+ key_name extradata
64
+ reserve_msg no
65
+ </filter>
66
+ ```
67
+
68
+ ## References
69
+
70
+ * https://github.com/repeatedly/fluent-plugin-record-modifier/
71
+ * https://docs.fluentd.org/v0.12/articles/plugin-development
72
+ * https://ruby-doc.org/core-2.1.5/
73
+ * https://stackoverflow.com/questions/tagged/ruby
74
+ * http://rubular.com/
@@ -0,0 +1,13 @@
1
+ require "bundler"
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/test_*.rb'
9
+ test.verbose = true
10
+ end
11
+
12
+ task :default => [:test]
13
+
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "fluent-plugin-split_record"
6
+ spec.version = "0.12.1"
7
+ spec.authors = ["Masahiro Sano","Michael Adams"]
8
+ spec.email = ["sabottenda@gmail.com","unquietwiki@gmail.com"]
9
+ spec.description = %q{Fluentd filter plugin to split a record into multiple records with key/value pair.}
10
+ spec.summary = %q{Successor to original fluent-plugin-split. Updated for fluentd 0.12 and 0.14, with non-conflicting name.}
11
+ spec.homepage = "https://github.com/unquietwiki/fluent-plugin-split_record"
12
+ spec.license = "MIT"
13
+ spec.files = `git ls-files`.split("\n")
14
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ spec.require_paths = ["lib"]
17
+ spec.add_dependency "fluentd",">= 0.12.39","< 0.16"
18
+ end
@@ -0,0 +1,105 @@
1
+ # Derived from https://github.com/kazegusuri/fluent-plugin-split/blob/master/lib/fluent/plugin/out_split.rb
2
+ # Aug 30, 2017; Michael Adams; unquietwiki@gmail.com
3
+
4
+ # References
5
+ # https://github.com/repeatedly/fluent-plugin-record-modifier/
6
+ # https://docs.fluentd.org/v0.12/articles/plugin-development
7
+ # https://ruby-doc.org/core-2.1.5/
8
+ # https://stackoverflow.com/questions/tagged/ruby
9
+
10
+ require 'fluent/filter'
11
+
12
+ module Fluent
13
+ class SplitRecordFilter < Filter
14
+ Fluent::Plugin.register_filter("split_record", self)
15
+
16
+ # Parameters
17
+ config_param :tag, :string
18
+ config_param :key_name, :string
19
+ config_param :out_key, :string, :default => nil
20
+ config_param :reserve_msg, :bool, :default => nil
21
+ config_param :keys_prefix, :string, :default => nil
22
+ config_param :format, :string, :default => '(?<key>\S*)=(?<value>\S*)'
23
+ config_param :substring_format, :string, :default => '(?<key>\S*)=\\"(?<value>.*?)\\"'
24
+
25
+ # Configuration
26
+ def configure(conf)
27
+ super
28
+ @format_regex = Regexp.new(@format)
29
+ @format_regex_substring = Regexp.new(@substring_format)
30
+ unless @format_regex.names.include?("key") and @format_regex.names.include?("value")
31
+ raise ConfigError, "split_record: format must have named_captures of key and value"
32
+ end
33
+ if (!keys_prefix.nil? && keys_prefix.is_a?(String))
34
+ @store_fun = method(:store_with_prefix)
35
+ else
36
+ @store_fun = method(:store)
37
+ end
38
+ end
39
+
40
+ # ===== Required API methods =====
41
+ def start
42
+ super
43
+ end
44
+
45
+ def shutdown
46
+ super
47
+ end
48
+
49
+ def filter(tag, time, record)
50
+ record
51
+ end
52
+
53
+ def filter_stream(tag, es)
54
+ mes = MultiEventStream.new
55
+ es.each { |time, record|
56
+ begin
57
+ msg = record[@key_name]
58
+ record.delete(@key_name) unless @reserve_msg
59
+ data = split_message(msg)
60
+ if @out_key.nil?
61
+ record.merge!(data)
62
+ else
63
+ record[@out_key] = data
64
+ end
65
+ mes.add(time, record)
66
+ rescue => e
67
+ router.emit_error_event(tag, time, record, e)
68
+ end
69
+ }
70
+ mes
71
+ end
72
+
73
+ # ===== Private methods =====
74
+ private
75
+
76
+ # Message splitter
77
+ def split_message(message)
78
+ return {} unless message.is_a?(String)
79
+ # Convert key-pairs as found
80
+ if @format_regex_substring.nil?
81
+ key_values = message.scan @format_regex
82
+ # Pop off substrings; get their key-pairs; then scan the leftovers
83
+ else
84
+ key_values = message.scan @format_regex_substring
85
+ leftovers = message.gsub(@format_regex_substring,'').scan(@format_regex)
86
+ leftovers.each { |e| key_values << e }
87
+ end
88
+ # Store key pairs
89
+ data = {}
90
+ key_values.each { |e| @store_fun.call(data,e[0],e[1]) }
91
+ data
92
+ end
93
+
94
+ # Store key/value pair
95
+ def store(data, key, value)
96
+ data.store(key, value)
97
+ end
98
+
99
+ # Store key/value pair, with prefix
100
+ def store_with_prefix(data, key, value)
101
+ data.store(@keys_prefix+key, value)
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
17
+ require 'fluent/test'
18
+
19
+ unless ENV.has_key?('VERBOSE')
20
+ nulllogger = Object.new
21
+ nulllogger.instance_eval {|obj|
22
+ def method_missing(method, *args)
23
+ # pass
24
+ end
25
+ }
26
+ $log = nulllogger
27
+ end
28
+
29
+ require 'fluent/plugin/filter_split_record'
30
+
31
+ class Test::Unit::TestCase
32
+ end
@@ -0,0 +1,109 @@
1
+ require 'fluent/test'
2
+ require 'fluent/plugin/filter_split_record'
3
+
4
+ class SplitRecordFilterTest < Test::Unit::TestCase
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ type split_record
11
+ tag foo.filtered
12
+ key_name message
13
+ ]
14
+
15
+ def create_driver(conf = CONFIG, tag='test')
16
+ Fluent::Test:::OutputTestDriver.new(Fluent::SplitRecordFilter, tag).configure(conf)
17
+ end
18
+
19
+ def get_hostname
20
+ require 'socket'
21
+ Socket.gethostname.chomp
22
+ end
23
+
24
+ def test_configure
25
+ assert_raise(Fluent::ConfigError) {
26
+ create_driver(CONFIG + %[
27
+ format /aa/
28
+ ])
29
+ }
30
+ assert_raise(Fluent::ConfigError) {
31
+ create_driver(CONFIG + %[
32
+ format (?<key>a)
33
+ ])
34
+ }
35
+ assert_raise(Fluent::ConfigError) {
36
+ create_driver(CONFIG + %[
37
+ format (?<value>a)
38
+ ])
39
+ }
40
+ assert_nothing_raised(Fluent::ConfigError) {
41
+ create_driver(CONFIG + %[
42
+ format (?<value>a) (?<key>b)
43
+ ])
44
+ }
45
+ end
46
+
47
+ def test_format_1
48
+ d = create_driver
49
+
50
+ d.run do
51
+ d.emit({"message" => "key1=val1 key2=val2"})
52
+ d.emit({"message" => " key1=val1 "})
53
+ d.emit({"message" => " "})
54
+ d.emit({"message" => 1})
55
+ end
56
+
57
+ mapped = {'gen_host' => get_hostname, 'foo' => 'bar', 'included_tag' => 'test'}
58
+ assert_equal [
59
+ {"key1" => "val1", "key2" => "val2"},
60
+ {"key1" => "val1"},
61
+ {},
62
+ {},
63
+ ], d.records
64
+ end
65
+
66
+ def test_format_2
67
+ d = create_driver(CONFIG + %[
68
+ separator ,
69
+ reserve_msg true
70
+ ])
71
+
72
+ d.run do
73
+ d.emit({"message" => "key1=val1,key2=val2"})
74
+ end
75
+
76
+ assert_equal [
77
+ {"message" => "key1=val1,key2=val2", "key1" => "val1", "key2" => "val2"},
78
+ ], d.records
79
+ end
80
+
81
+ def test_format_3
82
+ d = create_driver(CONFIG + %[
83
+ out_key data
84
+ ])
85
+
86
+ d.run do
87
+ d.emit({"message" => "key1=val1 key2=val2"})
88
+ end
89
+
90
+ assert_equal [
91
+ {"data" => {"key1" => "val1", "key2" => "val2"}},
92
+ ], d.records
93
+ end
94
+
95
+ def test_format_keysprefix
96
+ d = create_driver(CONFIG + %[
97
+ out_key data
98
+ keys_prefix extracted_
99
+ ])
100
+
101
+ d.run do
102
+ d.emit({"message" => "key1=val1 key2=val2"})
103
+ end
104
+
105
+ assert_equal [
106
+ {"data" => {"extracted_key1" => "val1", "extracted_key2" => "val2"}},
107
+ ], d.records
108
+ end
109
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-split_record
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.12.1
5
+ platform: ruby
6
+ authors:
7
+ - Masahiro Sano
8
+ - Michael Adams
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-08-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 0.12.39
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '0.16'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 0.12.39
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.16'
34
+ description: Fluentd filter plugin to split a record into multiple records with key/value
35
+ pair.
36
+ email:
37
+ - sabottenda@gmail.com
38
+ - unquietwiki@gmail.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - ".gitignore"
44
+ - Gemfile
45
+ - LICENSE.txt
46
+ - README.md
47
+ - Rakefile
48
+ - fluent-plugin-split_record.gemspec
49
+ - lib/fluent/plugin/filter_split_record.rb
50
+ - test/helper.rb
51
+ - test/plugin/test_filter_split_record.rb
52
+ homepage: https://github.com/unquietwiki/fluent-plugin-split_record
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.8
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Successor to original fluent-plugin-split. Updated for fluentd 0.12 and 0.14,
76
+ with non-conflicting name.
77
+ test_files: []