fluent-plugin-record-splitter 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.
- checksums.yaml +7 -0
- data/.github/workflows/ci-release-gem.yml +39 -0
- data/.github/workflows/ci-test-cases.yml +42 -0
- data/.gitignore +12 -0
- data/.rbenv-version +1 -0
- data/.ruby-gemset +1 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +3 -0
- data/Gemfile.fluentd.0.12 +4 -0
- data/LICENSE +22 -0
- data/README.md +98 -0
- data/Rakefile +18 -0
- data/fluent-plugin-record-splitter.gemspec +26 -0
- data/lib/fluent/plugin/out_record_splitter.rb +7 -0
- data/lib/fluent/plugin/out_record_splitter/core.rb +83 -0
- data/lib/fluent/plugin/out_record_splitter/v12.rb +32 -0
- data/lib/fluent/plugin/out_record_splitter/v14.rb +26 -0
- data/test/helper.rb +32 -0
- data/test/output_test_driver.rb +42 -0
- data/test/test_out_record_splitter.rb +288 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.rbenv-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.5
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
record-splitter
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# 0.0.1
|
data/Gemfile
ADDED
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.
|
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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,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
|
data/test/helper.rb
ADDED
@@ -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: []
|