logstash-lite 0.2.20101222161646 → 0.2.20110112115019

Sign up to get free protection for your applications and to get access to all the features.
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