logstash-lite 0.2.20101222161646 → 0.2.20110112115019

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 (48) hide show
  1. data/bin/logstash +13 -2
  2. data/bin/logstash-test +1 -3
  3. data/lib/logstash.rb +1 -1
  4. data/lib/logstash/agent.rb +37 -40
  5. data/lib/logstash/event.rb +20 -5
  6. data/lib/logstash/filters.rb +1 -1
  7. data/lib/logstash/filters/base.rb +6 -1
  8. data/lib/logstash/filters/date.rb +4 -0
  9. data/lib/logstash/filters/field.rb +4 -5
  10. data/lib/logstash/filters/grep.rb +39 -3
  11. data/lib/logstash/filters/grok.rb +10 -3
  12. data/lib/logstash/filters/grokdiscovery.rb +4 -1
  13. data/lib/logstash/filters/multiline.rb +6 -2
  14. data/lib/logstash/inputs.rb +6 -2
  15. data/lib/logstash/inputs/amqp.rb +5 -2
  16. data/lib/logstash/inputs/base.rb +17 -4
  17. data/lib/logstash/inputs/beanstalk.rb +5 -2
  18. data/lib/logstash/inputs/file.rb +7 -2
  19. data/lib/logstash/inputs/internal.rb +5 -2
  20. data/lib/logstash/inputs/stdin.rb +38 -0
  21. data/lib/logstash/inputs/stomp.rb +14 -12
  22. data/lib/logstash/inputs/syslog.rb +10 -5
  23. data/lib/logstash/inputs/tcp.rb +8 -3
  24. data/lib/logstash/inputs/twitter.rb +81 -0
  25. data/lib/logstash/logging.rb +4 -1
  26. data/lib/logstash/namespace.rb +0 -1
  27. data/lib/logstash/outputs.rb +1 -1
  28. data/lib/logstash/outputs/amqp.rb +9 -2
  29. data/lib/logstash/outputs/base.rb +7 -3
  30. data/lib/logstash/outputs/beanstalk.rb +4 -0
  31. data/lib/logstash/outputs/elasticsearch.rb +86 -18
  32. data/lib/logstash/outputs/gelf.rb +5 -6
  33. data/lib/logstash/outputs/internal.rb +7 -1
  34. data/lib/logstash/outputs/mongodb.rb +10 -10
  35. data/lib/logstash/outputs/nagios.rb +6 -2
  36. data/lib/logstash/outputs/stdout.rb +3 -4
  37. data/lib/logstash/outputs/stomp.rb +4 -0
  38. data/lib/logstash/outputs/tcp.rb +3 -4
  39. data/lib/logstash/outputs/websocket.rb +5 -6
  40. data/lib/logstash/ruby_fixes.rb +1 -3
  41. data/lib/logstash/stomp/handler.rb +29 -4
  42. data/lib/logstash/web/lib/elasticsearch.rb +8 -4
  43. data/lib/logstash/web/public/js/logstash.js +25 -5
  44. data/lib/logstash/web/public/ws/index.html +9 -7
  45. data/lib/logstash/web/server.rb +50 -12
  46. data/lib/logstash/web/views/search/ajax.haml +5 -2
  47. data/lib/logstash/web/views/search/results.txt.erb +10 -0
  48. metadata +7 -4
data/bin/logstash CHANGED
@@ -68,8 +68,19 @@ if settings.daemonize
68
68
  end
69
69
  end
70
70
 
71
- agent = LogStash::Agent.new(config)
72
71
  if settings.logfile
73
- agent.log_to(settings.logfile)
72
+ logfile = File.open(settings.logfile, "w")
73
+ STDOUT.reopen(logfile)
74
+ STDERR.reopen(logfile)
75
+ elsif settings.daemonize
76
+ # Write to /dev/null if
77
+ devnull = File.open("/dev/null", "w")
78
+ STDOUT.reopen(devnull)
79
+ STDERR.reopen(devnull)
74
80
  end
81
+
82
+ agent = LogStash::Agent.new(config)
83
+ #if settings.logfile
84
+ #agent.log_to(settings.logfile)
85
+ #end
75
86
  agent.run
