fluent-plugin-json-by-name 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de1b7254b02e90e313f58420fc68d907c3bf430f03f6cd4e5e9c9fb5817114d2
4
+ data.tar.gz: 231703f04dda952f44f30af034ba167a5939498dec830f0e0377b2a4e0501a3a
5
+ SHA512:
6
+ metadata.gz: 359a8700afc9d93d1648faf8d88a24e88ac0a790725eaf0c6d1e07adab794566b4f1895a2ec9a9572ba9191a9e1ec8775a89dda1c34c73b2b82d940eaa419013
7
+ data.tar.gz: e57c8a3305e04187ce93dfb9345ff456d95f5365d8d0229ec4dd2b613b008d42ab4a4dc1241e1d0e5b6f1bc6d97f10db327cd9933f603459bb2a6eb845196b73
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-json-by-name (0.1.0)
5
+ fluentd (~> 1.15, >= 1.15.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ concurrent-ruby (1.2.2)
11
+ cool.io (1.7.1)
12
+ fluentd (1.15.3)
13
+ bundler
14
+ cool.io (>= 1.4.5, < 2.0.0)
15
+ http_parser.rb (>= 0.5.1, < 0.9.0)
16
+ msgpack (>= 1.3.1, < 2.0.0)
17
+ serverengine (>= 2.3.0, < 3.0.0)
18
+ sigdump (~> 0.2.2)
19
+ strptime (>= 0.2.4, < 1.0.0)
20
+ tzinfo (>= 1.0, < 3.0)
21
+ tzinfo-data (~> 1.0)
22
+ webrick (>= 1.4.2, < 1.8.0)
23
+ yajl-ruby (~> 1.0)
24
+ http_parser.rb (0.8.0)
25
+ msgpack (1.6.1)
26
+ power_assert (2.0.2)
27
+ rake (13.0.6)
28
+ serverengine (2.3.2)
29
+ sigdump (~> 0.2.2)
30
+ sigdump (0.2.4)
31
+ strptime (0.2.5)
32
+ test-unit (3.5.5)
33
+ power_assert
34
+ tzinfo (2.0.6)
35
+ concurrent-ruby (~> 1.0)
36
+ tzinfo-data (1.2023.1)
37
+ tzinfo (>= 1.0.0)
38
+ webrick (1.7.0)
39
+ yajl-ruby (1.4.3)
40
+
41
+ PLATFORMS
42
+ x86_64-linux
43
+
44
+ DEPENDENCIES
45
+ fluent-plugin-json-by-name!
46
+ rake (~> 13.0, >= 13.0.6)
47
+ test-unit (~> 3.1, >= 3.1.0)
48
+
49
+ BUNDLED WITH
50
+ 2.3.7
data/Makefile ADDED
@@ -0,0 +1,43 @@
1
+ .PHONY: deps
2
+ deps: deps-npm deps-ruby
3
+
4
+ .PHONY: deps-npm
5
+ deps-npm: node_modules
6
+
7
+ node_modules: package.json
8
+ npm install
9
+
10
+ .PHONY: deps-ruby
11
+ deps-ruby:
12
+ bundle install
13
+
14
+ .PHONY: lint
15
+ lint: lint-md
16
+
17
+ .PHONY: lint-fix
18
+ lint-fix: lint-md-fix
19
+
20
+ .PHONY: lint-md
21
+ lint-md: node_modules
22
+ npx remark .
23
+
24
+ .PHONY: lint-md-fix
25
+ lint-md-fix: node_modules
26
+ npx remark . -o
27
+
28
+ .PHONY: build
29
+ build: build-ruby
30
+
31
+ .PHONY: build-ruby
32
+ build-ruby:
33
+ rake build
34
+
35
+ .PHONY: test
36
+ test: test-ruby
37
+
38
+ .PHONY: test-ruby
39
+ test-ruby:
40
+ rake test
41
+
42
+ .PHONY: all
43
+ all: deps-ruby build
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # fluent-plugin-json-by-name
2
+
3
+ ## what does this plugin do
4
+
5
+ With this plugin you can add json fields as fluent field by the name of the
6
+ json field
7
+
8
+ ## Configuration
9
+
10
+ For just indexing, provide the fields with value null in json:
11
+
12
+ ```xml
13
+ <filter **>
14
+ @type json_by_name
15
+ fields_to_index {
16
+ "test1": null,
17
+ "test2": null,
18
+ "test3": null
19
+ }
20
+ </filter>
21
+ ```
22
+
23
+ If you also want to rename the field, provide a new name as string instead of
24
+ null. All this also works for nested fields:
25
+
26
+ ```xml
27
+ <filter **>
28
+ @type json_by_name
29
+ fields_to_index {
30
+ "test1": null,
31
+ "test2": "this_was_field_test2",
32
+ "nested": {
33
+ "test3": null,
34
+ "test4": "this_was_nested_field_test4"
35
+ }
36
+ }
37
+ </filter>
38
+ ```
39
+
40
+ Assuming the above config, then the plugin would act as follows:
41
+
42
+ ### Inputs
43
+
44
+ ```json
45
+ {"message": "{\"test1\": true}"}
46
+ {"message": "{\"test2\": true}"}
47
+ {"message": "{\"nested\": {\"test3\": true}}"}
48
+ {"message": "{\"nested\": {\"test4\": true}}"}
49
+ ```
50
+
51
+ ### Outputs
52
+
53
+ ```json
54
+ {"message": "{\"test1\": true}", "test1": true}
55
+ {"message": "{\"test2\": true}", "this_was_field_test2": true}
56
+ {"message": "{\"nested\": {\"test3\": true}}", "nested.test3": true}
57
+ {"message": "{\"nested\": {\"test4\": true}}", "this_was_nested_field_test4": true}
58
+ ```
59
+
60
+ More examples can be found in `test/plugin/test_filter_json_by_name.rb`
61
+
62
+ ## Testing
63
+
64
+ ```sh
65
+ bundle install
66
+ rake
67
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rake/testtask"
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
data/build.sh ADDED
@@ -0,0 +1,2 @@
1
+ bundle install
2
+ bundle exec rake build
@@ -0,0 +1,12 @@
1
+ require_relative 'lib/release/fluent_plugin_json_by_name/version'
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'fluent-plugin-json-by-name'
5
+ gem.version = FluentPluginJsonByName::VERSION
6
+ gem.summary = "Fluentd filter plugin to reshape json"
7
+ gem.authors = "platform+rubygems@riskident.com"
8
+ gem.files = `find *`.split("\n").uniq.sort.select{|f| !f.empty? }
9
+ gem.add_runtime_dependency 'fluentd', '~> 1.15', '>= 1.15.3'
10
+ gem.add_development_dependency 'rake', '~> 13.0', '>= 13.0.6'
11
+ gem.add_development_dependency "test-unit", '~> 3.1', '>= 3.1.0'
12
+ end
@@ -0,0 +1,62 @@
1
+ require 'fluent/plugin/filter'
2
+
3
+ module Fluent::Plugin
4
+
5
+ class JsonByName < Filter
6
+ Fluent::Plugin.register_filter('json_by_name', self)
7
+
8
+ helpers :record_accessor
9
+
10
+ desc 'A hash/JSON object of fields to index and rename from log messages.'
11
+ config_param :fields_to_index, :hash, default: nil
12
+
13
+ def configure(conf)
14
+ super
15
+ validate_config(fields_to_index)
16
+ end
17
+
18
+ def combine_path(path, element)
19
+ return element if path.nil?
20
+ return "#{path}.#{element}"
21
+ end
22
+
23
+ def validate_config(fields_to_index_remaining, path=nil)
24
+ if fields_to_index_remaining.class == Hash then
25
+ fields_to_index_remaining.keys.each do |key|
26
+ validate_config(fields_to_index_remaining[key], combine_path(path, key))
27
+ end
28
+ return
29
+ elsif fields_to_index_remaining.nil? or fields_to_index_remaining.class == String then
30
+ return
31
+ end
32
+ raise Fluent::ConfigError.new("value at \"#{path}\" in config is not either object, string, or null")
33
+ end
34
+
35
+ def reshape(record, fields_to_index_remaining, data, path=nil)
36
+ return if data == nil
37
+ if fields_to_index_remaining.class == Hash and data.class == Hash then
38
+ common_keys = Set.new(fields_to_index_remaining.keys) & Set.new(data.keys)
39
+ common_keys.each do |key|
40
+ reshape(record, fields_to_index_remaining[key], data[key], combine_path(path, key))
41
+ end
42
+ elsif fields_to_index_remaining.nil? then
43
+ record[path] = data
44
+ elsif fields_to_index_remaining.class == String then
45
+ record[fields_to_index_remaining] = data
46
+ end
47
+ end
48
+
49
+ def filter(tag, time, record)
50
+ return record if record["message"] == nil
51
+ begin
52
+ record_as_json = JSON.parse(record["message"])
53
+ rescue JSON::ParserError
54
+ return record
55
+ end
56
+
57
+ reshape(record, fields_to_index, record_as_json)
58
+
59
+ return record
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,3 @@
1
+ module FluentPluginJsonByName
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/package.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "remarkConfig": ".remarkrc",
3
+ "devDependencies": {
4
+ "remark-cli": "^11.0.0",
5
+ "remark-gfm": "^3.0.1",
6
+ "remark-lint": "^9.1.1",
7
+ "remark-preset-lint-markdown-style-guide": "^5.1.2"
8
+ }
9
+ }
data/publish.sh ADDED
@@ -0,0 +1,3 @@
1
+ mkdir -p -- /root/.gem/
2
+ gem build *.gemspec
3
+ gem push *.gem
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler/setup'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.join(__dir__, '..', 'lib'))
5
+ $LOAD_PATH.unshift(__dir__)
6
+ require 'fluent/test'
7
+ require 'fluent/test/driver/filter'
8
+ require 'fluent/test/helpers'
9
+
10
+ Test::Unit::TestCase.include(Fluent::Test::Helpers)
11
+
12
+ require 'fluent/plugin/filter_json_by_name'
@@ -0,0 +1,92 @@
1
+ require 'helper'
2
+
3
+ class JsonByNameTest < Test::Unit::TestCase
4
+ include Fluent::Test::Helpers
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ fields_to_index {
11
+ "test1": null,
12
+ "test2": "this_was_field_test2",
13
+ "nested": {
14
+ "test3": null,
15
+ "test4": "this_was_field_test4"
16
+ },
17
+ "nonnested.test5": null,
18
+ "nonnested.test6": "this_was_field_test6"
19
+ }
20
+ ]
21
+
22
+ def create_driver(config)
23
+ Fluent::Test::Driver::Filter.new(Fluent::Plugin::JsonByName).configure(config)
24
+ end
25
+
26
+ def run_plugin(message, config = CONFIG)
27
+ d = create_driver(config)
28
+ d.run(default_tag: "test") do
29
+ d.feed(Fluent::Engine.now, {"message" => message})
30
+ end
31
+ return d.filtered_records
32
+ end
33
+
34
+ def assert_message(original_message, result, added_fields)
35
+ message = {"message" => original_message}
36
+ full_message = message.merge(added_fields)
37
+ assert_equal([full_message], result)
38
+ end
39
+
40
+ def run_and_assert(message, added_fields, config = CONFIG)
41
+ result = run_plugin(message, config)
42
+ assert_message(message, result, added_fields)
43
+ end
44
+
45
+ test 'valid config validates' do
46
+ assert_nothing_raised(RuntimeError) {
47
+ create_driver(CONFIG)
48
+ }
49
+ end
50
+
51
+ test 'invalid config fails validation' do
52
+ assert_raise(Fluent::ConfigError.new("value at \"foo.invalid_config\" in config is not either object, string, or null")) {
53
+ create_driver(<<-CONFIG)
54
+ fields_to_index {
55
+ "foo": {
56
+ "rename_given_name": "renamename",
57
+ "invalid_config" : true,
58
+ "rename_same_name" : null
59
+ }
60
+ }
61
+ CONFIG
62
+ }
63
+ end
64
+
65
+ test 'invalid json is left as is' do
66
+ run_and_assert("this_is_not_json", {})
67
+ end
68
+
69
+ test 'indexing field' do
70
+ run_and_assert("{\"test1\":true}", {"test1" => true})
71
+ end
72
+
73
+ test 'indexing and renaming field' do
74
+ run_and_assert("{\"test2\":true}", {"this_was_field_test2" => true})
75
+ end
76
+
77
+ test 'indexing nested field' do
78
+ run_and_assert("{\"nested\":{\"test3\":true}}", {"nested.test3" => true})
79
+ end
80
+
81
+ test 'indexing and renaming nested field' do
82
+ run_and_assert("{\"nested\":{\"test4\":true}}", {"this_was_field_test4" => true})
83
+ end
84
+
85
+ test 'indexing field with "." in name' do
86
+ run_and_assert("{\"nonnested.test5\":true}", {"nonnested.test5" => true})
87
+ end
88
+
89
+ test 'indexing and renaming field with "." in name' do
90
+ run_and_assert("{\"nonnested.test6\":true}", {"this_was_field_test6" => true})
91
+ end
92
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-json-by-name
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - platform+rubygems@riskident.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-24 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: '1.15'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.15.3
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.15'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.15.3
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '13.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 13.0.6
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '13.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 13.0.6
53
+ - !ruby/object:Gem::Dependency
54
+ name: test-unit
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.1'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.1.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.1'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.1.0
73
+ description:
74
+ email:
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - Makefile
82
+ - README.md
83
+ - Rakefile
84
+ - build.sh
85
+ - fluent_plugin_json_by_name.gemspec
86
+ - lib/fluent/plugin/filter_json_by_name.rb
87
+ - lib/release/fluent_plugin_json_by_name/version.rb
88
+ - package.json
89
+ - pkg/fluent-plugin-json-by-name-0.1.0.gem
90
+ - publish.sh
91
+ - test/helper.rb
92
+ - test/plugin/test_filter_json_by_name.rb
93
+ homepage:
94
+ licenses: []
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.3.26
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Fluentd filter plugin to reshape json
115
+ test_files: []