fluent-plugin-record-splitter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 95eaaedda188b48d981731e092efc5622123767e7cd853dd731f377dcff8807c
4
+ data.tar.gz: 9794eaccdea09378762cdd60e7f229382c551b97864519c01881dca840867496
5
+ SHA512:
6
+ metadata.gz: dd74aa0bddf63d3c3924b359d6a119f4386515e0b53a181b0ac34348f2edd80592a79251f64113ca8a71fb33da5f4cb07bc08aaa5aa7b6fccf84960388047d07
7
+ data.tar.gz: 9f7872a3071252fabbffad9d3f99d19f294716d50e14e39b7635a040af8835227dafe6dae0fe1c66d1614cdf632d97ca33181581dc1c3904a4dbb11060fc1a76
@@ -0,0 +1,39 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build + Publish
10
+ runs-on: ubuntu-latest
11
+ if: github.actor == github.event.repository.owner.login
12
+
13
+ steps:
14
+ - uses: actions/checkout@master
15
+ - name: Set up Ruby 2.6
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.6
19
+
20
+ - name: Publish to RubyGems
21
+ run: |
22
+ mkdir -p $HOME/.gem
23
+ touch $HOME/.gem/credentials
24
+ chmod 0600 $HOME/.gem/credentials
25
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
26
+ gem build *.gemspec
27
+ gem push *.gem
28
+ env:
29
+ GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
30
+
31
+ - name: Slack notification Success
32
+ if: success()
33
+ env:
34
+ SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
35
+ uses: cemkiy/action-slacker@master
36
+ with:
37
+ channel: '#github-ci-actions'
38
+ icon_url: 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png'
39
+ username: 'GitHub'
@@ -0,0 +1,42 @@
1
+ name: CI-TEST-CASES
2
+
3
+ on:
4
+
5
+ pull_request:
6
+ branches:
7
+ - master
8
+
9
+ jobs:
10
+ test_cases:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu]
15
+ ruby: [2.5, 2.6]
16
+
17
+ runs-on: ${{ matrix.os }}-latest
18
+ continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ with:
22
+ fetch-depth: 1
23
+ - uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+
27
+ - name: Install Dependencies v12
28
+ run: |
29
+ gem install bundler -v 1.17.3
30
+ bundle install --gemfile=Gemfile.fluentd.0.12 --jobs=4 --retry=3 --path vendor/bundle
31
+ - name: Run tests
32
+ run: |
33
+ bundle exec rake
34
+
35
+ - name: Install Dependencies
36
+ run: |
37
+ gem install bundler -v 1.17.3
38
+ bundle install --gemfile=Gemfile --jobs=4 --retry=3 --path vendor/bundle
39
+ bundle clean --force
40
+ - name: Run tests
41
+ run: |
42
+ bundle exec rake
@@ -0,0 +1,12 @@
1
+ /*.gem
2
+ ~*
3
+ #*
4
+ *~
5
+ .bundle
6
+ Gemfile.lock
7
+ vendor
8
+ doc/*
9
+ tmp/*
10
+ coverage
11
+ .yardoc
12
+ pkg/*
@@ -0,0 +1 @@
1
+ 2.6.5
@@ -0,0 +1 @@
1
+ record-splitter
@@ -0,0 +1 @@
1
+ # 0.0.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'fluentd', '~> 0.12.0'
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Naotoshi Seo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,98 @@
1
+ # fluent-plugin-record-splitter
2
+
3
+ A Fluentd plugin to split fluentd events into multiple records
4
+
5
+ ## Requirements
6
+
7
+ Fluentd >= v0.12
8
+
9
+ ## Install
10
+
11
+ Use RubyGems:
12
+
13
+ ```
14
+ gem install fluent-plugin-record-splitter
15
+ ```
16
+
17
+ ## Configuration
18
+
19
+ - tag: The output tag for the generated records.
20
+ - input_key: The target key to be splited.
21
+ - output_key: The generateed splitted key (if not specified input_key will be used).
22
+ - split_stratgey: The strategy used to splited the message should be either lines or regex.
23
+ - split_regex: Regex to split lines.
24
+ - shared_keys: List of keys to be shared between all generated records.
25
+ - remove_keys: List of keys to be removed from all generated records.
26
+ - append_new_line: Append a new line to the end of the input event.
27
+ - remove_new_line: Remove the new line form the end of the generated events.
28
+ - remove_input_key: Remove the key spcified by `input_key` from the generated events.
29
+
30
+
31
+ ## Configuration Examples
32
+
33
+ ```
34
+ <match pattern>
35
+ @type record_splitter
36
+ tag splitted.log
37
+ input_key message
38
+ split_stratgey lines
39
+ append_new_line true
40
+ remove_new_line true
41
+ shared_keys ["akey"]
42
+ </match>
43
+ ```
44
+
45
+ If following record is passed:
46
+
47
+ ```
48
+ {'akey':'c', 'abkey':'cc', 'message': 'line one\nlines2' }
49
+ ```
50
+
51
+ then you got new records like below:
52
+
53
+ ```
54
+ {'akey':'c', 'message': 'line one' }
55
+ {'akey':'c', 'message': 'lines2' }
56
+ ```
57
+
58
+ another configuration
59
+
60
+ ```
61
+ <match pattern>
62
+ @type record_splitter
63
+ tag splitted.log
64
+ input_key message
65
+ split_stratgey regex
66
+ split_regex /\d+\s<\d+>.+/
67
+ remove_keys ["akey"]
68
+ </match>
69
+ ```
70
+
71
+ If following record is passed:
72
+
73
+ ```
74
+ {'dkey':'c', 'akey':'c', 'abkey':'cc', 'message': '83 <40>1 2012-11-30T06:45:29+00:00 start app\n90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process' }
75
+ ```
76
+
77
+ then you got new records like below:
78
+
79
+ ```
80
+ {'dkey':'c', 'abkey':'cc', 'message': '83 <40>1 2012-11-30T06:45:29+00:00 start app' }
81
+ {'dkey':'c', 'abkey':'cc', 'message': '90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process' }
82
+ ```
83
+
84
+ ## ChangeLog
85
+
86
+ See [CHANGELOG.md](CHANGELOG.md) for details.
87
+
88
+ ## Contributing
89
+
90
+ 1. Fork it
91
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
92
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
93
+ 4. Push to the branch (`git push origin my-new-feature`)
94
+ 5. Create new [Pull Request](../../pull/new/master)
95
+
96
+ ## Copyright
97
+
98
+ Copyright (c) 2015 Naotoshi Seo. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ desc 'Run test_unit based test'
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.test_files = Dir["test/**/test_*.rb"].sort
9
+ t.verbose = true
10
+ #t.warning = true
11
+ end
12
+ task :default => :test
13
+
14
+ desc 'Open an irb session preloaded with the gem library'
15
+ task :console do
16
+ sh 'irb -rubygems -I lib'
17
+ end
18
+ task :c => :console
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "fluent-plugin-record-splitter"
6
+ s.version = "0.0.1"
7
+ s.authors = ["Al-waleed Shihadeh"]
8
+ s.email = ["wshihadeh.dev@gmail.com"]
9
+ s.homepage = "https://github.com/wshihadeh/fluent-plugin-record-splitter.git"
10
+ s.summary = "A Fluentd plugin to split fluentd events into multiple records"
11
+ s.description = s.summary
12
+ s.licenses = ["MIT"]
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_runtime_dependency "fluentd", ">= 0.12"
20
+ s.add_development_dependency "rake"
21
+ s.add_development_dependency "test-unit"
22
+ s.add_development_dependency "pry"
23
+ s.add_development_dependency "pry-nav"
24
+ s.add_development_dependency "test-unit-rr"
25
+ s.add_development_dependency "timecop"
26
+ end
@@ -0,0 +1,7 @@
1
+ require 'fluent/version'
2
+ major, minor, patch = Fluent::VERSION.split('.').map(&:to_i)
3
+ if major > 0 || (major == 0 && minor >= 14)
4
+ require_relative 'out_record_splitter/v14'
5
+ else
6
+ require_relative 'out_record_splitter/v12'
7
+ end
@@ -0,0 +1,83 @@
1
+ module Fluent
2
+ module RecordSplitterOutputCore
3
+ def initialize
4
+ super
5
+ end
6
+
7
+ def self.included(klass)
8
+ klass.config_param :tag, :string, default: nil, desc: 'The output tag name.'
9
+ klass.config_param :input_key, :string, default: nil, desc: 'The Target key to be splited.'
10
+ klass.config_param :remove_input_key, :bool, default: false
11
+ klass.config_param :output_key, :string, default: nil, desc: 'The generateed splitted key.'
12
+ klass.config_param :split_stratgey, :string, default: 'lines', desc: 'the strategy used to splited the message should be either lines or regex'
13
+ klass.config_param :append_new_line, :bool, default: false
14
+ klass.config_param :remove_new_line, :bool, default: false
15
+ klass.config_param :split_regex, :string, default: '/.+\n/', desc: 'Regex to split lines'
16
+ klass.config_param :shared_keys, :array, default: [], desc: 'List of keys to be shared between all generated records.'
17
+ klass.config_param :remove_keys, :array, default: [], desc: 'List of keys to be removed from all generated records.'
18
+ end
19
+
20
+ def configure(conf)
21
+ super
22
+
23
+ regex = /^\/.+\/$/
24
+
25
+ if @tag.nil?
26
+ raise Fluent::ConfigError, "out_record_splitter: `tag` must be specified"
27
+ end
28
+
29
+ if @input_key.nil?
30
+ raise Fluent::ConfigError, "out_record_splitter: `input_key` must be specified"
31
+ end
32
+
33
+ if @output_key.nil?
34
+ @output_key = @input_key
35
+ end
36
+
37
+ if !@shared_keys.empty? && !@remove_keys.empty?
38
+ raise Fluent::ConfigError, 'Cannot set both shared_keys and remove_keys.'
39
+ end
40
+
41
+ if regex.match(@split_regex.to_s)
42
+ @split_regex = Regexp.new(@split_regex[1..-2])
43
+ end
44
+ end
45
+
46
+ def process(tag, es)
47
+ es.each do |time, record|
48
+ common_keys = if !@shared_keys.empty?
49
+ record.select { |key, _value| @shared_keys.include?(key) }
50
+ elsif !@remove_keys.empty?
51
+ record.reject { |key, _value| @remove_keys.include?(key) }
52
+ else
53
+ record.dup
54
+ end
55
+
56
+ if @remove_input_key && @output_key != @input_key
57
+ common_keys.delete(@input_key)
58
+ end
59
+
60
+ next unless record.key?(@input_key)
61
+ message = record[@input_key]
62
+ lines = split_lines message
63
+
64
+ lines.each do |l|
65
+ keys = common_keys.merge(@output_key => l)
66
+ router.emit(@tag, time, keys)
67
+ end
68
+ end
69
+ end
70
+
71
+ def split_lines(message)
72
+ message = "#{message}\n" if @append_new_line
73
+
74
+ messages = if @split_stratgey == 'lines'
75
+ message.to_s.lines
76
+ else
77
+ message.scan(@split_regex)
78
+ end
79
+ messages = messages.map{|m| m.gsub("\n",'') } if @remove_new_line
80
+ messages
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'core'
2
+
3
+ module Fluent
4
+ class RecordSplitterOutput < Output
5
+ Fluent::Plugin.register_output('record_splitter', self)
6
+
7
+ include ::Fluent::RecordSplitterOutputCore
8
+
9
+ def initialize
10
+ super
11
+ end
12
+
13
+ # To support log_level option implemented by Fluentd v0.10.43
14
+ unless method_defined?(:log)
15
+ define_method("log") { $log }
16
+ end
17
+
18
+ # Define `router` method of v0.12 to support v0.10 or earlier
19
+ unless method_defined?(:router)
20
+ define_method("router") { Fluent::Engine }
21
+ end
22
+
23
+ def configure(conf)
24
+ super
25
+ end
26
+
27
+ def emit(tag, es, chain)
28
+ process(tag, es)
29
+ chain.next
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'core'
2
+
3
+ module Fluent
4
+ class Plugin::RecordSplitterOutput < Plugin::Output
5
+ Fluent::Plugin.register_output('record_splitter', self)
6
+
7
+ helpers :event_emitter
8
+ include ::Fluent::RecordSplitterOutputCore
9
+
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ def configure(conf)
15
+ super
16
+ end
17
+
18
+ def multi_workers_ready?
19
+ true
20
+ end
21
+
22
+ def process(tag, es)
23
+ super
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ require 'test/unit'
2
+ require 'fluent/log'
3
+ require 'fluent/test'
4
+ require 'test/unit/rr'
5
+ require 'timecop'
6
+
7
+ unless defined?(Test::Unit::AssertionFailedError)
8
+ class Test::Unit::AssertionFailedError < StandardError
9
+ end
10
+ end
11
+
12
+ # Reduce sleep period at
13
+ # https://github.com/fluent/fluentd/blob/a271b3ec76ab7cf89ebe4012aa5b3912333dbdb7/lib/fluent/test/base.rb#L81
14
+ module Fluent
15
+ module Test
16
+ class TestDriver
17
+ def run(num_waits = 10, &block)
18
+ @instance.start
19
+ begin
20
+ # wait until thread starts
21
+ # num_waits.times { sleep 0.05 }
22
+ sleep 0.05
23
+ return yield
24
+ ensure
25
+ @instance.shutdown
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ require_relative 'output_test_driver'
@@ -0,0 +1,42 @@
1
+ require 'fluent/version'
2
+ major, minor, patch = Fluent::VERSION.split('.').map(&:to_i)
3
+ if major > 0 || (major == 0 && minor >= 14)
4
+ require 'fluent/test/driver/output'
5
+ require 'fluent/test/helpers'
6
+ include Fluent::Test::Helpers
7
+
8
+ class OutputTestDriver < Fluent::Test::Driver::Output
9
+ def initialize(klass, tag)
10
+ super(klass)
11
+ @tag = tag
12
+ end
13
+
14
+ def configure(conf, use_v1)
15
+ super(conf, syntax: use_v1 ? :v1 : :v0)
16
+ end
17
+
18
+ def run(&block)
19
+ super(default_tag: @tag, &block)
20
+ end
21
+
22
+ def emit(record, time)
23
+ feed(time, record)
24
+ end
25
+
26
+ def emits
27
+ events
28
+ end
29
+ end
30
+
31
+ def create_driver(conf, use_v1, default_tag: @tag)
32
+ OutputTestDriver.new(Fluent::Plugin::RecordSplitterOutput, default_tag).configure(conf, use_v1)
33
+ end
34
+ else
35
+ def event_time(str)
36
+ Time.parse(str)
37
+ end
38
+
39
+ def create_driver(conf, use_v1, default_tag: @tag)
40
+ Fluent::Test::OutputTestDriver.new(Fluent::RecordSplitterOutput, default_tag).configure(conf, use_v1)
41
+ end
42
+ end
@@ -0,0 +1,288 @@
1
+ require_relative 'helper'
2
+ require 'time'
3
+ require 'fluent/plugin/out_record_splitter'
4
+
5
+ Fluent::Test.setup
6
+
7
+ class RecordSplitterOutpuTest < Test::Unit::TestCase
8
+ def emit(config, use_v1, msgs = [''])
9
+ d = create_driver(config, use_v1)
10
+ d.run do
11
+ records = msgs.map do |msg|
12
+ next msg if msg.is_a?(Hash)
13
+ {'message' => msg }
14
+ end
15
+ records.each do |record|
16
+ d.emit(record, @time)
17
+ end
18
+ end
19
+
20
+ @instance = d.instance
21
+ d.emits
22
+ end
23
+
24
+ setup do
25
+ @tag = 'splitter.log'
26
+ @time = event_time("2020-06-24 03:02:01")
27
+ Timecop.freeze(@time)
28
+ end
29
+
30
+ teardown do
31
+ Timecop.return
32
+ end
33
+
34
+ [true, false].each do |use_v1|
35
+ sub_test_case 'configure' do
36
+ test 'missing input key' do
37
+ assert_raise(Fluent::ConfigError) do
38
+ create_driver(%[
39
+ tag test.tag
40
+ ], use_v1)
41
+ end
42
+ end
43
+
44
+ test 'missing input tag' do
45
+ assert_raise(Fluent::ConfigError) do
46
+ create_driver(%[
47
+ input_key x
48
+ ], use_v1)
49
+ end
50
+ end
51
+
52
+ test 'config conflict' do
53
+ assert_raise(Fluent::ConfigError) do
54
+ create_driver(%[
55
+ input_key x
56
+ tag test.tag
57
+ shared_keys x
58
+ remove_keys y
59
+ ], use_v1)
60
+ end
61
+ end
62
+
63
+ test 'typical usage' do
64
+ assert_nothing_raised do
65
+ create_driver(%[
66
+ tag test.tag
67
+ input_key log
68
+ ], use_v1)
69
+ end
70
+ end
71
+ end
72
+
73
+ sub_test_case 'test split lines' do
74
+
75
+ test 'Split message on new line' do
76
+ config = <<EOC
77
+ tag test.tag
78
+ input_key message
79
+ EOC
80
+ msgs = ["0\n1\n2\n3"]
81
+ emits = emit(config, use_v1, msgs)
82
+ emits.each_with_index do |(tag, _time, record), i|
83
+ assert_equal('test.tag', tag)
84
+ assert_equal(record['message'].gsub("\n",''), i.to_s)
85
+ end
86
+ end
87
+
88
+ test 'Wrong input key' do
89
+ config = <<EOC
90
+ tag test.tag
91
+ input_key wrong
92
+ EOC
93
+ msgs = ["0\n1\n2\n3"]
94
+ emits = emit(config, use_v1, msgs)
95
+ assert_equal(emits.count, 0)
96
+ end
97
+
98
+ test 'copy to a new key' do
99
+ config = <<EOC
100
+ tag test.tag
101
+ input_key message
102
+ output_key log
103
+ EOC
104
+ msgs = ["0\n1\n2\n3"]
105
+ emits = emit(config, use_v1, msgs)
106
+ emits.each_with_index do |(tag, _time, record), i|
107
+ assert_equal('test.tag', tag)
108
+ assert_equal(record['log'].gsub("\n",''), i.to_s)
109
+ assert_equal(record['message'], "0\n1\n2\n3")
110
+ end
111
+ end
112
+
113
+ test 'remove input key' do
114
+ config = <<EOC
115
+ tag test.tag
116
+ input_key message
117
+ output_key log
118
+ remove_input_key true
119
+ EOC
120
+ msgs = ["0\n1\n2\n3"]
121
+ emits = emit(config, use_v1, msgs)
122
+ assert_equal(emits.count, 4)
123
+ emits.each_with_index do |(tag, _time, record), i|
124
+ assert_equal('test.tag', tag)
125
+ assert_equal(record['log'].gsub("\n",''), i.to_s)
126
+ assert_equal(record['message'], nil)
127
+ end
128
+ end
129
+
130
+ test 'remove new line' do
131
+ config = <<EOC
132
+ tag test.tag
133
+ input_key message
134
+ output_key log
135
+ remove_input_key true
136
+ remove_new_line true
137
+ EOC
138
+ msgs = ["0\n1\n2\n3"]
139
+ emits = emit(config, use_v1, msgs)
140
+ assert_equal(emits.count, 4)
141
+ emits.each_with_index do |(tag, _time, record), i|
142
+ assert_equal('test.tag', tag)
143
+ assert_equal(record['log'], i.to_s)
144
+ assert_equal(record['message'], nil)
145
+ end
146
+ end
147
+
148
+ test 'remove input key with append_new_line' do
149
+ config = <<EOC
150
+ tag test.tag
151
+ input_key message
152
+ output_key log
153
+ remove_input_key true
154
+ append_new_line true
155
+ EOC
156
+ msgs = ["0\n1\n2\n3"]
157
+ emits = emit(config, use_v1, msgs)
158
+ assert_equal(emits.count, 4)
159
+ emits.each_with_index do |(tag, _time, record), i|
160
+ assert_equal('test.tag', tag)
161
+ assert_equal(record['log'].gsub("\n",''), i.to_s)
162
+ assert_equal(record['message'], nil)
163
+ end
164
+ end
165
+
166
+ test 'keep shared keys' do
167
+ config = <<EOC
168
+ tag test.tag
169
+ input_key message
170
+ output_key log
171
+ shared_keys ["ckey", "bkey"]
172
+ EOC
173
+ msgs = [{ 'message' => "0\n1\n2\n3", 'akey' => 1, 'bkey' => 2, 'ckey' => 3, 'dkey' => 4 }]
174
+ emits = emit(config, use_v1, msgs)
175
+ assert_equal(emits.count, 4)
176
+ emits.each_with_index do |(tag, _time, record), i|
177
+ assert_equal('test.tag', tag)
178
+ assert_equal(record['log'].gsub("\n",''), i.to_s)
179
+ assert_equal(record['ckey'], 3)
180
+ assert_equal(record['bkey'], 2)
181
+ assert_equal(record['message'], nil)
182
+ assert_equal(record['akey'], nil)
183
+ end
184
+ end
185
+
186
+ test 'remove keys' do
187
+ config = <<EOC
188
+ tag test.tag
189
+ input_key message
190
+ output_key log
191
+ remove_keys ["ckey", "bkey"]
192
+ EOC
193
+ msgs = [{ 'message' => "0\n1\n2\n3", 'akey' => 1, 'bkey' => 2, 'ckey' => 3, 'dkey' => 4 }]
194
+ emits = emit(config, use_v1, msgs)
195
+ assert_equal(emits.count, 4)
196
+ emits.each_with_index do |(tag, _time, record), i|
197
+ assert_equal('test.tag', tag)
198
+ assert_equal(record['log'].gsub("\n",''), i.to_s)
199
+ assert_equal(record['ckey'], nil)
200
+ assert_equal(record['bkey'], nil)
201
+ assert_equal(record['message'], "0\n1\n2\n3")
202
+ assert_equal(record['akey'], 1)
203
+ end
204
+ end
205
+ end
206
+
207
+ sub_test_case 'test split lines with regex' do
208
+
209
+ test 'Split message on new line' do
210
+ config = <<EOC
211
+ tag test.tag
212
+ input_key message
213
+ split_stratgey regex
214
+ EOC
215
+ msgs = ["0\n1\n2\n3\n"]
216
+ emits = emit(config, use_v1, msgs)
217
+ assert_equal(emits.count, 4)
218
+ emits.each_with_index do |(tag, _time, record), i|
219
+ assert_equal('test.tag', tag)
220
+ assert_equal(record['message'].gsub("\n",''), i.to_s)
221
+ end
222
+ end
223
+
224
+ test 'Split message with append_new_line' do
225
+ config = <<EOC
226
+ tag test.tag
227
+ input_key message
228
+ split_stratgey regex
229
+ append_new_line true
230
+ EOC
231
+ msgs = ["0\n1\n2\n3"]
232
+ emits = emit(config, use_v1, msgs)
233
+ assert_equal(emits.count, 4)
234
+ emits.each_with_index do |(tag, _time, record), i|
235
+ assert_equal('test.tag', tag)
236
+ assert_equal(record['message'].gsub("\n",''), i.to_s)
237
+ end
238
+ end
239
+
240
+ test 'Split message with remove_new_line true' do
241
+ config = <<EOC
242
+ tag test.tag
243
+ input_key message
244
+ split_stratgey regex
245
+ append_new_line true
246
+ remove_new_line true
247
+
248
+ EOC
249
+ msgs = ["0\n1\n2\n3"]
250
+ emits = emit(config, use_v1, msgs)
251
+ assert_equal(emits.count, 4)
252
+ emits.each_with_index do |(tag, _time, record), i|
253
+ assert_equal('test.tag', tag)
254
+ assert_equal(record['message'], i.to_s)
255
+ end
256
+ end
257
+
258
+ test 'Split message with custom regex and append_new_line' do
259
+ config = <<EOC
260
+ tag test.tag
261
+ input_key message
262
+ split_stratgey regex
263
+ split_regex /\\d+\\s<\\d+>.+\\n/
264
+ append_new_line true
265
+ EOC
266
+ msgs = ["83 <40>1 2012-11-30T06:45:29+00:00 start app\n90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process"]
267
+ emits = emit(config, use_v1, msgs)
268
+ assert_equal(emits.count, 2)
269
+ assert_equal(emits.first[2]['message'], "83 <40>1 2012-11-30T06:45:29+00:00 start app\n")
270
+ assert_equal(emits.last[2]['message'], "90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process\n")
271
+ end
272
+
273
+ test 'Split message with custom regex' do
274
+ config = <<EOC
275
+ tag test.tag
276
+ input_key message
277
+ split_stratgey regex
278
+ split_regex /\\d+\\s<\\d+>.+/
279
+ EOC
280
+ msgs = ["83 <40>1 2012-11-30T06:45:29+00:00 start app\n90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process"]
281
+ emits = emit(config, use_v1, msgs)
282
+ assert_equal(emits.count, 2)
283
+ assert_equal(emits.first[2]['message'], "83 <40>1 2012-11-30T06:45:29+00:00 start app")
284
+ assert_equal(emits.last[2]['message'], "90 <40>1 2012-11-30T06:45:26+00:00 host app web.3 - Starting process")
285
+ end
286
+ end
287
+ end
288
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-record-splitter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Al-waleed Shihadeh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.12'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-nav
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: test-unit-rr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: timecop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A Fluentd plugin to split fluentd events into multiple records
112
+ email:
113
+ - wshihadeh.dev@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".github/workflows/ci-release-gem.yml"
119
+ - ".github/workflows/ci-test-cases.yml"
120
+ - ".gitignore"
121
+ - ".rbenv-version"
122
+ - ".ruby-gemset"
123
+ - CHANGELOG.md
124
+ - Gemfile
125
+ - Gemfile.fluentd.0.12
126
+ - LICENSE
127
+ - README.md
128
+ - Rakefile
129
+ - fluent-plugin-record-splitter.gemspec
130
+ - lib/fluent/plugin/out_record_splitter.rb
131
+ - lib/fluent/plugin/out_record_splitter/core.rb
132
+ - lib/fluent/plugin/out_record_splitter/v12.rb
133
+ - lib/fluent/plugin/out_record_splitter/v14.rb
134
+ - test/helper.rb
135
+ - test/output_test_driver.rb
136
+ - test/test_out_record_splitter.rb
137
+ homepage: https://github.com/wshihadeh/fluent-plugin-record-splitter.git
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubygems_version: 3.0.3
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: A Fluentd plugin to split fluentd events into multiple records
160
+ test_files: []