data/bin/logstash-test CHANGED
@@ -60,9 +60,7 @@ def check_libraries
60
60
  end
61
61
 
62
62
  def run_tests
63
- require "logstash/test_syntax"
64
- require "logstash/filters/test_date"
65
- require "logstash/filters/test_multiline"
63
+ require "#{File.dirname(__FILE__)}/../test/run"
66
64
  return Test::Unit::AutoRunner.run
67
65
  end
68
66
 
data/lib/logstash.rb CHANGED
@@ -1,3 +1,3 @@
1
- require "logstash/namespace"
2
1
  require "logstash/agent"
3
2
  require "logstash/event"
3
+ require "logstash/namespace"
@@ -13,6 +13,7 @@ class LogStash::Agent
13
13
  attr_reader :outputs
14
14
  attr_reader :filters
15
15
 
16
+ public
16
17
  def initialize(config)
17
18
  log_to(STDERR)
18
19
 
@@ -44,28 +45,26 @@ class LogStash::Agent
44
45
  end
45
46
 
46
47
  # Register input and output stuff
47
- if @config.include?("inputs")
48
- inputs = @config["inputs"]
49
- inputs.each do |value|
50
- # If 'url' is an array, then inputs is a hash and the key is the type
51
- if inputs.is_a?(Hash)
52
- type, urls = value
53
- else
54
- raise "config error, no type for url #{urls.inspect}"
55
- end
48
+ inputs = @config["inputs"]
49
+ inputs.each do |value|
50
+ # If 'url' is an array, then inputs is a hash and the key is the type
51
+ if inputs.is_a?(Hash)
52
+ type, urls = value
53
+ else
54
+ raise "config error, no type for url #{urls.inspect}"
55
+ end
56
56
 
57
- # url could be a string or an array.
58
- urls = [urls] if !urls.is_a?(Array)
57
+ # url could be a string or an array.
58
+ urls = [urls] if !urls.is_a?(Array)
59
59
 
60
- urls.each do |url|
61
- @logger.debug("Using input #{url} of type #{type}")
62
- input = LogStash::Inputs.from_url(url, type) { |event| receive(event) }
63
- input.logger = @logger
64
- input.register
65
- @inputs << input
66
- end
67
- end # each input
68
- end
60
+ urls.each do |url|
61
+ @logger.debug("Using input #{url} of type #{type}")
62
+ input = LogStash::Inputs.from_url(url, type) { |event| receive(event) }
63
+ input.logger = @logger
64
+ input.register
65
+ @inputs << input
66
+ end
67
+ end # each input
69
68
 
70
69
  if @config.include?("filters")
71
70
  filters = @config["filters"]
@@ -77,20 +76,18 @@ class LogStash::Agent
77
76
  filter.register
78
77
  @filters << filter
79
78
  end # each filter
80
- end
81
-
82
- if @config.include?("outputs")
83
- @config["outputs"].each do |url|
84
- @logger.debug("Using output #{url}")
85
- output = LogStash::Outputs.from_url(url)
86
- output.logger = @logger
87
- output.register
88
- @outputs << output
89
- end # each output
90
- end
79
+ end # if we have filters
80
+
81
+ @config["outputs"].each do |url|
82
+ @logger.debug("Using output #{url}")
83
+ output = LogStash::Outputs.from_url(url)
84
+ output.logger = @logger
85
+ output.register
86
+ @outputs << output
87
+ end # each output
91
88
 
92
89
  # Register any signal handlers
93
- sighandler
90
+ register_signal_handler
94
91
  end # def register
95
92
 
96
93
  public
@@ -106,16 +103,16 @@ class LogStash::Agent
106
103
  # TODO(sissel): Stop inputs, fluch outputs, wait for finish,
107
104
  # then stop the event loop
108
105
  EventMachine.stop_event_loop
109
- end
106
+
107
+ # EventMachine has no default way to indicate a 'stopping' state.
108
+ $EVENTMACHINE_STOPPING = true
109
+ end # def stop
110
110
 
111
111
  protected
112
112
  def filter(event)
113
113
  @filters.each do |f|
