fluent-plugin-remove-empty 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/Gemfile +3 -0
- data/README.md +9 -0
- data/fluent-plugin-remove-empty.gemspec +25 -0
- data/lib/fluent/plugin/out_remove_empty.rb +176 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c27b47de51f0e72ef214b0d5c1951bd9922168d5
|
4
|
+
data.tar.gz: 2601881938c556aa5b6478ab1363afb12d1abfa8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1dc1429b3686c5f6c498f202a57dc9b09fc15f443880b0623602aac247e0eee5ee3dddccbd2976dddc2b3db79a38415fb73dc494ca348e465d9207a2e825afb7
|
7
|
+
data.tar.gz: ef9cb7638d5c22438bae04da151efc50183d438357b10417ca7ee2de77ee981eae879ad1c96dd01fd4958a2a872fe4f5e99ddfc14f30a90b757cabda1bee0380
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "fluent-plugin-remove-empty"
|
6
|
+
gem.version = "0.0.1"
|
7
|
+
gem.authors = ["Chadin Anuwattanaporn"]
|
8
|
+
gem.email = "chadin@sogamo.com"
|
9
|
+
gem.homepage = "https://github.com/newcmd001/fluent-plugin-remove-empty"
|
10
|
+
gem.description = "Fluentd plugin to remove empty fields of a event record"
|
11
|
+
gem.summary = gem.description
|
12
|
+
gem.licenses = ["MIT"]
|
13
|
+
gem.has_rdoc = false
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
16
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.add_dependency "fluentd", "~> 0.10.17"
|
21
|
+
gem.add_development_dependency "rake"
|
22
|
+
gem.add_development_dependency "rspec"
|
23
|
+
gem.add_development_dependency "pry"
|
24
|
+
gem.add_development_dependency "pry-nav"
|
25
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
class RemoveEmptyOutput < Output
|
6
|
+
Fluent::Plugin.register_output('remove_empty', self)
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
config_param :tag, :string, :default => nil
|
13
|
+
|
14
|
+
BUILTIN_CONFIGURATIONS = %W(type tag)
|
15
|
+
|
16
|
+
# To support log_level option implemented by Fluentd v0.10.43
|
17
|
+
unless method_defined?(:log)
|
18
|
+
define_method("log") { $log }
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure(conf)
|
22
|
+
super
|
23
|
+
|
24
|
+
@map = {}
|
25
|
+
conf.each_pair { |k, v|
|
26
|
+
next if BUILTIN_CONFIGURATIONS.include?(k)
|
27
|
+
conf.has_key?(k) # to suppress unread configuration warning
|
28
|
+
@map[k] = v
|
29
|
+
}
|
30
|
+
|
31
|
+
if @tag.nil?
|
32
|
+
raise Fluent::ConfigError, "out_remove_empty: `tag` must be specified"
|
33
|
+
end
|
34
|
+
|
35
|
+
@placeholder_expander =
|
36
|
+
if @enable_ruby
|
37
|
+
# require utilities which would be used in ruby placeholders
|
38
|
+
require 'pathname'
|
39
|
+
require 'uri'
|
40
|
+
require 'cgi'
|
41
|
+
RubyPlaceholderExpander.new(log)
|
42
|
+
else
|
43
|
+
PlaceholderExpander.new(log)
|
44
|
+
end
|
45
|
+
|
46
|
+
@hostname = Socket.gethostname
|
47
|
+
end
|
48
|
+
|
49
|
+
def emit(tag, es, chain)
|
50
|
+
tag_parts = tag.split('.')
|
51
|
+
tag_prefix = tag_prefix(tag_parts)
|
52
|
+
tag_suffix = tag_suffix(tag_parts)
|
53
|
+
placeholders = {
|
54
|
+
'tag' => tag,
|
55
|
+
'tags' => tag_parts,
|
56
|
+
'tag_parts' => tag_parts,
|
57
|
+
'tag_prefix' => tag_prefix,
|
58
|
+
'tag_suffix' => tag_suffix,
|
59
|
+
'hostname' => @hostname,
|
60
|
+
}
|
61
|
+
last_record = nil
|
62
|
+
es.each {|time, record|
|
63
|
+
last_record = record # for debug log
|
64
|
+
new_tag, new_record = reform(@tag, time, record, placeholders)
|
65
|
+
Engine.emit(new_tag, time, new_record)
|
66
|
+
}
|
67
|
+
chain.next
|
68
|
+
rescue => e
|
69
|
+
log.warn "remove_empty: #{e.class} #{e.message} #{e.backtrace.first}"
|
70
|
+
log.debug "remove_empty: tag:#{@tag} map:#{@map} record:#{last_record} placeholders:#{placeholders}"
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def reform(tag, time, record, opts)
|
76
|
+
@placeholder_expander.prepare_placeholders(time, record, opts)
|
77
|
+
new_tag = @placeholder_expander.expand(tag)
|
78
|
+
|
79
|
+
new_record = record.dup
|
80
|
+
new_record.each_key do |k|
|
81
|
+
if new_record[k] == ""
|
82
|
+
new_record.delete(k)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
[new_tag, new_record]
|
87
|
+
end
|
88
|
+
|
89
|
+
def tag_prefix(tag_parts)
|
90
|
+
return [] if tag_parts.empty?
|
91
|
+
tag_prefix = [tag_parts.first]
|
92
|
+
1.upto(tag_parts.size-1).each do |i|
|
93
|
+
tag_prefix[i] = "#{tag_prefix[i-1]}.#{tag_parts[i]}"
|
94
|
+
end
|
95
|
+
tag_prefix
|
96
|
+
end
|
97
|
+
|
98
|
+
def tag_suffix(tag_parts)
|
99
|
+
return [] if tag_parts.empty?
|
100
|
+
rev_tag_parts = tag_parts.reverse
|
101
|
+
rev_tag_suffix = [rev_tag_parts.first]
|
102
|
+
1.upto(tag_parts.size-1).each do |i|
|
103
|
+
rev_tag_suffix[i] = "#{rev_tag_parts[i]}.#{rev_tag_suffix[i-1]}"
|
104
|
+
end
|
105
|
+
rev_tag_suffix.reverse
|
106
|
+
end
|
107
|
+
|
108
|
+
class PlaceholderExpander
|
109
|
+
attr_reader :placeholders, :log
|
110
|
+
|
111
|
+
def initialize(log)
|
112
|
+
@log = log
|
113
|
+
end
|
114
|
+
|
115
|
+
def prepare_placeholders(time, record, opts)
|
116
|
+
placeholders = { '${time}' => Time.at(time).to_s }
|
117
|
+
record.each {|key, value| placeholders.store("${#{key}}", value) }
|
118
|
+
|
119
|
+
opts.each do |key, value|
|
120
|
+
if value.kind_of?(Array) # tag_parts, etc
|
121
|
+
size = value.size
|
122
|
+
value.each_with_index { |v, idx|
|
123
|
+
placeholders.store("${#{key}[#{idx}]}", v)
|
124
|
+
placeholders.store("${#{key}[#{idx-size}]}", v) # support [-1]
|
125
|
+
}
|
126
|
+
else # string, interger, float, and others?
|
127
|
+
placeholders.store("${#{key}}", value)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
@placeholders = placeholders
|
132
|
+
end
|
133
|
+
|
134
|
+
def expand(str)
|
135
|
+
str.gsub(/(\${[a-z_]+(\[-?[0-9]+\])?}|__[A-Z_]+__)/) {
|
136
|
+
log.warn "remove_empty: unknown placeholder `#{$1}` found" unless @placeholders.include?($1)
|
137
|
+
@placeholders[$1]
|
138
|
+
}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class RubyPlaceholderExpander
|
143
|
+
attr_reader :placeholders, :log
|
144
|
+
|
145
|
+
def initialize(log)
|
146
|
+
@log = log
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get placeholders as a struct
|
150
|
+
#
|
151
|
+
# @param [Time] time the time
|
152
|
+
# @param [Hash] record the record
|
153
|
+
# @param [Hash] opts others
|
154
|
+
def prepare_placeholders(time, record, opts)
|
155
|
+
struct = UndefOpenStruct.new(record)
|
156
|
+
struct.time = Time.at(time)
|
157
|
+
opts.each {|key, value| struct.__send__("#{key}=", value) }
|
158
|
+
@placeholders = struct
|
159
|
+
end
|
160
|
+
|
161
|
+
# Replace placeholders in a string
|
162
|
+
#
|
163
|
+
# @param [String] str the string to be replaced
|
164
|
+
def expand(str)
|
165
|
+
str = str.gsub(/\$\{([^}]+)\}/, '#{\1}') # ${..} => #{..}
|
166
|
+
eval "\"#{str}\"", @placeholders.instance_eval { binding }
|
167
|
+
end
|
168
|
+
|
169
|
+
class UndefOpenStruct < OpenStruct
|
170
|
+
(Object.instance_methods).each do |m|
|
171
|
+
undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-remove-empty
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chadin Anuwattanaporn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-09 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.10.17
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.17
|
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: rspec
|
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
|
+
description: Fluentd plugin to remove empty fields of a event record
|
84
|
+
email: chadin@sogamo.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- Gemfile
|
90
|
+
- README.md
|
91
|
+
- fluent-plugin-remove-empty.gemspec
|
92
|
+
- lib/fluent/plugin/out_remove_empty.rb
|
93
|
+
homepage: https://github.com/newcmd001/fluent-plugin-remove-empty
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.0.14
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Fluentd plugin to remove empty fields of a event record
|
117
|
+
test_files: []
|