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.
- 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
data/lib/logstash/logging.rb
CHANGED
@@ -4,7 +4,7 @@ require "logger"
|
|
4
4
|
|
5
5
|
class LogStash::Logger < Logger
|
6
6
|
# Try to load awesome_print, if it fails, log it later
|
7
|
-
# but otherwise we
|
7
|
+
# but otherwise we will continue to operate as normal.
|
8
8
|
begin
|
9
9
|
require "ap"
|
10
10
|
@@have_awesome_print = true
|
@@ -13,6 +13,7 @@ class LogStash::Logger < Logger
|
|
13
13
|
@@notify_awesome_print_load_failed = e
|
14
14
|
end
|
15
15
|
|
16
|
+
public
|
16
17
|
def initialize(*args)
|
17
18
|
super(*args)
|
18
19
|
@formatter = LogStash::Logger::Formatter.new
|
@@ -37,6 +38,7 @@ class LogStash::Logger < Logger
|
|
37
38
|
end
|
38
39
|
end # def initialize
|
39
40
|
|
41
|
+
public
|
40
42
|
def level=(level)
|
41
43
|
super(level)
|
42
44
|
@formatter.level = level
|
@@ -48,6 +50,7 @@ class LogStash::Logger::Formatter < Logger::Formatter
|
|
48
50
|
attr_accessor :level
|
49
51
|
attr_accessor :progname
|
50
52
|
|
53
|
+
public
|
51
54
|
def call(severity, timestamp, who, object)
|
52
55
|
# override progname to be the caller if the log level threshold is DEBUG
|
53
56
|
# We only do this if the logger level is DEBUG because inspecting the
|
data/lib/logstash/namespace.rb
CHANGED
data/lib/logstash/outputs.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
require "logstash/outputs/base"
|
2
1
|
require "amqp" # rubygem 'amqp'
|
2
|
+
require "logstash/outputs/base"
|
3
|
+
require "logstash/namespace"
|
3
4
|
require "mq" # rubygem 'amqp'
|
4
5
|
|
5
6
|
class LogStash::Outputs::Amqp < LogStash::Outputs::Base
|
6
7
|
MQTYPES = [ "fanout", "queue", "topic" ]
|
8
|
+
|
9
|
+
public
|
7
10
|
def initialize(url, config={}, &block)
|
8
11
|
super
|
9
12
|
|
@@ -18,9 +21,10 @@ class LogStash::Outputs::Amqp < LogStash::Outputs::Base
|
|
18
21
|
end
|
19
22
|
end # def initialize
|
20
23
|
|
24
|
+
public
|
21
25
|
def register
|
22
26
|
@logger.info("Registering output #{@url}")
|
23
|
-
@amqp = AMQP.connect(:host => @url.host)
|
27
|
+
@amqp = AMQP.connect(:host => @url.host, :port => (@url.port or 5672))
|
24
28
|
@mq = MQ.new(@amqp)
|
25
29
|
@target = nil
|
26
30
|
|
@@ -34,11 +38,14 @@ class LogStash::Outputs::Amqp < LogStash::Outputs::Base
|
|
34
38
|
end # case @mqtype
|
35
39
|
end # def register
|
36
40
|
|
41
|
+
public
|
37
42
|
def receive(event)
|
38
43
|
@logger.debug(["Sending event", { :url => @url, :event => event }])
|
39
44
|
@target.publish(event.to_json)
|
40
45
|
end # def receive
|
41
46
|
|
47
|
+
# This is used by the ElasticSearch AMQP/River output.
|
48
|
+
public
|
42
49
|
def receive_raw(raw)
|
43
50
|
if @target == nil
|
44
51
|
raise "had trouble registering AMQP URL #{@url.to_s}, @target is nil"
|
@@ -1,11 +1,13 @@
|
|
1
|
-
require "
|
1
|
+
require "cgi"
|
2
2
|
require "logstash/event"
|
3
3
|
require "logstash/logging"
|
4
|
-
require "
|
4
|
+
require "logstash/namespace"
|
5
5
|
require "uri"
|
6
6
|
|
7
7
|
class LogStash::Outputs::Base
|
8
8
|
attr_accessor :logger
|
9
|
+
|
10
|
+
public
|
9
11
|
def initialize(url, config={}, &block)
|
10
12
|
@url = url
|
11
13
|
@url = URI.parse(url) if url.is_a? String
|
@@ -20,11 +22,13 @@ class LogStash::Outputs::Base
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
public
|
23
26
|
def register
|
24
27
|
raise "#{self.class}#register must be overidden"
|
25
28
|
end # def register
|
26
29
|
|
30
|
+
public
|
27
31
|
def receive(event)
|
28
32
|
raise "#{self.class}#receive must be overidden"
|
29
|
-
end
|
33
|
+
end # def receive
|
30
34
|
end # class LogStash::Outputs::Base
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require "logstash/outputs/base"
|
2
|
+
require "logstash/namespace"
|
2
3
|
require "em-jack"
|
3
4
|
|
4
5
|
class LogStash::Outputs::Beanstalk < LogStash::Outputs::Base
|
6
|
+
public
|
5
7
|
def initialize(url, config={}, &block)
|
6
8
|
super
|
7
9
|
|
@@ -11,6 +13,7 @@ class LogStash::Outputs::Beanstalk < LogStash::Outputs::Base
|
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
16
|
+
public
|
14
17
|
def register
|
15
18
|
tube = @url.path[1..-1] # Skip leading '/'
|
16
19
|
port = @url.port || 11300
|
@@ -19,6 +22,7 @@ class LogStash::Outputs::Beanstalk < LogStash::Outputs::Base
|
|
19
22
|
:tube => tube)
|
20
23
|
end # def register
|
21
24
|
|
25
|
+
public
|
22
26
|
def receive(event)
|
23
27
|
@beanstalk.put(event.to_json, :ttr => @ttr)
|
24
28
|
end # def receive
|
@@ -1,36 +1,78 @@
|
|
1
|
-
require "logstash/outputs/base"
|
2
|
-
require "logstash/outputs/amqp"
|
3
1
|
require "em-http-request"
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/outputs/amqp"
|
4
|
+
require "logstash/outputs/base"
|
4
5
|
|
5
6
|
class LogStash::Outputs::Elasticsearch < LogStash::Outputs::Base
|
6
|
-
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
7
|
+
public
|
10
8
|
def register
|
9
|
+
@pending = []
|
11
10
|
# Port?
|
12
11
|
# Authentication?
|
13
|
-
@
|
14
|
-
@
|
12
|
+
@esurl = @url.clone
|
13
|
+
@esurl.scheme = "http"
|
14
|
+
@esurl.path = "/" + @url.path.split("/")[1]
|
15
15
|
defaults = {"method" => "http"}
|
16
16
|
params = defaults.merge(@urlopts)
|
17
17
|
|
18
|
+
# Describe this index to elasticsearch
|
19
|
+
indexmap = {
|
20
|
+
# The name of the index
|
21
|
+
"settings" => {
|
22
|
+
@url.path.split("/")[-1] => {
|
23
|
+
"mappings" => {
|
24
|
+
"@source" => { "type" => "string" },
|
25
|
+
"@source_host" => { "type" => "string" },
|
26
|
+
"@source_path" => { "type" => "string" },
|
27
|
+
"@timestamp" => { "type" => "date" },
|
28
|
+
"@tags" => { "type" => "string" },
|
29
|
+
"@message" => { "type" => "string" },
|
30
|
+
|
31
|
+
# TODO(sissel): Hack for now until this bug is resolved:
|
32
|
+
# https://github.com/elasticsearch/elasticsearch/issues/issue/604
|
33
|
+
"@fields" => {
|
34
|
+
"type" => "object",
|
35
|
+
"properties" => {
|
36
|
+
"HOSTNAME" => { "type" => "string" },
|
37
|
+
},
|
38
|
+
}, # "@fields"
|
39
|
+
}, # "properties"
|
40
|
+
}, # index map for this index type.
|
41
|
+
}, # "settings"
|
42
|
+
} # ES Index
|
43
|
+
|
44
|
+
indexurl = @esurl.to_s
|
45
|
+
indexmap_http = EventMachine::HttpRequest.new(indexurl)
|
46
|
+
indexmap_req = indexmap_http.put :body => indexmap.to_json
|
47
|
+
indexmap_req.callback do
|
48
|
+
@logger.info(["Done configuring index", indexurl, indexmap])
|
49
|
+
ready(params)
|
50
|
+
end
|
51
|
+
indexmap_req.errback do
|
52
|
+
@logger.warn(["Failure configuring index", @esurl.to_s, indexmap])
|
53
|
+
end
|
54
|
+
end # def register
|
55
|
+
|
56
|
+
public
|
57
|
+
def ready(params)
|
18
58
|
case params["method"]
|
19
59
|
when "http"
|
20
|
-
@logger.debug "ElasticSearch using http with URL #{@
|
21
|
-
@http = EventMachine::HttpRequest.new(@
|
60
|
+
@logger.debug "ElasticSearch using http with URL #{@url.to_s}"
|
61
|
+
@http = EventMachine::HttpRequest.new(@url.to_s)
|
22
62
|
@callback = self.method(:receive_http)
|
23
63
|
when "river"
|
24
|
-
|
64
|
+
params["port"] ||= 5672
|
65
|
+
mq_url = URI::parse("amqp://#{params["host"]}:#{params["port"]}/queue/#{params["queue"]}?durable=1")
|
25
66
|
@mq = LogStash::Outputs::Amqp.new(mq_url.to_s)
|
26
67
|
@mq.register
|
27
68
|
@callback = self.method(:receive_river)
|
28
|
-
em_url = URI.parse("http://#{@
|
29
|
-
unused, @es_index, @es_type = @
|
69
|
+
em_url = URI.parse("http://#{@url.host}:#{@url.port}/_river/logstash#{@url.path.tr("/", "_")}/_meta")
|
70
|
+
unused, @es_index, @es_type = @url.path.split("/", 3)
|
30
71
|
|
31
72
|
river_config = {"type" => params["type"],
|
32
73
|
params["type"] => {"host" => params["host"],
|
33
74
|
"user" => params["user"],
|
75
|
+
"port" => params["port"],
|
34
76
|
"pass" => params["pass"],
|
35
77
|
"vhost" => params["vhost"],
|
36
78
|
"queue" => params["queue"],
|
@@ -46,21 +88,47 @@ class LogStash::Outputs::Elasticsearch < LogStash::Outputs::Base
|
|
46
88
|
req.errback do
|
47
89
|
@logger.warn "Error setting up river: #{req.response}"
|
48
90
|
end
|
91
|
+
@callback = self.method(:receive_river)
|
49
92
|
else raise "unknown elasticsearch method #{params["method"].inspect}"
|
50
93
|
end
|
51
|
-
end # def register
|
52
94
|
|
95
|
+
receive(LogStash::Event.new({
|
96
|
+
"@source" => "@logstashinit",
|
97
|
+
"@type" => "@none",
|
98
|
+
"@message" => "Starting logstash output to elasticsearch",
|
99
|
+
"@fields" => {
|
100
|
+
"HOSTNAME" => Socket.gethostname
|
101
|
+
},
|
102
|
+
}))
|
103
|
+
|
104
|
+
pending = @pending
|
105
|
+
@pending = []
|
106
|
+
pending.each do |event|
|
107
|
+
receive(event)
|
108
|
+
end
|
109
|
+
end # def ready
|
110
|
+
|
111
|
+
public
|
53
112
|
def receive(event)
|
54
|
-
@callback
|
113
|
+
if @callback
|
114
|
+
@callback.call(event)
|
115
|
+
else
|
116
|
+
@pending << event
|
117
|
+
end
|
55
118
|
end # def receive
|
56
119
|
|
57
|
-
|
120
|
+
public
|
121
|
+
def receive_http(event, tries=5)
|
58
122
|
req = @http.post :body => event.to_json
|
59
123
|
req.errback do
|
60
|
-
$stderr.puts "Request to index to #{@
|
124
|
+
$stderr.puts "Request to index to #{@url.to_s} failed (will retry, #{tries} tries left). Event was #{event.to_s}"
|
125
|
+
EventMachine::add_timer(2) do
|
126
|
+
receive_http(event, tries - 1)
|
127
|
+
end
|
61
128
|
end
|
62
129
|
end # def receive_http
|
63
130
|
|
131
|
+
public
|
64
132
|
def receive_river(event)
|
65
133
|
# bulk format; see http://www.elasticsearch.com/docs/elasticsearch/river/rabbitmq/
|
66
134
|
index_message = {"index" => {"_index" => @es_index, "_type" => @es_type}}.to_json + "\n"
|
@@ -68,4 +136,4 @@ class LogStash::Outputs::Elasticsearch < LogStash::Outputs::Base
|
|
68
136
|
index_message += event.to_hash.to_json + "\n"
|
69
137
|
@mq.receive_raw(index_message)
|
70
138
|
end # def receive_river
|
71
|
-
end # class LogStash::Outputs::
|
139
|
+
end # class LogStash::Outputs::Elasticsearch
|
@@ -4,18 +4,17 @@
|
|
4
4
|
# This class doesn't currently use 'eventmachine'-style code, so it may
|
5
5
|
# block things. Whatever, we can fix that later ;)
|
6
6
|
|
7
|
-
require "gelf"
|
7
|
+
require "gelf" # rubygem 'gelf'
|
8
|
+
require "logstash/namespace"
|
8
9
|
require "logstash/outputs/base"
|
9
10
|
|
10
11
|
class LogStash::Outputs::Gelf < LogStash::Outputs::Base
|
11
|
-
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
12
|
+
public
|
15
13
|
def register
|
16
14
|
# nothing to do
|
17
15
|
end # def register
|
18
16
|
|
17
|
+
public
|
19
18
|
def receive(event)
|
20
19
|
# TODO(sissel): Use Gelf::Message instead
|
21
20
|
gelf = Gelf.new(@url.host, (@url.port or 12201))
|
@@ -31,5 +30,5 @@ class LogStash::Outputs::Gelf < LogStash::Outputs::Base
|
|
31
30
|
end
|
32
31
|
gelf.add_additional "event_timestamp", event.timestamp
|
33
32
|
gelf.send
|
34
|
-
end # def
|
33
|
+
end # def receive
|
35
34
|
end # class LogStash::Outputs::Gelf
|
@@ -1,15 +1,19 @@
|
|
1
|
+
require "logstash/namespace"
|
1
2
|
require "logstash/outputs/base"
|
2
3
|
|
3
4
|
class LogStash::Outputs::Internal < LogStash::Outputs::Base
|
5
|
+
public
|
4
6
|
def initialize(url, config={}, &block)
|
5
7
|
super
|
6
8
|
@callback = block
|
7
|
-
end
|
9
|
+
end # def initialize
|
8
10
|
|
11
|
+
public
|
9
12
|
def register
|
10
13
|
@logger.info("Registering output #{@url}")
|
11
14
|
end # def register
|
12
15
|
|
16
|
+
public
|
13
17
|
def receive(event)
|
14
18
|
if !@callback
|
15
19
|
@logger.error("No callback for output #{@url}, cannot receive")
|
@@ -19,11 +23,13 @@ class LogStash::Outputs::Internal < LogStash::Outputs::Base
|
|
19
23
|
end # def event
|
20
24
|
|
21
25
|
# Set the callback by passing a block of code
|
26
|
+
public
|
22
27
|
def callback(&block)
|
23
28
|
@callback = block
|
24
29
|
end
|
25
30
|
|
26
31
|
# Set the callback by passing a proc object
|
32
|
+
public
|
27
33
|
def callback=(proc_block)
|
28
34
|
@callback = proc_block
|
29
35
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
require "logstash/outputs/base"
|
2
|
+
require "logstash/namespace"
|
2
3
|
require "em-mongo"
|
3
4
|
|
4
5
|
class LogStash::Outputs::Mongodb < LogStash::Outputs::Base
|
5
|
-
|
6
|
-
super
|
7
|
-
end
|
8
|
-
|
6
|
+
public
|
9
7
|
def register
|
10
|
-
# Port?
|
11
|
-
# Authentication?
|
12
|
-
db
|
13
|
-
@
|
8
|
+
# TODO(sissel): Port?
|
9
|
+
# TODO(sissel): Authentication?
|
10
|
+
# db and collection are mongodb://.../db/collection
|
11
|
+
unused, @db, @collection = @url.path.split("/", 3)
|
12
|
+
@mongodb = EventMachine::Mongo::Connection.new(@url.host).db(@db)
|
14
13
|
end # def register
|
15
14
|
|
15
|
+
public
|
16
16
|
def receive(event)
|
17
|
-
@mongodb.collection(
|
18
|
-
end # def
|
17
|
+
@mongodb.collection(@collection).insert(event.to_hash)
|
18
|
+
end # def receive
|
19
19
|
end # class LogStash::Outputs::Mongodb
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require "logstash/namespace"
|
1
2
|
require "logstash/outputs/base"
|
2
3
|
|
3
4
|
class LogStash::Outputs::Nagios < LogStash::Outputs::Base
|
4
5
|
NAGIOS_CRITICAL = 2
|
5
6
|
NAGIOS_WARN = 1
|
6
7
|
|
8
|
+
public
|
7
9
|
def initialize(url, config={}, &block)
|
8
10
|
super
|
9
11
|
|
@@ -12,12 +14,14 @@ class LogStash::Outputs::Nagios < LogStash::Outputs::Base
|
|
12
14
|
else
|
13
15
|
@cmdfile = @url.path
|
14
16
|
end
|
15
|
-
end
|
17
|
+
end # def initialize
|
16
18
|
|
19
|
+
public
|
17
20
|
def register
|
18
21
|
# nothing to do
|
19
22
|
end # def register
|
20
23
|
|
24
|
+
public
|
21
25
|
def receive(event)
|
22
26
|
if !File.exists?(@cmdfile)
|
23
27
|
@logger.warn(["Skipping nagios output; command file is missing",
|
@@ -68,5 +72,5 @@ class LogStash::Outputs::Nagios < LogStash::Outputs::Base
|
|
68
72
|
{"error" => $!, "cmdfile" => @cmdfile,
|
69
73
|
"missed_event" => event}])
|
70
74
|
end
|
71
|
-
end # def
|
75
|
+
end # def receive
|
72
76
|
end # class LogStash::Outputs::Nagios
|
@@ -1,14 +1,13 @@
|
|
1
1
|
require "logstash/outputs/base"
|
2
|
+
require "logstash/namespace"
|
2
3
|
|
3
4
|
class LogStash::Outputs::Stdout < LogStash::Outputs::Base
|
4
|
-
|
5
|
-
super
|
6
|
-
end
|
7
|
-
|
5
|
+
public
|
8
6
|
def register
|
9
7
|
# nothing to do
|
10
8
|
end # def register
|
11
9
|
|
10
|
+
public
|
12
11
|
def receive(event)
|
13
12
|
puts event
|
14
13
|
end # def event
|