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
@@ -1,20 +1,24 @@
1
1
  require "logstash/outputs/base"
2
+ require "logstash/namespace"
2
3
  require "logstash/stomp/handler"
3
4
 
4
5
  class LogStash::Outputs::Stomp < LogStash::Outputs::Base
5
6
  attr_reader :url
6
7
 
8
+ public
7
9
  def initialize(url, config={}, &block)
8
10
  super
9
11
 
10
12
  @logger.debug(["Initialize", { :url => @url }])
11
13
  end # def initialize
12
14
 
15
+ public
13
16
  def register
14
17
  @logger.info(["Registering output", { :url => @url }])
15
18
  @connection = EventMachine::connect(@url.host, @url.port, LogStash::Stomp::Handler, self, @logger, @url)
16
19
  end # def register
17
20
 
21
+ public
18
22
  def receive(event)
19
23
  @logger.debug(["Sending event", { :url => @url, :event => event }])
20
24
  @connection.send(@url.path, event.to_json)
@@ -1,10 +1,8 @@
1
1
  require "logstash/outputs/base"
2
+ require "logstash/namespace"
2
3
 
3
4
  class LogStash::Outputs::Tcp < LogStash::Outputs::Base
4
- def initialize(url, config={}, &block)
5
- super
6
- end
7
-
5
+ public
8
6
  def register
9
7
  # TODO(sissel): Write generic validation methods
10
8
  if !@url.host or !@url.port
@@ -16,6 +14,7 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
16
14
  @connection = EventMachine::connect(@url.host, @url.port)
17
15
  end # def register
18
16
 
17
+ public
19
18
  def receive(event)
20
19
  @connection.send_data(event.to_hash.to_json)
21
20
  @connection.send_data("\n")
@@ -1,11 +1,9 @@
1
- require "logstash/outputs/base"
2
1
  require "em-websocket" # rubygem 'em-websocket'
2
+ require "logstash/namespace"
3
+ require "logstash/outputs/base"
3
4
 
4
5
  class LogStash::Outputs::Websocket < LogStash::Outputs::Base
5
- def initialize(url, config={}, &block)
6
- super
7
- end
8
-
6
+ public
9
7
  def register
10
8
  @channel = EventMachine::Channel.new
11
9
  @subscribers = 0
@@ -27,6 +25,7 @@ class LogStash::Outputs::Websocket < LogStash::Outputs::Base
27
25
  end
28
26
  end # def register
29
27
 
28
+ public
30
29
  def receive(event)
31
30
  # Only publish the event to websockets if there are subscribers
32
31
  # TODO(sissel): send a patch to eventmachine to fix this.
@@ -34,5 +33,5 @@ class LogStash::Outputs::Websocket < LogStash::Outputs::Base
34
33
  @logger.info("Sending event to websocket.")
35
34
  @channel.push event.to_json
36
35
  end
37
- end # def event
36
+ end # def receive
38
37
  end # class LogStash::Outputs::Websocket
@@ -1,12 +1,10 @@
1
-
2
-
3
1
  # Ruby 1.8.7 added String#start_with? - monkeypatch the
4
2
  # String class if it isn't supported (<= ruby 1.8.6)
5
3
  if !String.instance_methods.include?("start_with?")
6
4
  class String
5
+ public
7
6
  def start_with?(str)
8
7
  return self[0 .. (str.length-1)] == str
9
8
  end
10
9
  end
11
10
  end
12
-
@@ -1,3 +1,5 @@
1
+ require "logstash/namespace"
2
+
1
3
  # Base of Stomp Handler
2
4
  # it handles connecting and subscribing to the stomp broker which
3
5
  # is used in both stomp input and output
@@ -5,29 +7,52 @@ class LogStash::Stomp
5
7
  class Handler < EventMachine::Connection
6
8
  include EM::Protocols::Stomp
7
9
 
10
+ attr_accessor :should_subscribe
11
+ attr_accessor :ready
12
+
13
+ public
8
14
  def initialize(*args)
9
15
  super
10
16
 
11
17
  @input = args[0]
12
18
  @logger = args[1]
13
19
  @url = args[2]
20
+ @should_subscribe = true
21
+ @ready = false
14
22
  end # def initialize
15
23
 
24
+ public
16
25
  def connection_completed
17
26
  @logger.debug("Connected")
