/
grep.rb
137 lines (121 loc) · 3.7 KB
/
grep.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require "logstash/filters/base"
require "logstash/namespace"
# Grep filter.
#
# Useful for:
# * Dropping events
# * Tagging events
# * Adding static fields
#
# Events not matched ar dropped. If 'negate' is set to true (defaults false), then
# matching events are dropped.
#
# Config:
# - grep:
# <type>:
# - match:
# <field>: <regexp>
# negate: true/false
# add_fields:
# <field>: <value>
# add_tags:
# - tag1
# - tag2
#
class LogStash::Filters::Grep < LogStash::Filters::Base
config_name "grep"
public
def initialize(config = {})
super
@config = config
end # def initialize
public
def register
@config.each do |type, matches|
if ! matches.is_a?(Array)
@logger.warn("grep: #{type} misconfigured; must be an array")
next
end
matches.each_index do |i|
match = matches[i]
if ! match.member?("match")
@logger.warn(["grep: #{type}/#{i}: no 'match' section defined", match])
next
end
match["match"].each do |field, re_str|
re = Regexp.new(re_str)
@config[type][i]["match"][field] = re
@logger.debug(["grep: #{type}/#{i}/#{field}", re_str, re])
end
end # matches.each
end # @config.each
end # def register
public
def filter(event)
config = @config[event.type]
if not config
@logger.debug("grep: skipping type #{event.type} from #{event.source}")
event.cancel
return
end
@logger.debug(["Running grep filter", event.to_hash, config])
matched = false
config.each do |match|
if ! match["match"]
@logger.debug(["Skipping match object, no match key", match])
next
end
# For each match object, we have to match everything in order to
# apply any fields/tags.
match_count = 0
match["match"].each do |field, re|
if !event[field]
@logger.debug(["Skipping match object, field not present", field, event, event[field]])
next
end
if event[field].nil? and match["negate"] == true
match_count += 1
end
(event[field].is_a?(Array) ? event[field] : [event[field]]).each do |value|
if match["negate"] == true
@logger.debug("want negate match")
next if re.match(value)
@logger.debug(["grep not-matched (negate requsted)", { field => value }])
else
@logger.debug(["trying regex", re, value])
next unless re.match(value)
@logger.debug(["grep matched", { field => value }])
end
match_count += 1
break
end
end # match["match"].each
if match_count == match["match"].length
matched = true
@logger.debug("matched all fields (#{match_count})")
if match["add_fields"]
match["add_fields"].each do |field, value|
event[field] ||= []
event[field] << event.sprintf(value)
@logger.debug("grep: adding #{value} to field #{field}")
end
end # if match["add_fields"]
if match["add_tags"]
match["add_tags"].each do |tag|
event.tags << event.sprintf(tag)
@logger.debug("grep: adding tag #{tag}")
end
end # if match["add_tags"]
else
@logger.debug("match block failed " \
"(#{match_count}/#{match["match"].length} matches)")
end # match["match"].each
end # config.each
if not matched
@logger.debug("grep: dropping event, no matches")
event.cancel
return
end
@logger.debug(["Event after grep filter", event.to_hash])
end # def filter
end # class LogStash::Filters::Grep