logstash-lite 0.2.20101118134500

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.
Files changed (134) hide show
  1. data/bin/logstash +56 -0
  2. data/bin/logstash-web +6 -0
  3. data/etc/logstash-elasticsearch-rabbitmq-river.yaml +41 -0
  4. data/etc/logstash-mongodb-storage.yaml +5 -0
  5. data/etc/logstash-parser.yaml +20 -0
  6. data/etc/logstash-reader.yaml +8 -0
  7. data/etc/logstash-shipper.yaml +18 -0
  8. data/etc/logstash-standalone.yaml +47 -0
  9. data/etc/prod.yaml +38 -0
  10. data/etc/redhat/logstash +92 -0
  11. data/etc/redhat/logstash-agent +83 -0
  12. data/etc/redhat/logstash-agent.sysconfig +7 -0
  13. data/etc/redhat/logstash.spec +171 -0
  14. data/etc/redhat/logstash.sysconfig +18 -0
  15. data/etc/tograylog.yaml +37 -0
  16. data/examples/test.rb +38 -0
  17. data/lib/logstash.rb +3 -0
  18. data/lib/logstash/agent.rb +116 -0
  19. data/lib/logstash/event.rb +70 -0
  20. data/lib/logstash/filters.rb +17 -0
  21. data/lib/logstash/filters/base.rb +17 -0
  22. data/lib/logstash/filters/date.rb +59 -0
  23. data/lib/logstash/filters/field.rb +29 -0
  24. data/lib/logstash/filters/grok.rb +74 -0
  25. data/lib/logstash/filters/grokdiscovery.rb +60 -0
  26. data/lib/logstash/inputs.rb +18 -0
  27. data/lib/logstash/inputs/amqp.rb +48 -0
  28. data/lib/logstash/inputs/base.rb +32 -0
  29. data/lib/logstash/inputs/file.rb +47 -0
  30. data/lib/logstash/inputs/syslog.rb +123 -0
  31. data/lib/logstash/inputs/tcp.rb +51 -0
  32. data/lib/logstash/logging.rb +82 -0
  33. data/lib/logstash/namespace.rb +6 -0
  34. data/lib/logstash/outputs.rb +15 -0
  35. data/lib/logstash/outputs/amqp.rb +48 -0
  36. data/lib/logstash/outputs/base.rb +29 -0
  37. data/lib/logstash/outputs/elasticsearch.rb +71 -0
  38. data/lib/logstash/outputs/gelf.rb +35 -0
  39. data/lib/logstash/outputs/mongodb.rb +19 -0
  40. data/lib/logstash/outputs/stdout.rb +15 -0
  41. data/lib/logstash/outputs/websocket.rb +35 -0
  42. data/lib/logstash/time.rb +27 -0
  43. data/lib/logstash/web/lib/elasticsearch.rb +79 -0
  44. data/lib/logstash/web/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  45. data/lib/logstash/web/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  46. data/lib/logstash/web/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  47. data/lib/logstash/web/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  48. data/lib/logstash/web/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  49. data/lib/logstash/web/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  50. data/lib/logstash/web/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  51. data/lib/logstash/web/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  52. data/lib/logstash/web/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  53. data/lib/logstash/web/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  54. data/lib/logstash/web/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  55. data/lib/logstash/web/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  56. data/lib/logstash/web/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  57. data/lib/logstash/web/public/css/smoothness/jquery-ui-1.8.5.custom.css +572 -0
  58. data/lib/logstash/web/public/js/flot/API.txt +1024 -0
  59. data/lib/logstash/web/public/js/flot/FAQ.txt +71 -0
  60. data/lib/logstash/web/public/js/flot/LICENSE.txt +22 -0
  61. data/lib/logstash/web/public/js/flot/Makefile +15 -0
  62. data/lib/logstash/web/public/js/flot/NEWS.txt +340 -0
  63. data/lib/logstash/web/public/js/flot/PLUGINS.txt +105 -0
  64. data/lib/logstash/web/public/js/flot/README.txt +81 -0
  65. data/lib/logstash/web/public/js/flot/examples/ajax.html +143 -0
  66. data/lib/logstash/web/public/js/flot/examples/annotating.html +75 -0
  67. data/lib/logstash/web/public/js/flot/examples/arrow-down.gif +0 -0
  68. data/lib/logstash/web/public/js/flot/examples/arrow-left.gif +0 -0
  69. data/lib/logstash/web/public/js/flot/examples/arrow-right.gif +0 -0
  70. data/lib/logstash/web/public/js/flot/examples/arrow-up.gif +0 -0
  71. data/lib/logstash/web/public/js/flot/examples/basic.html +38 -0
  72. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth-1.json +4 -0
  73. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth-2.json +4 -0
  74. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth-3.json +4 -0
  75. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth-4.json +4 -0
  76. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth-5.json +4 -0
  77. data/lib/logstash/web/public/js/flot/examples/data-eu-gdp-growth.json +4 -0
  78. data/lib/logstash/web/public/js/flot/examples/data-japan-gdp-growth.json +4 -0
  79. data/lib/logstash/web/public/js/flot/examples/data-usa-gdp-growth.json +4 -0
  80. data/lib/logstash/web/public/js/flot/examples/dual-axis.html +39 -0
  81. data/lib/logstash/web/public/js/flot/examples/graph-types.html +75 -0
  82. data/lib/logstash/web/public/js/flot/examples/hs-2004-27-a-large_web.jpg +0 -0
  83. data/lib/logstash/web/public/js/flot/examples/image.html +45 -0
  84. data/lib/logstash/web/public/js/flot/examples/index.html +43 -0
  85. data/lib/logstash/web/public/js/flot/examples/interacting.html +93 -0
  86. data/lib/logstash/web/public/js/flot/examples/layout.css +6 -0
  87. data/lib/logstash/web/public/js/flot/examples/navigate.html +118 -0
  88. data/lib/logstash/web/public/js/flot/examples/selection.html +114 -0
  89. data/lib/logstash/web/public/js/flot/examples/setting-options.html +65 -0
  90. data/lib/logstash/web/public/js/flot/examples/stacking.html +77 -0
  91. data/lib/logstash/web/public/js/flot/examples/thresholding.html +54 -0
  92. data/lib/logstash/web/public/js/flot/examples/time.html +71 -0
  93. data/lib/logstash/web/public/js/flot/examples/tracking.html +95 -0
  94. data/lib/logstash/web/public/js/flot/examples/turning-series.html +98 -0
  95. data/lib/logstash/web/public/js/flot/examples/visitors.html +90 -0
  96. data/lib/logstash/web/public/js/flot/examples/zooming.html +98 -0
  97. data/lib/logstash/web/public/js/flot/excanvas.js +1427 -0
  98. data/lib/logstash/web/public/js/flot/excanvas.min.js +1 -0
  99. data/lib/logstash/web/public/js/flot/jquery.colorhelpers.js +174 -0
  100. data/lib/logstash/web/public/js/flot/jquery.colorhelpers.min.js +1 -0
  101. data/lib/logstash/web/public/js/flot/jquery.flot.crosshair.js +156 -0
  102. data/lib/logstash/web/public/js/flot/jquery.flot.crosshair.min.js +1 -0
  103. data/lib/logstash/web/public/js/flot/jquery.flot.image.js +237 -0
  104. data/lib/logstash/web/public/js/flot/jquery.flot.image.min.js +1 -0
  105. data/lib/logstash/web/public/js/flot/jquery.flot.js +2119 -0
  106. data/lib/logstash/web/public/js/flot/jquery.flot.min.js +1 -0
  107. data/lib/logstash/web/public/js/flot/jquery.flot.navigate.js +272 -0
  108. data/lib/logstash/web/public/js/flot/jquery.flot.navigate.min.js +1 -0
  109. data/lib/logstash/web/public/js/flot/jquery.flot.selection.js +299 -0
  110. data/lib/logstash/web/public/js/flot/jquery.flot.selection.min.js +1 -0
  111. data/lib/logstash/web/public/js/flot/jquery.flot.stack.js +152 -0
  112. data/lib/logstash/web/public/js/flot/jquery.flot.stack.min.js +1 -0
  113. data/lib/logstash/web/public/js/flot/jquery.flot.threshold.js +103 -0
  114. data/lib/logstash/web/public/js/flot/jquery.flot.threshold.min.js +1 -0
  115. data/lib/logstash/web/public/js/flot/jquery.js +4376 -0
  116. data/lib/logstash/web/public/js/flot/jquery.min.js +19 -0
  117. data/lib/logstash/web/public/js/jquery-hashchange-1.0.0.js +121 -0
  118. data/lib/logstash/web/public/js/jquery.livequery.js +250 -0
  119. data/lib/logstash/web/public/js/jquery.tmpl.min.js +1 -0
  120. data/lib/logstash/web/public/js/logstash.js +202 -0
  121. data/lib/logstash/web/server.rb +90 -0
  122. data/lib/logstash/web/views/header.haml +8 -0
  123. data/lib/logstash/web/views/layout.haml +21 -0
  124. data/lib/logstash/web/views/main/index.haml +5 -0
  125. data/lib/logstash/web/views/search/ajax.haml +32 -0
  126. data/lib/logstash/web/views/search/results.haml +17 -0
  127. data/lib/logstash/web/views/style.sass +50 -0
  128. data/patterns/firewalls +2 -0
  129. data/patterns/grok-patterns +90 -0
  130. data/patterns/haproxy +5 -0
  131. data/patterns/linux-syslog +7 -0
  132. data/patterns/nagios +7 -0
  133. data/patterns/ruby +2 -0
  134. metadata +228 -0