18
27
  connect :login => @url.user, :passcode => @url.password
28
+ @ready = true
19
29
  end # def connection_completed
20
30
 
31
+ public
21
32
  def unbind
22
- @logger.error(["Error when connecting to stomp broker", { :url => @url }])
33
+ if $EVENTMACHINE_STOPPING
34
+ @logger.debug(["Connection to stomp broker died (probably since we are exiting)",
35
+ { :url => @url }])
36
+ return
37
+ end
38
+
39
+ @logger.error(["Connection to stomp broker died, retrying.", { :url => @url }])
40
+ @ready = false
41
+ EventMachine::Timer.new(1) do
42
+ reconnect(@url.host, @url.port)
43
+ end
23
44
  end # def unbind
24
45
 
46
+ public
25
47
  def receive_msg(message)
26
48
  @logger.debug(["receiving message", { :msg => message }])
27
49
  if message.command == "CONNECTED"
28
- @logger.debug(["subscribing to", { :path => @url.path }])
29
- subscribe @url.path
30
- return
50
+ if @should_subscribe
51
+ @logger.debug(["subscribing to", { :path => @url.path }])
52
+ subscribe @url.path
53
+ return
54
+ end
55
+ @ready = true
31
56
  end
32
57
  end # def receive_msg
33
58
  end # class Handler
@@ -5,11 +5,14 @@ require "logstash/logging"
5
5
  require "logstash/event"
6
6
 
7
7
  module LogStash::Web; end
8
+
8
9
  class LogStash::Web::ElasticSearch
10
+ public
9
11
  def initialize
10
12
  @logger = LogStash::Logger.new(STDOUT)
11
13
  end
12
14
 
15
+ public
13
16
  def search(params)
14
17
  http = EventMachine::HttpRequest.new("http://localhost:9200/_search")
15
18
  params[:offset] ||= 0
@@ -37,7 +40,8 @@ class LogStash::Web::ElasticSearch
37
40
  "from" => params[:offset],
38
41
  "size" => params[:count],
39
42
  }
40
- #@logger.info(["ElasticSearch Query", esreq])
43
+
44
+ @logger.info("ElasticSearch Query: #{esreq.to_json}")
41
45
  start_time = Time.now
42
46
  req = http.get :body => esreq.to_json
43
47
  req.callback do
@@ -69,13 +73,13 @@ class LogStash::Web::ElasticSearch
69
73
  { :query => params[:q], :duration => data["duration"]}])
70
74
  #@logger.info(data)
71
75
  if req.response_header.status != 200
72
- @error = data["error"]
76
+ @error = data["error"] || req.inspect
73
77
  end
74
78
  yield data
75
79
  end
76
80
  req.errback do
77
- @logger.warn(["Query failed", params, req.response])
81
+ @logger.warn(["Query failed", params, req, req.response])
78
82
  yield({ "error" => req.response })
79
83
  end
80
84
  end # def search
81
- end
85
+ end # class LogStash::Web::ElasticSearch
@@ -7,12 +7,28 @@
7
7
  },
8
8
 
9
9
  search: function(query) {
10
+ if (query == undefined || query == "") {
11
+ return;
12
+ }
13
+ var display_query = query.replace("<", "&lt;").replace(">", "&gt;")
14
+ $("#querystatus").html("Loading query '" + display_query + "'")
10
15
  logstash.params.q = query;
11
16
  document.location.hash = escape(JSON.stringify(logstash.params));
12
17
  $("#results").load("/search/ajax", logstash.params);
13
18
  $("#query").val(logstash.params.q);
14
19
  }, /* search */
15
20
 
21
+ parse_params: function(href) {
22
+ var params = href.replace(/^[^?]*\?/, "").split("&")
23
+ for (var p in params) {
24
+ var a = params[p].split("=");
25
+ var key = a[0]
26
+ var value = a[1]
27
+ logstash.params[key] = unescape(value)
28
+ }
29
+ return params;
30
+ },
31
+
16
32
  appendquery: function(query) {
17
33
  var newquery = $("#query").val();
18
34
  newquery += " " + query;
@@ -70,6 +86,13 @@
70
86
  // Do nothing
71
87
  }
72
88
  logstash.search(logstash.params.q);
