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.
- data/bin/logstash +13 -2
- data/bin/logstash-test +1 -3
- data/lib/logstash.rb +1 -1
- data/lib/logstash/agent.rb +37 -40
- data/lib/logstash/event.rb +20 -5
- data/lib/logstash/filters.rb +1 -1
- data/lib/logstash/filters/base.rb +6 -1
- data/lib/logstash/filters/date.rb +4 -0
- data/lib/logstash/filters/field.rb +4 -5
- data/lib/logstash/filters/grep.rb +39 -3
- data/lib/logstash/filters/grok.rb +10 -3
- data/lib/logstash/filters/grokdiscovery.rb +4 -1
- data/lib/logstash/filters/multiline.rb +6 -2
- data/lib/logstash/inputs.rb +6 -2
- data/lib/logstash/inputs/amqp.rb +5 -2
- data/lib/logstash/inputs/base.rb +17 -4
- data/lib/logstash/inputs/beanstalk.rb +5 -2
- data/lib/logstash/inputs/file.rb +7 -2
- data/lib/logstash/inputs/internal.rb +5 -2
- data/lib/logstash/inputs/stdin.rb +38 -0
- data/lib/logstash/inputs/stomp.rb +14 -12
- data/lib/logstash/inputs/syslog.rb +10 -5
- data/lib/logstash/inputs/tcp.rb +8 -3
- data/lib/logstash/inputs/twitter.rb +81 -0
- data/lib/logstash/logging.rb +4 -1
- data/lib/logstash/namespace.rb +0 -1
- data/lib/logstash/outputs.rb +1 -1
- data/lib/logstash/outputs/amqp.rb +9 -2
- data/lib/logstash/outputs/base.rb +7 -3
- data/lib/logstash/outputs/beanstalk.rb +4 -0
- data/lib/logstash/outputs/elasticsearch.rb +86 -18
- data/lib/logstash/outputs/gelf.rb +5 -6
- data/lib/logstash/outputs/internal.rb +7 -1
- data/lib/logstash/outputs/mongodb.rb +10 -10
- data/lib/logstash/outputs/nagios.rb +6 -2
- data/lib/logstash/outputs/stdout.rb +3 -4
- data/lib/logstash/outputs/stomp.rb +4 -0
- data/lib/logstash/outputs/tcp.rb +3 -4
- data/lib/logstash/outputs/websocket.rb +5 -6
- data/lib/logstash/ruby_fixes.rb +1 -3
- data/lib/logstash/stomp/handler.rb +29 -4
- data/lib/logstash/web/lib/elasticsearch.rb +8 -4
- data/lib/logstash/web/public/js/logstash.js +25 -5
- data/lib/logstash/web/public/ws/index.html +9 -7
- data/lib/logstash/web/server.rb +50 -12
- data/lib/logstash/web/views/search/ajax.haml +5 -2
- data/lib/logstash/web/views/search/results.txt.erb +10 -0
- 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)
|
data/lib/logstash/outputs/tcp.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
36
|
+
end # def receive
|
38
37
|
end # class LogStash::Outputs::Websocket
|
data/lib/logstash/ruby_fixes.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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("<", "<").replace(">", ">")
|
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 =
|
109
|
+
var params = logstash.parse_params(location.href);
|
87
110
|
for (var p in params) {
|
88
|
-
|
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
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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>
|
data/lib/logstash/web/server.rb
CHANGED
@@ -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 "
|
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
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
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
|
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
|
-
|
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:
|
4
|
+
hash: 40220224230017
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
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:
|
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
|