114
- # TODO(sissel): Add ability for a filter to cancel/drop a message
115
114
  f.filter(event)
116
- if event.cancelled?
117
- break
118
- end
115
+ break if event.cancelled?
119
116
  end
120
117
  end # def filter
121
118
 
@@ -137,7 +134,7 @@ class LogStash::Agent
137
134
  end # def input
138
135
 
139
136
  public
140
- def sighandler
137
+ def register_signal_handler
141
138
  @sigchannel = EventMachine::Channel.new
142
139
  Signal.trap("USR1") do
143
140
  @sigchannel.push(:USR1)
@@ -172,5 +169,5 @@ class LogStash::Agent
172
169
  # hooks.
173
170
  end # case msg
174
171
  end # @sigchannel.subscribe
175
- end # def sighandler
176
- end # class LogStash::Components::Agent
172
+ end # def register_signal_handler
173
+ end # class LogStash::Agent
@@ -1,9 +1,11 @@
1
1
  require "json"
2
2
  require "logstash/time"
3
+ require "logstash/namespace"
3
4
  require "uri"
4
5
 
5
6
  # General event type. Will expand this in the future.
6
- module LogStash; class Event
7
+ class LogStash::Event
8
+ public
7
9
  def initialize(data=Hash.new)
8
10
  @cancelled = false