89
+ } else {
90
+ /* No hash. See if there's a query param. */
91
+ var params = logstash.parse_params(location.href);
92
+ for (var p in params) {
93
+ logstash.params[p] = params[p];
94
+ }
95
+ logstash.search(logstash.params.q)
73
96
  }
74
97
 
75
98
  $(window).hashchange(function() {
@@ -83,12 +106,9 @@
83
106
 
84
107
  $("a.pager").live("click", function() {
85
108
  var href = $(this).attr("href");
86
- var params = href.replace(/^[^?]*\?/, "").split("&")
109
+ var params = logstash.parse_params(location.href);
87
110
  for (var p in params) {
88
- var a = params[p].split("=");
89
- var key = a[0]
90
- var value = a[1]
91
- logstash.params[key] = unescape(value)
111
+ logstash.params[p] = params[p];
92
112
  }
93
113
  logstash.search(logstash.params.q)
94
114
  return false;
@@ -57,16 +57,18 @@
57
57
  //console.log(["WebSocket open", ws])
58
58
  };
59
59
  ws.onmessage = function(event) {
60
- eval("var data = " + event.data);
60
+ var data = JSON.parse(event.data);
61
61
  var el = $("#message-template").tmpl(data, { "message": data["@message"], "timestamp": data["@timestamp"] });
62
+ //.css("display", "none")
63
+ //.fadeIn()
62
64
  el.addClass("message")
63
- .css("display", "none")
64
65
  .appendTo($("#radiator"))
65
- .fadeIn()
66
- .delay(10000)
67
- .fadeOut(2000, function() {
68
- $(this).remove();
69
- });
66
+ //.delay(10000)
67
+ //.hide(2000, function() {
68
+ //$(this).remove();
69
+ //});
70
+ setTimeout(function() { $(el).remove() }, 12000)
71
+ //.fadeOut(2000, function() {
70
72
  };
71
73
  });
72
74
  </script>
@@ -4,13 +4,13 @@
4
4
  $:.unshift("%s/../lib" % File.dirname(__FILE__))
5
5
  $:.unshift(File.dirname(__FILE__))
6
6
 
7
- require "rubygems"
8
- require "json"
9
7
  require "eventmachine"
10
- require "rack"
11
- require "sinatra/async"
8
+ require "json"
12
9
  require "lib/elasticsearch"
13
10
  require "logstash/namespace"
11
+ require "rack"
12
+ require "rubygems"
13
+ require "sinatra/async"
14
14
 
15
15
  class EventMachine::ConnectionError < RuntimeError; end
16
16
 
@@ -25,24 +25,58 @@ class LogStash::Web::Server < Sinatra::Base
25
25
  aget '/style.css' do
26
26
  headers "Content-Type" => "text/css; charset=utf8"
27
27
  body sass :style
28
- end
28
+ end # /style.css
29
29
 
30
30
  aget '/' do
31
31
  redirect "/search"
32
32
  end # '/'
33
33
 
34
34
  aget '/search' do
35
- headers({"Content-Type" => "text/html" })
35
+ result_callback = proc do
36
+ status 500 if @error
37
+
38
+ params[:format] ||= "html"
39
+ case params[:format]
40
+ when "html"
41
+ headers({"Content-Type" => "text/html" })
42
+ body haml :"search/results", :layout => !request.xhr?
43
+ when "text"
44
+ headers({"Content-Type" => "text/plain" })
45
+ body erb :"search/results.txt", :layout => false
46
+ when "txt"
47
+ headers({"Content-Type" => "text/plain" })
48
+ body erb :"search/results.txt", :layout => false
49
+ when "json"
50
+ headers({"Content-Type" => "text/plain" })
51
+ hits = @hits.collect { |h| h["_source"] }
52
+ response = {
53
+ "hits" => hits,
54
+ "facets" => (@results["facets"] rescue nil),
55
+ }
56
+
57
+ response["error"] = @error if @error
58
+ body response.to_json
59
+ end # case params[:format]
60
+ end # proc result_callback
61
+
62
+ # We'll still do a search query here even though most users
63
+ # have javascript enabled, we need to show the results in
64
+ # case a user doesn't have javascript.
36
65
  if params[:q] and params[:q] != ""
37
66
  elasticsearch.search(params) do |@results|
38
67
  @hits = (@results["hits"]["hits"] rescue [])
39
- body haml :"search/results", :layout => !request.xhr?
40
- end
68
+ begin
69
+ result_callback.call
70
+ rescue => e
71
+ puts e
72
+ end
73
+ end # elasticsearch.search
41
74
  else
75
+ #@error = "No query given."
42
76
  @hits = []
43
- body haml :"search/results", :layout => !request.xhr?
77
+ result_callback.call
44
78
  end
45
- end
79
+ end # aget '/search'
46
80
 
47
81
  apost '/search/ajax' do
48
82
  headers({"Content-Type" => "text/html" })
@@ -99,10 +133,9 @@ class LogStash::Web::Server < Sinatra::Base
99
133
  body haml :"search/ajax", :layout => !request.xhr?
100
134
  end # elasticsearch.search
101
135
  end # apost '/search/ajax'
102
- end # class LogStashWeb
136
+ end # class LogStash::Web::Server
103
137
 
104
138
  require "optparse"
105
-
106
139
  Settings = Struct.new(:daemonize, :logfile)
107
140
  settings = Settings.new
108
141
  progname = File.basename($0)
@@ -133,6 +166,11 @@ if settings.logfile
133
166
  logfile = File.open(settings.logfile, "w")
134
167
  STDOUT.reopen(logfile)
135
168
  STDERR.reopen(logfile)
169
+ elsif settings.daemonize
170
+ # Write to /dev/null if
171
+ devnull = File.open("/dev/null", "w")
172
+ STDOUT.reopen(devnull)
173
+ STDERR.reopen(devnull)
136
174
  end
137
175
 
138
176
  Rack::Handler::Thin.run(
@@ -31,9 +31,12 @@
31
31
  last
32
32
  - if @hits.length == 0
33
33
  - if !params[:q]
34
- No query given. How about <a href="?q=*" class="querychanger">this?</a>
34
+ / We default to a '+2 days' in the future to capture 'today at 00:00'
35
+ / plus tomorrow, inclusive, in case you are 23 hours behind the international
36
+ / dateline.
37
+ %h3#querystatus No query given. How about <a href="?q=* @timestamp:[#{(Time.now - 7*24*60*60).strftime("%Y-%m-%d")} TO #{(Time.now + 2*24*60*60).strftime("%Y-%m-%d")}]" class="querychanger">this?</a>
35
38
  - else
36
- No results for query '#{params[:q]}'
39
+ %h3#querystatus No results for query '#{params[:q]}'
37
40
  - else
38
41
  %table.results
39
42
  %tr
@@ -0,0 +1,10 @@
1
+ <%
2
+ # Sinatra currently doesn't do ERB with newline trimming, so we
3
+ # have to write this funky mishmosh that is hard to read.
4
+ if @error %>Error: <%= @error %><% else
5
+ @hits.each do |hit|
6
+ event = LogStash::Event.new(hit["_source"])
7
+ %><%= event.message || event.to_hash.to_json %>
8
+ <% end
9
+ end
10
+ %>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-lite
3
3
  version: !ruby/object:Gem::Version
4
- hash: 40202444323275
4
+ hash: 40220224230017
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 20101222161646
10
- version: 0.2.20101222161646
9
+ - 20110112115019
10
+ version: 0.2.20110112115019
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jordan Sissel
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-12-22 00:00:00 -08:00
19
+ date: 2011-01-12 00:00:00 -08:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -95,8 +95,10 @@ files:
95
95
  - lib/logstash/inputs/internal.rb
96
96
  - lib/logstash/inputs/syslog.rb
97
97
  - lib/logstash/inputs/file.rb
98
+ - lib/logstash/inputs/stdin.rb
98
99
  - lib/logstash/inputs/base.rb
99
100
  - lib/logstash/inputs/amqp.rb
101
+ - lib/logstash/inputs/twitter.rb
100
102
  - lib/logstash/inputs/stomp.rb
101
103
  - lib/logstash/inputs/beanstalk.rb
102
104
  - lib/logstash/inputs/tcp.rb
@@ -209,6 +211,7 @@ files:
209
211
  - lib/logstash/web/views/style.sass
210
212
  - lib/logstash/web/views/main/index.haml
211
213
  - lib/logstash/web/views/layout.haml
214
+ - lib/logstash/web/views/search/results.txt.erb
212
215
  - lib/logstash/web/views/search/ajax.haml
213
216
  - lib/logstash/web/views/search/results.haml
214
217
  - lib/logstash/web/views/search/error.haml