Support deep fields (foo.bar) in date filter (LOGSTASH-724)

allow literal dot with \.
This commit is contained in:
Louis Zuckerman 2013-01-05 14:47:04 -05:00
parent eec7ac8a09
commit 13c25baccd
3 changed files with 72 additions and 17 deletions

View file

@ -131,19 +131,22 @@ class LogStash::Event
public
def [](key)
# If the key isn't in fields and it starts with an "@" sign, get it out of data instead of fields
if ! @data["@fields"].has_key?(key) and key.slice(0,1) == "@"
if ! @data["@fields"].has_key?(key.gsub(/\\\./, ".")) and key.slice(0,1) == "@"
return @data[key]
elsif key.include?(".")
elsif key.index(/(?<!\\)\./)
value = nil
obj = self
obj = @data["@fields"]
# "." is what ES uses to access structured data, so adopt that
# idea here, too. "foo.bar" will access key "bar" under hash "foo".
key.split('.').each do |segment|
# try to safely cast segment to integer for the 0 in foo.0.bar
begin
segment = Integer(segment)
rescue Exception
#not an int, do nothing, segment remains a string
key.split(/(?<!\\)\./).each do |segment|
segment.gsub!(/\\\./, ".")
if (obj.is_a?(Array) || (obj.is_a?(Hash) && !obj.member?(segment)) )
# try to safely cast segment to integer for the 0 in foo.0.bar
begin
segment = Integer(segment)
rescue Exception
#not an int, do nothing, segment remains a string
end
end
if obj
value = obj[segment] rescue nil
@ -155,7 +158,7 @@ class LogStash::Event
end # key.split.each
return value
else
return @data["@fields"][key]
return @data["@fields"][key.gsub(/\\\./, ".")]
end
end # def []

View file

@ -9,7 +9,27 @@ describe LogStash::Event do
@event.message = "hello world"
@event.tags = [ "tag1" ]
@event.source = "/home/foo"
@event["@fields"] = { "j" => { "k1" => "v", "k2" => [ "w", "x" ] } }
@event["@fields"] = {
"a" => "b",
"c" => {
"d" => "f",
"e.f" => "g"
},
"c.d" => "e",
"f.g" => {
"h" => "i"
},
"j" => {
"k1" => "v",
"k2" => [
"w",
"x"
],
"k3.4" => "m",
5 => 6,
"5" => 7
}
}
end
subject { @event }
@ -24,7 +44,7 @@ describe LogStash::Event do
insist { @event.sprintf("%{+MM}") } == "01"
insist { @event.sprintf("%{+HH}") } == "00"
end
it "should report fields with %{field} syntax" do
insist { @event.sprintf("%{@type}") } == "sprintf"
insist { @event.sprintf("%{@message}") } == subject["@message"]
@ -35,18 +55,36 @@ describe LogStash::Event do
insist { @event.sprintf("%{j.k2.0}") } == "w"
end
end
context "#[]" do
it "should fetch data" do
insist { @event["@type"] } == "sprintf"
end
it "should fetch fields" do
insist { @event["a"] } == "b"
insist { @event['c\.d'] } == "e"
end
it "should fetch deep fields" do
insist { @event["j.k1"] } == "v"
insist { @event["c.d"] } == "f"
insist { @event['f\.g.h'] } == "i"
insist { @event['j.k3\.4'] } == "m"
insist { @event['j.5'] } == 7
end
end
context "#append" do
it "should append message with \\n" do
subject.append(LogStash::Event.new("@message" => "hello world"))
insist { subject.message } == "hello world\nhello world"
end
it "should concatenate tags" do
subject.append(LogStash::Event.new("@tags" => [ "tag2" ]))
insist { subject.tags } == [ "tag1", "tag2" ]
end
context "when event field is nil" do
it "should add single value as string" do
subject.append(LogStash::Event.new("@fields" => {"field1" => "append1"}))
@ -57,10 +95,10 @@ describe LogStash::Event do
insist { subject[ "field1" ] } == [ "append1","append2" ]
end
end
context "when event field is a string" do
before { subject[ "field1" ] = "original1" }
it "should append string to values, if different from current" do
subject.append(LogStash::Event.new("@fields" => {"field1" => "append1"}))
insist { subject[ "field1" ] } == [ "original1", "append1" ]
@ -80,7 +118,7 @@ describe LogStash::Event do
end
context "when event field is an array" do
before { subject[ "field1" ] = [ "original1", "original2" ] }
it "should append string values to array, if not present in array" do
subject.append(LogStash::Event.new("@fields" => {"field1" => "append1"}))
insist { subject[ "field1" ] } == [ "original1", "original2", "append1" ]

View file

@ -213,4 +213,18 @@ describe LogStash::Filters::Date do
insist { subject["@timestamp"] } == "2013-01-01T00:00:00.000Z"
end
end
describe "support deep field access" do
config <<-CONFIG
filter {
date {
match => [ "data\\.deep", "ISO8601" ]
}
}
CONFIG
sample({ "@fields" => { "data.deep" => "2013-01-01T00:00:00.000Z" } }) do
insist { subject["@timestamp"] } == "2013-01-01T00:00:00.000Z"
end
end
end