fluentd-ui 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd-ui might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog.md +5 -0
- data/Gemfile.lock +1 -1
- data/app/controllers/api/settings_controller.rb +46 -16
- data/app/controllers/concerns/setting_concern.rb +1 -1
- data/app/controllers/fluentd/settings/filter_grep_controller.rb +9 -0
- data/app/controllers/fluentd/settings/filter_parser_controller.rb +9 -0
- data/app/controllers/fluentd/settings/filter_record_transformer_controller.rb +14 -0
- data/app/controllers/fluentd/settings/filter_stdout_controller.rb +9 -0
- data/app/javascript/packs/filter_grep_setting.js +39 -0
- data/app/javascript/packs/grep_container.js +53 -0
- data/app/javascript/packs/grep_pattern.js +43 -0
- data/app/javascript/packs/owned_plugin_form.js +9 -7
- data/app/javascript/packs/settings.js +34 -16
- data/app/models/concerns/fluentd/setting/configurable.rb +1 -0
- data/app/models/concerns/fluentd/setting/label.rb +11 -0
- data/app/models/concerns/fluentd/setting/plugin.rb +2 -0
- data/app/models/concerns/fluentd/setting/plugin_config.rb +34 -4
- data/app/models/concerns/fluentd/setting/section_config.rb +10 -2
- data/app/models/fluentd/agent/common.rb +97 -0
- data/app/models/fluentd/setting/config.rb +71 -0
- data/app/models/fluentd/setting/filter_grep.rb +38 -0
- data/app/models/fluentd/setting/filter_parser.rb +34 -0
- data/app/models/fluentd/setting/filter_record_transformer.rb +27 -0
- data/app/models/fluentd/setting/filter_stdout.rb +34 -0
- data/app/models/fluentd/setting/in_forward.rb +1 -0
- data/app/models/fluentd/setting/in_http.rb +1 -1
- data/app/models/fluentd/setting/in_monitor_agent.rb +1 -1
- data/app/models/fluentd/setting/in_syslog.rb +1 -1
- data/app/models/fluentd/setting/out_elasticsearch.rb +1 -0
- data/app/models/fluentd/setting/out_forward.rb +1 -1
- data/app/models/fluentd/setting/out_mongo.rb +1 -0
- data/app/models/fluentd/setting/out_s3.rb +1 -0
- data/app/models/fluentd/setting/out_stdout.rb +1 -1
- data/app/models/fluentd/setting/out_tdlog.rb +1 -1
- data/app/views/api/settings/_element.json.jbuilder +3 -1
- data/app/views/api/settings/index.json.jbuilder +10 -2
- data/app/views/api/settings/show.json.jbuilder +1 -1
- data/app/views/fluentd/settings/filter_grep/_form.html.haml +18 -0
- data/app/views/fluentd/settings/filter_record_transformer/_form.html.haml +20 -0
- data/app/views/fluentd/settings/in_tail/_form.html.haml +1 -0
- data/app/views/fluentd/settings/source_and_output.html.haml +46 -14
- data/app/views/shared/vue/_filter_grep_setting.html.haml +19 -0
- data/app/views/shared/vue/_grep_container.html.haml +32 -0
- data/app/views/shared/vue/_grep_pattern.html.haml +24 -0
- data/app/views/shared/vue/_setting.html.erb +2 -2
- data/config/locales/translation_en.yml +39 -10
- data/config/locales/translation_ja.yml +39 -10
- data/config/routes.rb +6 -0
- data/lib/fluentd-ui/version.rb +1 -1
- data/test/factories/fluentd.rb +4 -4
- data/test/factories/plugins.rb +2 -2
- data/test/factories/user.rb +2 -2
- data/test/fixtures/config/label.conf +15 -0
- data/test/fixtures/config/multi-label.conf +40 -0
- data/test/fixtures/config/simple.conf +12 -0
- data/test/models/fluentd/agent_common_test.rb +288 -0
- data/test/models/fluentd/setting/config_test.rb +98 -0
- data/test/support/configurable_daemon_settings.rb +1 -1
- data/test/system/fluentd/setting/filter_grep_test.rb +96 -0
- data/test/system/fluentd/setting/filter_parser_test.rb +13 -0
- data/test/system/fluentd/setting/filter_record_transformer_test.rb +30 -0
- data/test/system/fluentd/setting/filter_stdout_test.rb +13 -0
- data/test/system/source_and_output_test.rb +168 -19
- data/test/test_helper.rb +4 -0
- metadata +98 -55
- data/.rspec +0 -2
@@ -1,4 +1,5 @@
|
|
1
1
|
require "fluent/plugin"
|
2
|
+
require "fluent/plugin/buf_file"
|
2
3
|
require "fluent/test/log"
|
3
4
|
require "fluent/test/driver/input"
|
4
5
|
require "fluent/test/driver/output"
|
@@ -17,6 +18,7 @@ class Fluentd
|
|
17
18
|
include Fluentd::Setting::PluginConfig
|
18
19
|
include Fluentd::Setting::SectionParser
|
19
20
|
include Fluentd::Setting::PluginParameter
|
21
|
+
include Fluentd::Setting::Label
|
20
22
|
|
21
23
|
included do
|
22
24
|
cattr_accessor :plugin_type, :plugin_name, :config_definition
|
@@ -10,7 +10,12 @@ class Fluentd
|
|
10
10
|
def validate_configuration
|
11
11
|
original_log = $log
|
12
12
|
$log = DummyLogger.logger
|
13
|
-
|
13
|
+
full_config = to_config.to_s
|
14
|
+
config = if full_config.start_with?("<label ")
|
15
|
+
full_config.lines[2..-3].join
|
16
|
+
else
|
17
|
+
full_config.lines[1..-2].join
|
18
|
+
end
|
14
19
|
self.class.create_driver(config)
|
15
20
|
rescue Fluent::ConfigError => ex
|
16
21
|
errors.add(:base, :invalid, message: ex.message)
|
@@ -40,6 +45,10 @@ class Fluentd
|
|
40
45
|
end
|
41
46
|
_attributes = { "@type" => self.plugin_name }.merge(_attributes)
|
42
47
|
_attributes["@log_level"] = _attributes.delete("log_level")
|
48
|
+
label = _attributes.delete("label")
|
49
|
+
if plugin_type == "input"
|
50
|
+
_attributes["@label"] = label
|
51
|
+
end
|
43
52
|
argument = case plugin_type
|
44
53
|
when "output", "filter", "buffer"
|
45
54
|
_attributes.delete(self._argument_name.to_s) || ""
|
@@ -47,7 +56,18 @@ class Fluentd
|
|
47
56
|
""
|
48
57
|
end
|
49
58
|
attrs, elements = parse_attributes(_attributes)
|
50
|
-
|
59
|
+
case plugin_type
|
60
|
+
when "output", "filter"
|
61
|
+
# e is <match> or <filter>
|
62
|
+
e = config_element(name, argument, attrs, elements)
|
63
|
+
if label.blank?
|
64
|
+
e
|
65
|
+
else
|
66
|
+
config_element("label", label, {}, [e])
|
67
|
+
end
|
68
|
+
else
|
69
|
+
config_element(name, argument, attrs, elements)
|
70
|
+
end
|
51
71
|
end
|
52
72
|
|
53
73
|
def parse_attributes(attributes)
|
@@ -70,11 +90,21 @@ class Fluentd
|
|
70
90
|
}
|
71
91
|
end
|
72
92
|
end
|
73
|
-
|
93
|
+
_elements = section_params.map do |index, _section_params|
|
74
94
|
section_class.new(_section_params).to_config
|
75
95
|
end.compact
|
96
|
+
elements.concat(_elements)
|
97
|
+
end
|
98
|
+
params = params.to_h
|
99
|
+
if plugin_type == "filter" && plugin_name == "record_transformer"
|
100
|
+
record_params = {}
|
101
|
+
params.delete("record").lines.each do |line|
|
102
|
+
k, v = line.split(" ", 2)
|
103
|
+
record_params[k] = v
|
104
|
+
end
|
105
|
+
elements << config_element("record", "", record_params, [])
|
76
106
|
end
|
77
|
-
attrs = params.
|
107
|
+
attrs = params.reject do |key, value|
|
78
108
|
skip?(key.to_sym, value)
|
79
109
|
end
|
80
110
|
return attrs, elements
|
@@ -22,9 +22,17 @@ class Fluentd
|
|
22
22
|
end
|
23
23
|
elements = sections.map do |key, section_params|
|
24
24
|
if section_params.present?
|
25
|
-
self._sections[key.to_sym]
|
25
|
+
section_class = self._sections[key.to_sym]
|
26
|
+
if section_class.multi?
|
27
|
+
section_params.map do |index, _section_params|
|
28
|
+
section_class.new(_section_params).to_config
|
29
|
+
end
|
30
|
+
else
|
31
|
+
section_class.new(section_params).to_config
|
32
|
+
end
|
26
33
|
end
|
27
|
-
end
|
34
|
+
end
|
35
|
+
elements = elements.flatten.compact
|
28
36
|
attrs = params.to_h.reject do |key, value|
|
29
37
|
skip?(key.to_sym, value)
|
30
38
|
end
|
@@ -18,6 +18,8 @@
|
|
18
18
|
# - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/systemd/td-agent.service.erb#L14
|
19
19
|
# fluentd: /etc/fluent/fluent.conf (created by fluentd -s)
|
20
20
|
|
21
|
+
require "strscan"
|
22
|
+
|
21
23
|
class Fluentd
|
22
24
|
class Agent
|
23
25
|
module Common
|
@@ -74,6 +76,25 @@ class Fluentd
|
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
79
|
+
def config_merge(content)
|
80
|
+
if content.start_with?("<label ")
|
81
|
+
label = content.slice(/<label\s+(.+?)>/, 1)
|
82
|
+
key = "label:#{label}"
|
83
|
+
parsed_config = parse_config(config)
|
84
|
+
if parsed_config.key?(key)
|
85
|
+
offset = parsed_config[key][0][:pos] + parsed_config[key][0][:size]
|
86
|
+
label, sections = parse_label_section(content, offset)
|
87
|
+
parsed_config[key][0][:sections]["filter"].concat(sections["filter"])
|
88
|
+
parsed_config[key][0][:sections]["match"].concat(sections["match"])
|
89
|
+
config_write(dump_parsed_config(parsed_config))
|
90
|
+
else
|
91
|
+
config_append(content)
|
92
|
+
end
|
93
|
+
else
|
94
|
+
config_append(content)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
77
98
|
def configuration
|
78
99
|
if File.exists? config_file
|
79
100
|
::Fluentd::Agent::Configuration.new(config_file)
|
@@ -142,6 +163,82 @@ class Fluentd
|
|
142
163
|
FileUtils.rm(file) if File.exist? file
|
143
164
|
end
|
144
165
|
end
|
166
|
+
|
167
|
+
def parse_config(content)
|
168
|
+
scanner = StringScanner.new(content)
|
169
|
+
contents = Hash.new {|h, k| h[k] = [] }
|
170
|
+
until scanner.eos? do
|
171
|
+
started = scanner.pos
|
172
|
+
header = scanner.scan_until(/^<(source|filter|match|label)/)
|
173
|
+
section_type = scanner[1]
|
174
|
+
break unless header
|
175
|
+
case section_type
|
176
|
+
when "source", "filter", "match"
|
177
|
+
current_source = header + scanner.scan_until(%r{^</(?:source|filter|match)>})
|
178
|
+
contents[section_type] << { pos: started, content: current_source.strip }
|
179
|
+
when "label"
|
180
|
+
label_content = header + scanner.scan_until(%r{^</label>})
|
181
|
+
label, sections = parse_label_section(label_content, started)
|
182
|
+
contents["label:#{label}"] << { label: label, pos: started, sections: sections, size: label_content.size }
|
183
|
+
else
|
184
|
+
raise TypeError, "Unknown section: #{started}: #{section_type}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
contents
|
188
|
+
end
|
189
|
+
|
190
|
+
def parse_label_section(content, offset)
|
191
|
+
scanner = StringScanner.new(content)
|
192
|
+
scanner.scan_until(/^<label\s+?([^\s]+?)>/)
|
193
|
+
label = scanner[1]
|
194
|
+
sections = Hash.new {|h, k| h[k] = [] }
|
195
|
+
loop do
|
196
|
+
break if scanner.match?(%r{\s+?</label>})
|
197
|
+
pos = scanner.pos
|
198
|
+
header = scanner.scan_until(/^\s*<(filter|match)/)
|
199
|
+
type = scanner[1]
|
200
|
+
source = header + scanner.scan_until(%r{^\s*</(?:filter|match)>})
|
201
|
+
sections[type] << { label: label, pos: pos + offset, content: source.sub(/\n+/, "") }
|
202
|
+
end
|
203
|
+
return label, sections
|
204
|
+
end
|
205
|
+
|
206
|
+
def dump_parsed_config(parsed_config)
|
207
|
+
content = "".dup
|
208
|
+
sources = parsed_config["source"] || []
|
209
|
+
filters = parsed_config["filter"] || []
|
210
|
+
matches = parsed_config["match"] || []
|
211
|
+
labels = parsed_config.select do |key, sections|
|
212
|
+
key.start_with?("label:")
|
213
|
+
end
|
214
|
+
labels = labels.values.flatten
|
215
|
+
sorted_sections = (sources + filters + matches + labels).sort_by do |section|
|
216
|
+
section[:pos]
|
217
|
+
end
|
218
|
+
sorted_sections.each do |section|
|
219
|
+
if section.key?(:label)
|
220
|
+
label = section[:label]
|
221
|
+
sub_filters = section.dig(:sections, "filter") || []
|
222
|
+
sub_matches = section.dig(:sections, "match") || []
|
223
|
+
sorted_sub_filters = sub_filters.sort_by do |sub_section|
|
224
|
+
sub_section[:pos]
|
225
|
+
end
|
226
|
+
sorted_sub_matches = sub_matches.sort_by do |sub_section|
|
227
|
+
sub_section[:pos]
|
228
|
+
end
|
229
|
+
sub_sections = sorted_sub_filters + sorted_sub_matches
|
230
|
+
content << "<label #{label}>\n"
|
231
|
+
sub_sections.each do |sub_section|
|
232
|
+
content << sub_section[:content] << "\n\n"
|
233
|
+
end
|
234
|
+
content.chomp!
|
235
|
+
content << "</label>\n\n"
|
236
|
+
else
|
237
|
+
content << section[:content] << "\n\n"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
content.chomp
|
241
|
+
end
|
145
242
|
end
|
146
243
|
end
|
147
244
|
end
|
@@ -21,12 +21,83 @@ class Fluentd
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def filters
|
25
|
+
elements.find_all do |elm|
|
26
|
+
elm.name == "filter"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
24
30
|
def matches
|
25
31
|
elements.find_all do |elm|
|
26
32
|
elm.name == "match"
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
36
|
+
def labels
|
37
|
+
elements.find_all do |elm|
|
38
|
+
elm.name == "label"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def group_by_label
|
43
|
+
hash = Hash.new{|h, k| h[k] = {} }
|
44
|
+
sources.each do |source|
|
45
|
+
label = source["@label"] || source["label"]
|
46
|
+
if label
|
47
|
+
hash[label][:sources] = [source]
|
48
|
+
else
|
49
|
+
hash["ROOT"][:sources] = [source]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
hash["ROOT"][:filters] = filters unless filters.empty?
|
53
|
+
hash["ROOT"][:matches] = matches unless matches.empty?
|
54
|
+
|
55
|
+
labels.each do |label|
|
56
|
+
hash[label.arg][:filters] = label.elements.find_all do |e|
|
57
|
+
e.name == "filter"
|
58
|
+
end
|
59
|
+
hash[label.arg][:matches] = label.elements.find_all do |e|
|
60
|
+
e.name == "match"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete_element(name, arg, element)
|
67
|
+
if name == "label"
|
68
|
+
label_section = fl_config.elements(name: name, arg: arg).first
|
69
|
+
original_size = label_section.elements.size
|
70
|
+
remaining_elements = label_section.elements.reject do |e|
|
71
|
+
element == e
|
72
|
+
end
|
73
|
+
if remaining_elements.empty?
|
74
|
+
remaining_elements = fl_config.elements.reject do |e|
|
75
|
+
label_section == e
|
76
|
+
end
|
77
|
+
fl_config.elements = remaining_elements
|
78
|
+
return element
|
79
|
+
else
|
80
|
+
label_section.elements = remaining_elements
|
81
|
+
if original_size == label_section.elements.size
|
82
|
+
return nil
|
83
|
+
else
|
84
|
+
return element
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
original_size = fl_config.elements.size
|
89
|
+
remaining_elements = fl_config.elements.reject do |e|
|
90
|
+
element == e
|
91
|
+
end
|
92
|
+
fl_config.elements = remaining_elements
|
93
|
+
if original_size == fl_config.elements.size
|
94
|
+
return nil
|
95
|
+
else
|
96
|
+
return element
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
30
101
|
def write_to_file
|
31
102
|
return unless Fluentd.instance
|
32
103
|
Fluentd.instance.agent.config_write formatted
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Fluentd
|
2
|
+
module Setting
|
3
|
+
class FilterGrep
|
4
|
+
include Fluentd::Setting::Plugin
|
5
|
+
|
6
|
+
register_plugin("filter", "grep")
|
7
|
+
|
8
|
+
def self.initial_params
|
9
|
+
{
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.permit_params
|
14
|
+
[
|
15
|
+
:label,
|
16
|
+
:pattern, :log_level, :@log_level,
|
17
|
+
{ and: {regexp: [:key, :pattern], exclude: [:key, :pattern]} },
|
18
|
+
{ or: {regexp: [:key, :pattern], exclude: [:key, :pattern]} }
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def common_options
|
23
|
+
[
|
24
|
+
:label,
|
25
|
+
:pattern,
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def hidden_options
|
30
|
+
regexps = (1..20).map {|n| :"regexp#{n}"}
|
31
|
+
excludes = (1..20).map {|n| :"exclude#{n}"}
|
32
|
+
[
|
33
|
+
*regexps, *excludes, :regexp, :exclude, :and, :or
|
34
|
+
]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Fluentd
|
2
|
+
module Setting
|
3
|
+
class FilterParser
|
4
|
+
include Fluentd::Setting::Plugin
|
5
|
+
|
6
|
+
register_plugin("filter", "parser")
|
7
|
+
|
8
|
+
def self.initial_params
|
9
|
+
{
|
10
|
+
parse_type: "none",
|
11
|
+
parse: {
|
12
|
+
"0" => {
|
13
|
+
"type" => "none"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def common_options
|
20
|
+
[
|
21
|
+
:label,
|
22
|
+
:pattern,
|
23
|
+
:key_name,
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
def hidden_options
|
28
|
+
[
|
29
|
+
:parse
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Fluentd
|
2
|
+
module Setting
|
3
|
+
class FilterRecordTransformer
|
4
|
+
include Fluentd::Setting::Plugin
|
5
|
+
|
6
|
+
register_plugin("filter", "record_transformer")
|
7
|
+
|
8
|
+
attribute(:record, :string)
|
9
|
+
|
10
|
+
def self.initial_params
|
11
|
+
{
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def common_options
|
16
|
+
[
|
17
|
+
:label,
|
18
|
+
:pattern,
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def hidden_options
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Fluentd
|
2
|
+
module Setting
|
3
|
+
class FilterStdout
|
4
|
+
include Fluentd::Setting::Plugin
|
5
|
+
|
6
|
+
register_plugin("filter", "stdout")
|
7
|
+
|
8
|
+
def self.initial_params
|
9
|
+
{
|
10
|
+
format_type: "stdout",
|
11
|
+
format: {
|
12
|
+
"0" => {
|
13
|
+
"@type" => "stdout",
|
14
|
+
"output_type" => "json"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def common_options
|
21
|
+
[
|
22
|
+
:label,
|
23
|
+
:pattern,
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
def hidden_options
|
28
|
+
[
|
29
|
+
:inject
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|