9
11
  @data = {
@@ -18,25 +20,31 @@ module LogStash; class Event
18
20
  end
19
21
  end # def initialize
20
22
 
23
+ public
21
24
  def self.from_json(json)
22
- return Event.new(JSON.parse(json))
25
+ return LogStash::Event.new(JSON.parse(json))
23
26
  end # def self.from_json
24
27
 
28
+ public
25
29
  def cancel
26
30
  @cancelled = true
27
31
  end
28
32
 
33
+ public
29
34
  def cancelled?
30
35
  return @cancelled
31
36
  end
32
37
 
38
+ public
33
39
  def to_s
34
40
  return "#{timestamp} #{source}: #{message}"
35
41
  end # def to_s
36
42
 
43
+ public
37
44
  def timestamp; @data["@timestamp"]; end # def timestamp
38
45
  def timestamp=(val); @data["@timestamp"] = val; end # def timestamp=
39
46
 
47
+ public
40
48
  def source; @data["@source"]; end # def source
41
49
  def source=(val)
42
50
  if val.is_a?(URI)
@@ -48,31 +56,38 @@ module LogStash; class Event
48
56
  end
49
57
  end # def source=
50
58
 
59
+ public
51
60
  def message; @data["@message"]; end # def message
52
61
  def message=(val); @data["@message"] = val; end # def message=
53
62
 
63
+ public
54
64
  def type; @data["@type"]; end # def type
55
65
  def type=(val); @data["@type"] = val; end # def type=
56
66
 
67
+ public
57
68
  def tags; @data["@tags"]; end # def tags
58
69
  def tags=(val); @data["@tags"] = val; end # def tags=
59
70
 
60
71
  # field-related access
72
+ public
61
73
  def [](key); @data["@fields"][key] end # def []
62
74
  def []=(key, value); @data["@fields"][key] = value end # def []=
63
75
  def fields; return @data["@fields"] end # def fields
64
76
 
77
+ public
65
78
  def to_json; return @data.to_json end # def to_json
66
-
67
79
  def to_hash; return @data end # def to_hash
68
80
 
81
+ public
69
82
  def overwrite(event)
70
83
  @data = event.to_hash
71
84
  end
72
85
 
86
+ public
73
87
  def include?(key); return @data.include?(key) end
74
88
 
75
89
  # Append an event to this one.
90
+ public
76
91
  def append(event)
77
92
  self.message += "\n" + event.message
78
93
  self.tags |= event.tags
@@ -87,5 +102,5 @@ module LogStash; class Event
87
102
  self.fields[name] = value
88
103
  end
89
104
  end # event.fields.each
90
- end
91
- end; end # class LogStash::Event
105
+ end # def append
106
+ end # class LogStash::Event
@@ -1,7 +1,7 @@
1
-
2
1
  require "logstash/namespace"
3
2
 
4
3
  module LogStash::Filters
4
+ public
5
5
  def self.from_name(name, *args)
6
6
  # TODO(sissel): Add error handling
7
7
  # TODO(sissel): Allow plugin paths
@@ -3,24 +3,29 @@ require "logstash/logging"
3
3
 
4
4
  class LogStash::Filters::Base
5
5
  attr_accessor :logger
6
+
7
+ public
6
8
  def initialize(config = {})
7
9
  @logger = LogStash::Logger.new(STDERR)
8
10
  @config = config
9
11
  end # def initialize
10
12
 
13
+ public
11
14
  def register
12
15
  raise "#{self.class}#register must be overidden"
13
16
  end # def register
14
17
 
18
+ public
15
19
  def filter(event)
16
20
  raise "#{self.class}#filter must be overidden"
17
21
  end # def filter
18
22
 
23
+ public
19
24
  def add_config(type, typeconfig)
20
25
  if @config.include?(type)
21
26
  @config[type].merge!(typeconfig)
22
27
  else
23
28
  @config[type] = typeconfig
24
29
  end
25
- end
30
+ end # def add_config
26
31
  end # class LogStash::Filters::Base
@@ -1,4 +1,5 @@
1
1
  require "logstash/filters/base"
2
+ require "logstash/namespace"
2
3
  require "logstash/time"
3
4
 
4
5
  class LogStash::Filters::Date < LogStash::Filters::Base
@@ -16,12 +17,14 @@ class LogStash::Filters::Date < LogStash::Filters::Base
16
17
  # <fieldname>: <format>
17
18
  #
18
19
  # The format is whatever is supported by Ruby's DateTime.strptime
20
+ public
19
21
  def initialize(config = {})
20
22
  super
21
23
 
22
24
  @types = Hash.new { |h,k| h[k] = [] }
23
25
  end # def initialize
24
26
 
27
+ public
25
28
  def register
26
29
  @config.each do |type, typeconfig|
27
30
  @logger.debug "Setting type #{type.inspect} to the config #{typeconfig.inspect}"
@@ -30,6 +33,7 @@ class LogStash::Filters::Date < LogStash::Filters::Base
30
33
  end # @config.each
31
34
  end # def register
32
35
 
36
+ public
33
37
  def filter(event)
34
38
  @logger.debug "DATE FILTER: received event of type #{event.type}"
35
39
  return unless @types.member?(event.type)
@@ -1,4 +1,5 @@
1
1
  require "logstash/filters/base"
2
+ require "logstash/namespace"
2
3
  require "ostruct"
3
4
 
4
5
  class LogStash::Filters::Field < LogStash::Filters::Base
@@ -8,14 +9,12 @@ class LogStash::Filters::Field < LogStash::Filters::Base
8
9
  end
9
10
  end
10
11
 
11
- def initialize(config = {})
12
- super
13
- end # def initialize
14
-
12
+ public
15
13
  def register
16
14
  # nothing to do
17
15
  end # def register
18
16
 
17
+ public
19
18
  def filter(event)
20
19
  data = EvalSpace.new(event.to_hash)
21
20
 
@@ -25,5 +24,5 @@ class LogStash::Filters::Field < LogStash::Filters::Base
25
24
  end
26
25
  end
27
26
  event.cancel
28
- end
27
+ end # def filter
29
28
  end # class LogStash::Filters::Field
@@ -1,12 +1,37 @@
1
1
  require "logstash/filters/base"
2
+ require "logstash/namespace"
2
3
 
4
+ # Grep filter.
5
+ #
6
+ # Useful for:
7
+ # * Dropping events
8
+ # * Tagging events
9
+ # * Adding static fields
10
+ #
11
+ # Events not matched ar dropped. If 'negate' is set to true (defaults false), then
12
+ # matching events are dropped.
13
+ #
14
+ # Config:
15
+ # - grep:
16
+ # <type>:
17
+ # - match:
18
+ # <field>: <regexp>
19
+ # negate: true/false
20
+ # add_fields:
21
+ # <field>: <value>
22
+ # add_tags:
23
+ # - tag1
24
+ # - tag2
25
+ #
3
26
  class LogStash::Filters::Grep < LogStash::Filters::Base
27
+ public
4
28
  def initialize(config = {})
5
29
  super
6
30
 
7
31
  @config = config
8
32
  end # def initialize
9
33
 
34
+ public
10
35
  def register
11
36
  @config.each do |type, matches|
12
37
  if ! matches.is_a?(Array)
@@ -29,6 +54,7 @@ class LogStash::Filters::Grep < LogStash::Filters::Base
29
54
  end # @config.each
30
55
  end # def register
31
56
 
57
+ public
32
58
  def filter(event)
33
59
  config = @config[event.type]
34
60
  if not config
@@ -37,7 +63,7 @@ class LogStash::Filters::Grep < LogStash::Filters::Base
37
63
  return
38
64
  end
39
65
 
40
- @logger.debug(["Running grep filter", event, config])
66
+ @logger.debug(["Running grep filter", event.to_hash, config])
41
67
  matched = false
42
68
  config.each do |match|
43
69
  if ! match["match"]
@@ -51,9 +77,18 @@ class LogStash::Filters::Grep < LogStash::Filters::Base
51
77
  match["match"].each do |field, re|
52
78
  next unless event[field]
53
79
 
80
+ if event[field].empty? and match["negate"] == true
81
+ match_count += 1
82
+ end
54
83
  event[field].each do |value|
55
- next unless re.match(value)
56
- @logger.debug("grep matched on field #{field}")
84
+ if match["negate"] == true
85
+ @logger.debug("want negate match")
86
+ next if re.match(value)
87
+ @logger.debug(["grep not-matched (negate requsted)", { field => value }])
88
+ else
89
+ next unless re.match(value)
90
+ @logger.debug(["grep matched", { field => value }])
91
+ end
57
92
  match_count += 1
58
93
  break
59
94
  end
@@ -77,6 +112,7 @@ class LogStash::Filters::Grep < LogStash::Filters::Base
77
112
  @logger.debug("grep: adding tag #{tag}")
78
113
  end
79
114
  end # if match["add_tags"]
115
+
80
116
  else
81
117
  @logger.debug("match block failed " \
82
118
  "(#{match_count}/#{match["match"].length} matches)")
@@ -1,15 +1,18 @@
1
1
  require "logstash/filters/base"
2
+ require "logstash/namespace"
2
3
 
3
4
  gem "jls-grok", ">=0.2.3071"
4
5
  require "grok" # rubygem 'jls-grok'
5
6
 
6
7
  class LogStash::Filters::Grok < LogStash::Filters::Base
8
+ public
7
9
  def initialize(config = {})
8
10
  super
9
11
 
10
12
  @grokpiles = {}
11
13
  end # def initialize
12
14
 
15
+ public
13
16
  def register
14
17
  # TODO(sissel): Make patterns files come from the config
15
18
  @config.each do |type, typeconfig|
@@ -27,6 +30,7 @@ class LogStash::Filters::Grok < LogStash::Filters::Base
27
30
  end # @config.each
28
31
  end # def register
29
32
 
33
+ public
30
34
  def filter(event)
31
35
  # parse it with grok
32
36
  message = event.message
@@ -38,9 +42,10 @@ class LogStash::Filters::Grok < LogStash::Filters::Base
38
42
  pile = @grokpiles[event.type]
39
43
  grok, match = pile.match(message)
40
44
  end # @grokpiles.include?(event.type)
41
- else
42
- return
45
+ # TODO(2.0): support grok pattern discovery
46
+ else
43
47
  @logger.info("Unknown type for #{event.source} (type: #{event.type})")
48
+ @logger.debug(event.to_hash)
44
49
  end
45
50
 
46
51
  if match
@@ -60,7 +65,9 @@ class LogStash::Filters::Grok < LogStash::Filters::Base
60
65
  event.fields[key] = []
61
66
  end
62
67
 
63
- event.fields[key] << value
68
+ if value && !value.empty?
69
+ event.fields[key] << value
70
+ end
64
71
  end
65
72
  else
66
73
  # Tag this event if we can't parse it. We can use this later to