@@ -0,0 +1,18 @@
1
+ # LogStash configuration
2
+
3
+ # Run the indexer. This can be set to false to disable the indexer (and
4
+ # searching) and only parse log lines.
5
+ INDEXER=true
6
+
7
+ # Run one parser. For maximum throughput, run one parser per core.
8
+ # This can be set to 0 to disable the parser.
9
+ PARSERS=1
10
+
11
+ # Path to config file
12
+ CONFIG=/opt/logstash/etc/logstashd.yaml
13
+
14
+ # Set to true for very verbose debugging output
15
+ DEBUG=false
16
+
17
+ # Run as the logstash user
18
+ USER=logstash
@@ -0,0 +1,37 @@
1
+ ---
2
+ inputs:
3
+ linux-syslog:
4
+ - /var/log/messages
5
+ - /var/log/kern.log
6
+ - /var/log/auth.log
7
+ - /var/log/user.log
8
+ apache-access:
9
+ - /var/log/apache2/access.log
10
+ - /home/jls/logs/access_log
11
+ apache-error:
12
+ - /var/log/apache2/error.log
13
+ - /home/jls/logs/error_log
14
+ filters:
15
+ - grok:
16
+ linux-syslog: # for logs of type 'linux-syslog'
17
+ patterns:
18
+ - %{SYSLOGLINE}
19
+ apache-access: # for logs of type 'apache-error'
20
+ patterns:
21
+ - %{COMBINEDAPACHELOG}
22
+ nagios:
23
+ patterns:
24
+ - %{NAGIOSLOGLINE}
25
+ - date:
26
+ linux-syslog: # for logs of type 'linux-syslog'
27
+ # Look for a field 'timestamp' with this format, parse and it for the timestamp
28
+ # This field comes from the SYSLOGLINE pattern
29
+ timestamp: "%b %e %H:%M:%S"
30
+ timestamp8601: ISO8601
31
+ apache-access:
32
+ timestamp: "%d/%b/%Y:%H:%M:%S %Z"
33
+ nagios:
34
+ epochtime: %s
35
+ outputs:
36
+ - stdout:///
37
+ - gelf://localhost/
data/examples/test.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # How to trigger the 'evil ip' message:
4
+ # % logger -t "pantscon" "naughty host 14.33.24.55 $RANDOM"
5
+
6
+ require "rubygems"
7
+ require "logstash/agent"
8
+
9
+ class MyAgent < LogStash::Agent
10
+ def receive(event)
11
+ filter(event) # Invoke any filters
12
+
13
+ return unless event["progname"][0] == "pantscon"
14
+ return unless event.message =~ /naughty host/
15
+ event["IP"].each do |ip|
16
+ next unless ip.length > 0
17
+ puts "Evil IP: #{ip}"
18
+ end
19
+ end # def receive
20
+ end # class MyAgent
21
+
22
+ # Read a local file, parse it, and react accordingly (see MyAgent#receive)
23
+ agent = MyAgent.new({
24
+ "input" => [
25
+ "/var/log/messages",
26
+ ],
27
+ "filter" => [ "grok" ],
28
+ })
29
+ agent.run
30
+
31
+ # Read messages that we expect to be parsed by another agent. Reads
32
+ # a particular AMQP topic for messages
33
+ #agent = MyAgent.new({
34
+ #"input" => [
35
+ #"amqp://localhost/topic/parsed",
36
+ #]
37
+ #})
38
+ #agent.run
data/lib/logstash.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "logstash/namespace"
2
+ require "logstash/agent"
3
+ require "logstash/event"
@@ -0,0 +1,116 @@
1
+ require "eventmachine"
2
+ require "eventmachine-tail"
3
+ require "logstash/namespace"
4
+ require "logstash/inputs"
5
+ require "logstash/outputs"
6
+ require "logstash/filters"
7
+ require "logstash/logging"
8
+
9
+ # Collect logs, ship them out.
10
+ class LogStash::Agent
11
+ attr_reader :config
12
+
13
+ def initialize(config)
14
+ @logger = LogStash::Logger.new(STDERR)
15
+
16
+ @config = config
17
+ @outputs = []
18
+ @inputs = []
19
+ @filters = []
20
+ # Config should have:
21
+ # - list of logs to monitor
22
+ # - log config
23
+ # - where to ship to
24
+ end # def initialize
25
+
26
+ # Register any event handlers with EventMachine
27
+ # Technically, this agent could listen for anything (files, sockets, amqp,
28
+ # stomp, etc).
29
+ protected
30
+ def register
31
+ # TODO(sissel): warn when no inputs and no outputs are defined.
32
+ # TODO(sissel): Refactor this madness into a config lib
33
+
34
+ if (["inputs", "outputs"] & @config.keys).length == 0
35
+ $stderr.puts "No inputs or no outputs configured. This probably isn't what you want."
36
+ end
37
+
38
+ # Register input and output stuff
39
+ if @config.include?("inputs")
40
+ inputs = @config["inputs"]
41
+ inputs.each do |value|
42
+ # If 'url' is an array, then inputs is a hash and the key is the type
43
+ if inputs.is_a?(Hash)
44
+ type, urls = value
45
+ else
46
+ raise "config error, no type for url #{urls.inspect}"
47
+ end
48
+
49
+ # url could be a string or an array.
50
+ urls = [urls] if !urls.is_a?(Array)
51
+
52
+ urls.each do |url|
53
+ @logger.debug("Using input #{url} of type #{type}")
54
+ input = LogStash::Inputs.from_url(url, type) { |event| receive(event) }
55
+ input.register
56
+ @inputs << input
57
+ end
58
+ end # each input
59
+ end
60
+
61
+ if @config.include?("filters")
62
+ filters = @config["filters"]
63
+ filters.collect { |x| x.to_a[0] }.each do |filter|
64
+ name, value = filter
65
+ @logger.debug("Using filter #{name} => #{value.inspect}")
66
+ filter = LogStash::Filters.from_name(name, value)
67
+ filter.register
68
+ @filters << filter
69
+ end # each filter
70
+ end
71
+
72
+ if @config.include?("outputs")
73
+ @config["outputs"].each do |url|
74
+ @logger.debug("Using output #{url}")
75
+ output = LogStash::Outputs.from_url(url)
76
+ output.register
77
+ @outputs << output
78
+ end # each output
79
+ end
80
+ end # def register
81
+
82
+ public
83
+ def run
84
+ EventMachine.run do
85
+ self.register
86
+ end # EventMachine.run
87
+ end # def run
88
+
89
+ protected
90
+ def filter(event)
91
+ @filters.each do |f|
92
+ # TODO(sissel): Add ability for a filter to cancel/drop a message
93
+ f.filter(event)
94
+ if event.cancelled?
95
+ break
96
+ end
97
+ end
98
+ end # def filter
99
+
100
+ protected
101
+ def output(event)
102
+ @outputs.each do |o|
103
+ o.receive(event)
104
+ end # each output
105
+ end # def output
106
+
107
+ protected
108
+ # Process a message
109
+ def receive(event)
110
+ filter(event)
111
+
112
+ if !event.cancelled?
113
+ output(event)
114
+ end
115
+ end # def input
116
+ end # class LogStash::Components::Agent
@@ -0,0 +1,70 @@
1
+ require "json"
2
+ require "logstash/time"
3
+ require "uri"
4
+
5
+ # General event type. Will expand this in the future.
6
+ module LogStash; class Event
7
+ def initialize(data)
8
+ @cancelled = false
9
+ @data = {
10
+ "@source" => "unknown",
11
+ "@type" => nil,
12
+ "@tags" => [],
13
+ "@fields" => {},
14
+ }.merge(data)
15
+
16
+ if !@data.include?("@timestamp")
17
+ @data["@timestamp"] = LogStash::Time.now.utc.to_iso8601
18
+ end
19
+ end # def initialize
20
+
21
+ def self.from_json(json)
22
+ return Event.new(JSON.parse(json))
23
+ end # def self.from_json
24
+
25
+ def cancel
26
+ @cancelled = true
27
+ end
28
+
29
+ def cancelled?
30
+ return @cancelled
31
+ end
32
+
33
+ def to_s
34
+ return "#{timestamp} #{source}: #{message}"
35
+ end # def to_s
36
+
37
+ def timestamp; @data["@timestamp"]; end # def timestamp
38
+ def timestamp=(val); @data["@timestamp"] = val; end # def timestamp=
39
+
40
+ def source; @data["@source"]; end # def source
41
+ def source=(val)
42
+ if val.is_a?(URI)
43
+ @data["@source"] = val.to_s
44
+ @data["@source_host"] = val.host
45
+ @data["@source_path"] = val.path
46
+ else
47
+ @data["@source"] = val
48
+ end
49
+ end # def source=
50
+
51
+ def message; @data["@message"]; end # def message
52
+ def message=(val); @data["@message"] = val; end # def message=
53
+
54
+ def type; @data["@type"]; end # def type
55
+ def type=(val); @data["@type"] = val; end # def type=
56
+
57
+ def tags; @data["@tags"]; end # def tags
58
+ def tags=(val); @data["@tags"] = val; end # def tags=
59
+
60
+ # field-related access
61
+ def [](key); @data["@fields"][key] end # def []
62
+ def []=(key, value); @data["@fields"][key] = value end # def []=
63
+ def fields; return @data["@fields"] end # def fields
64
+
65
+ def to_json; return @data.to_json end # def to_json
66
+
67
+ def to_hash; return @data end # def to_hash
68
+
69
+ def include?(key); return @data.include?(key) end
70
+ end; end # class LogStash::Event
@@ -0,0 +1,17 @@
1
+
2
+ require "logstash/namespace"
3
+
4
+ module LogStash::Filters
5
+ def self.from_name(name, *args)
6
+ # TODO(sissel): Add error handling
7
+ # TODO(sissel): Allow plugin paths
8
+ klass = name.capitalize
9
+
10
+ # Load the class if we haven't already.
11
+ require "logstash/filters/#{name}"
12
+
13
+ # Get the class name from the Filters namespace and create a new instance.
14
+ # for name == 'foo' this will call LogStash::Filters::Foo.new
15
+ LogStash::Filters.const_get(klass).new(*args)
16
+ end # def from_url
17
+ end # module LogStash::Filters
@@ -0,0 +1,17 @@
1
+ require "logstash/namespace"
2
+ require "logstash/logging"
3
+
4
+ class LogStash::Filters::Base
5
+ def initialize(config = {})
6
+ @logger = LogStash::Logger.new(STDERR)
7
+ @config = config
8
+ end # def initialize
9
+
10
+ def register
11
+ raise "#{self.class}#register must be overidden"
12
+ end # def register
13
+
14
+ def filter(event)
15
+ raise "#{self.class}#filter must be overidden"
16
+ end # def filter
17
+ end # class LogStash::Filters::Base
@@ -0,0 +1,59 @@
1
+ require "logstash/filters/base"
2
+ require "logstash/time"
3
+
4
+ class LogStash::Filters::Date < LogStash::Filters::Base
5
+ # The 'date' filter will take a value from your event and use it as the
6
+ # event timestamp. This is useful for parsing logs generated on remote
7
+ # servers or for importing old logs.
8
+ #
9
+ # The config looks like this:
10
+ #
11
+ # filters:
12
+ # date:
13
+ # <type>:
14
+ # <fieldname>: <format>
15
+ # <type>
16
+ # <fieldname>: <format>
17
+ #
18
+ # The format is whatever is supported by Ruby's DateTime.strptime
19
+ def initialize(config = {})
20
+ super
21
+
22
+ @types = Hash.new { |h,k| h[k] = [] }
23
+ end # def initialize
24
+
25
+ def register
26
+ @config.each do |type, typeconfig|
27
+ @logger.debug "Setting type #{type.inspect} to the config #{typeconfig.inspect}"
28
+ raise "date filter type \"#{type}\" defined more than once" unless @types[type].empty?
29
+ @types[type] = typeconfig
30
+ end # @config.each
31
+ end # def register
32
+
33
+ def filter(event)
34
+ @logger.debug "DATE FILTER: received event of type #{event.type}"
35
+ return unless @types.member?(event.type)
36
+ @types[event.type].each do |field, format|
37
+ @logger.debug "DATE FILTER: type #{event.type}, looking for field #{field.inspect} with format #{format.inspect}"
38
+ # TODO(sissel): check event.message, too.
39
+ if event.fields.member?(field)
40
+ fieldvalue = event.fields[field]
41
+ fieldvalue = [fieldvalue] if fieldvalue.is_a?(String)
42
+ fieldvalue.each do |value|
43
+ begin
44
+ case format
45
+ when "ISO8601"
46
+ time = DateTime.parse(value)
47
+ else
48
+ time = DateTime.strptime(value, format)
49
+ end
50
+ event.timestamp = LogStash::Time.to_iso8601(time)
51
+ @logger.debug "Parsed #{value.inspect} as #{event.timestamp}"
52
+ rescue
53
+ @logger.warn "Failed parsing date #{value.inspect} from field #{field} with format #{format.inspect}: #{$!}"
54
+ end
55
+ end # fieldvalue.each
56
+ end # if this event has a field we expect to be a timestamp
57
+ end # @types[event.type].each
58
+ end # def filter
59
+ end # class LogStash::Filters::Date
@@ -0,0 +1,29 @@
1
+ require "logstash/filters/base"
2
+ require "ostruct"
3
+
4
+ class LogStash::Filters::Field < LogStash::Filters::Base
5
+ class EvalSpace < OpenStruct
6
+ def get_binding
7
+ return binding
8
+ end
9
+ end
10
+
11
+ def initialize(config = {})
12
+ super
13
+ end # def initialize
14
+
15
+ def register
16
+ # nothing to do
17
+ end # def register
18
+
19
+ def filter(event)
20
+ data = EvalSpace.new(event.to_hash)
21
+
22
+ @config.each do |condition|
23
+ if data.instance_eval(condition)
24
+ return # This event is OK, matches the condition.
25
+ end
26
+ end
27
+ event.cancel
28
+ end
29
+ end # class LogStash::Filters::Field
@@ -0,0 +1,74 @@
1
+ require "logstash/filters/base"
2
+
3
+ gem "jls-grok", ">=0.2.3071"
4
+ require "grok" # rubygem 'jls-grok'
5
+
6
+ class LogStash::Filters::Grok < LogStash::Filters::Base
7
+ def initialize(config = {})
8
+ super
9
+
10
+ @grokpiles = {}
11
+ end # def initialize
12
+
13
+ def register
14
+ # TODO(sissel): Make patterns files come from the config
15
+ @config.each do |type, typeconfig|
16
+ @logger.debug("Registering type with grok: #{type}")
17
+ pile = Grok::Pile.new
18
+ patterndir = "#{File.dirname(__FILE__)}/../../../patterns/*"
19
+ Dir.glob(patterndir).each do |path|
20
+ pile.add_patterns_from_file(path)
21
+ end
22
+ typeconfig["patterns"].each do |pattern|
23
+ groks = pile.compile(pattern)
24
+ @logger.debug(["Compiled pattern", pattern, groks[-1].expanded_pattern])
25
+ end
26
+ @grokpiles[type] = pile
27
+ end # @config.each
28
+ end # def register
29
+
30
+ def filter(event)
31
+ # parse it with grok
32
+ message = event.message
33
+ match = false
34
+
35
+ if event.type
36
+ if @grokpiles.include?(event.type)
37
+ @logger.debug(["Running grok filter", event])
38
+ pile = @grokpiles[event.type]
39
+ grok, match = pile.match(message)
40
+ end # @grokpiles.include?(event.type)
41
+ # TODO(2.0): support grok pattern discovery
42
+ else
43
+ @logger.info("Unknown type for #{event.source} (type: #{event.type})")
44
+ @logger.debug(event.to_hash)
45
+ end
46
+
47
+ if match
48
+ match.each_capture do |key, value|
49
+ if key.include?(":")
50
+ key = key.split(":")[1]
51
+ end
52
+ if event.message == value
53
+ # Skip patterns that match the entire line
54
+ @logger.debug("Skipping capture '#{key}' since it matches the whole line.")
55
+ next
56
+ end
57
+
58
+ if event.fields[key].is_a?(String)
59
+ event.fields[key] = [event.fields[key]]
60
+ elsif event.fields[key] == nil
61
+ event.fields[key] = []
62
+ end
63
+
64
+ event.fields[key] << value
65
+ end
66
+ else
67
+ # Tag this event if we can't parse it. We can use this later to
68
+ # reparse+reindex logs if we improve the patterns given .
69
+ event.tags << "_grokparsefailure"
70
+ end
71
+
72
+ @logger.debug(["Event now: ", event.to_hash])
73
+ end # def filter
74
+ end # class LogStash::Filters::Grok