refactor conditionals generation

added specs
This commit is contained in:
Colin Surprenant 2015-04-02 23:38:27 -04:00
parent 2e1b879431
commit 573149b002
2 changed files with 90 additions and 14 deletions

View file

@ -1,7 +1,9 @@
# encoding: utf-8 # encoding: utf-8
require 'logstash/errors' require 'logstash/errors'
require "treetop" require "treetop"
class Treetop::Runtime::SyntaxNode class Treetop::Runtime::SyntaxNode
def compile def compile
return "" if elements.nil? return "" if elements.nil?
return elements.collect(&:compile).reject(&:empty?).join("") return elements.collect(&:compile).reject(&:empty?).join("")
@ -55,11 +57,31 @@ class Treetop::Runtime::SyntaxNode
end end
end end
module LogStash; module Config; module AST module LogStash; module Config; module AST
def self.defered_conditionals=(val)
@defered_conditionals = val
end
def self.defered_conditionals
@defered_conditionals
end
def self.defered_conditionals_index
@defered_conditionals_index
end
def self.defered_conditionals_index=(val)
@defered_conditionals_index = val
end
class Node < Treetop::Runtime::SyntaxNode; end class Node < Treetop::Runtime::SyntaxNode; end
class Config < Node class Config < Node
def compile def compile
LogStash::Config::AST.defered_conditionals = []
LogStash::Config::AST.defered_conditionals_index = 0
code = [] code = []
code << <<-CODE code << <<-CODE
@ -94,6 +116,9 @@ module LogStash; module Config; module AST
end end
code += definitions.join("\n").split("\n", -1).collect { |l| " #{l}" } code += definitions.join("\n").split("\n", -1).collect { |l| " #{l}" }
code += LogStash::Config::AST.defered_conditionals
return code.join("\n") return code.join("\n")
end end
end end
@ -124,20 +149,15 @@ module LogStash; module Config; module AST
#{name}_flush = lambda do |options, &block| #{name}_flush = lambda do |options, &block|
@logger.debug? && @logger.debug(\"Flushing\", :plugin => #{name}) @logger.debug? && @logger.debug(\"Flushing\", :plugin => #{name})
flushed_events = #{name}.flush(options) events = #{name}.flush(options)
return if flushed_events.nil? || flushed_events.empty? return if events.nil? || events.empty?
flushed_events.each do |event| @logger.debug? && @logger.debug(\"Flushing\", :plugin => #{name}, :events => events)
@logger.debug? && @logger.debug(\"Flushing\", :plugin => #{name}, :event => event)
events = [event]
#{plugin.compile_starting_here.gsub(/^/, " ")} #{plugin.compile_starting_here.gsub(/^/, " ")}
block.call(event) events.each{|e| block.call(e)}
events.flatten.each{|e| block.call(e) if e != event}
end
end end
if #{name}.respond_to?(:flush) if #{name}.respond_to?(:flush)
@ -357,14 +377,38 @@ module LogStash; module Config; module AST
# at the end, events is returned to handle the case where no branch match and no branch code is executed # at the end, events is returned to handle the case where no branch match and no branch code is executed
# so we must make sure to return the current event. # so we must make sure to return the current event.
type = recursive_select_parent(PluginSection).first.plugin_type.text_value
if type == "filter"
i = LogStash::Config::AST.defered_conditionals_index += 1
source = <<-CODE
def cond_func_#{i}(input_events)
result = []
input_events.each do |event|
events = [event]
#{super}
end
result += events
end
result
end
CODE
LogStash::Config::AST.defered_conditionals << source
<<-CODE
events = cond_func_#{i}(events)
CODE
else
<<-CODE <<-CODE
#{super} #{super}
end end
CODE CODE
end end
end end
end
class BranchEntry < Node; end class BranchEntry < Node; end
class If < BranchEntry class If < BranchEntry
def compile def compile
children = recursive_inject { |e| e.is_a?(Branch) || e.is_a?(Plugin) } children = recursive_inject { |e| e.is_a?(Branch) || e.is_a?(Plugin) }

View file

@ -393,4 +393,36 @@ describe "conditionals in filter" do
# expect(subject[1]["cond2"]).to eq("true") # expect(subject[1]["cond2"]).to eq("true")
end end
end end
describe "multiple new events from root" do
config <<-CONFIG
filter {
if [type] == "original" {
clone {
clones => ["clone1", "clone2"]
}
}
if [type] == "clone1" {
mutate { add_field => { "cond1" => "true" } }
} else if [type] == "clone2" {
mutate { add_field => { "cond2" => "true" } }
}
}
CONFIG
sample({"type" => "original"}) do
# puts subject.inspect
expect(subject[0]["cond1"]).to eq(nil)
expect(subject[0]["cond2"]).to eq(nil)
expect(subject[1]["type"]).to eq("clone1")
expect(subject[1]["cond1"]).to eq("true")
expect(subject[1]["cond2"]).to eq(nil)
expect(subject[2]["type"]).to eq("clone2")
expect(subject[2]["cond1"]).to eq(nil)
expect(subject[2]["cond2"]).to eq("true")
end
end
end end