gelf 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +4 -1
- data/CHANGELOG +3 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +61 -0
- data/LICENSE +1 -1
- data/README.md +62 -0
- data/Rakefile +5 -7
- data/VERSION +1 -1
- data/gelf.gemspec +29 -17
- data/lib/gelf.rb +4 -0
- data/lib/gelf/logger.rb +24 -31
- data/lib/gelf/notifier.rb +23 -4
- data/lib/gelf/ruby_sender.rb +127 -0
- data/test/test_logger.rb +53 -12
- data/test/test_notifier.rb +40 -1
- metadata +64 -38
- data/README.rdoc +0 -18
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 204c030f01e64d6980fe343a5d53144c3f31c894
|
4
|
+
data.tar.gz: 7ae8e4d33e55764f191692a396f950e87118f359
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3dfbe2d3d722a53de17c4a46edf93ffb4d17105b1f481f07bfaad598d9a29a070d1cdc5c8160e05c11bc1d373ee95c1de7997b676981826169a191f507c324e
|
7
|
+
data.tar.gz: c4d5d7fbf18e55096ae640af049c7e508a718a88c8e321b901bf7765f5da85c421ca3bb76d037534c5844cb1ae85534adda4648b3c9a601228246c7b54f21e17
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Please follow [the instructions on graylog.org](https://www.graylog.org/contributing-to-graylog/).
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.3.5)
|
5
|
+
builder (3.2.2)
|
6
|
+
faraday (0.8.8)
|
7
|
+
multipart-post (~> 1.2.0)
|
8
|
+
git (1.2.6)
|
9
|
+
github_api (0.10.1)
|
10
|
+
addressable
|
11
|
+
faraday (~> 0.8.1)
|
12
|
+
hashie (>= 1.2)
|
13
|
+
multi_json (~> 1.4)
|
14
|
+
nokogiri (~> 1.5.2)
|
15
|
+
oauth2
|
16
|
+
hashie (2.0.5)
|
17
|
+
highline (1.6.19)
|
18
|
+
httpauth (0.2.0)
|
19
|
+
jeweler (1.8.7)
|
20
|
+
builder
|
21
|
+
bundler (~> 1.0)
|
22
|
+
git (>= 1.2.5)
|
23
|
+
github_api (= 0.10.1)
|
24
|
+
highline (>= 1.6.15)
|
25
|
+
nokogiri (= 1.5.10)
|
26
|
+
rake
|
27
|
+
rdoc
|
28
|
+
json (1.8.2)
|
29
|
+
jwt (0.1.8)
|
30
|
+
multi_json (>= 1.5)
|
31
|
+
metaclass (0.0.1)
|
32
|
+
mocha (0.14.0)
|
33
|
+
metaclass (~> 0.0.1)
|
34
|
+
multi_json (1.7.9)
|
35
|
+
multi_xml (0.5.5)
|
36
|
+
multipart-post (1.2.0)
|
37
|
+
nokogiri (1.5.10)
|
38
|
+
oauth2 (0.9.2)
|
39
|
+
faraday (~> 0.8)
|
40
|
+
httpauth (~> 0.2)
|
41
|
+
jwt (~> 0.1.4)
|
42
|
+
multi_json (~> 1.0)
|
43
|
+
multi_xml (~> 0.5)
|
44
|
+
rack (~> 1.2)
|
45
|
+
power_assert (0.2.3)
|
46
|
+
rack (1.5.2)
|
47
|
+
rake (10.1.0)
|
48
|
+
rdoc (4.0.1)
|
49
|
+
json (~> 1.4)
|
50
|
+
shoulda (2.11.3)
|
51
|
+
test-unit (3.0.9)
|
52
|
+
power_assert
|
53
|
+
|
54
|
+
PLATFORMS
|
55
|
+
ruby
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
jeweler (~> 1.8.7)
|
59
|
+
mocha (~> 0.14.0)
|
60
|
+
shoulda (~> 2.11.3)
|
61
|
+
test-unit (~> 3.0.8)
|
data/LICENSE
CHANGED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
## GELF Ruby library
|
2
|
+
|
3
|
+
This is the new GELF gem written by Alexey Palazhchenko. It is based on the old gem by Lennart Koopmann and allows you to send GELF messages to Graylog2 server instances. See [http://www.graylog2.org/about/gelf](http://www.graylog2.org/about/gelf) for more information about GELF and [http://rdoc.info/github/Graylog2/gelf-rb/master/frames](http://rdoc.info/github/Graylog2/gelf-rb/master/frames) for API documentation.
|
4
|
+
|
5
|
+
Tested with Ruby 1.8.7, 1.9.x. and 2.0.x.
|
6
|
+
|
7
|
+
![](https://travis-ci.org/Graylog2/gelf-rb.png?branch=master)
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
### Gelf::Notifier
|
11
|
+
|
12
|
+
This allows you to sent arbitary messages via UDP to your Graylog2 server.
|
13
|
+
|
14
|
+
n = GELF::Notifier.new("localhost", 12201)
|
15
|
+
|
16
|
+
# Send with custom attributes and an additional parameter "foo"
|
17
|
+
n.notify!(:short_message => "foo", :full_message => "something here\n\nbacktrace?!", :_foo => "bar")
|
18
|
+
|
19
|
+
# Pass any object that responds to .to_hash
|
20
|
+
n.notify!(Exception.new)
|
21
|
+
|
22
|
+
The recommended default is to send via UDP but you can choose to send via TCP like this:
|
23
|
+
|
24
|
+
n = GELF::Notifier.new("127.0.0.1", 12201, "LAN", { :protocol => GELF::Protocol::TCP })
|
25
|
+
|
26
|
+
Note that the `LAN` or `WAN` option is ignored for TCP because no chunking happens. (Read below for more information.)
|
27
|
+
|
28
|
+
### Gelf::Logger
|
29
|
+
|
30
|
+
The Gelf::Logger is compatible with the standard Ruby Logger interface and can be used interchangeably.
|
31
|
+
Under the hood it uses Gelf::Notifier to send log messages via UDP to Graylog.
|
32
|
+
|
33
|
+
logger = GELF::Logger.new("localhost", 12201, "WAN", { :facility => "appname" })
|
34
|
+
|
35
|
+
logger.debug "foobar"
|
36
|
+
logger.info "foobar"
|
37
|
+
logger.warn "foobar"
|
38
|
+
logger.error "foobar"
|
39
|
+
logger.fatal "foobar"
|
40
|
+
|
41
|
+
logger << "foobar"
|
42
|
+
|
43
|
+
Then `WAN` or `LAN` option influences the UDP chunk size depending on if you send in your own
|
44
|
+
network (LAN) or on a longer route (i.e. through the internet) and should be set accordingly.
|
45
|
+
|
46
|
+
Since it's compatible with the Logger interface, you can also use it in your Rails application:
|
47
|
+
|
48
|
+
# config/environments/production.rb
|
49
|
+
config.logger = GELF::Logger.new("localhost", 12201, "WAN", { :facility => "appname" })
|
50
|
+
|
51
|
+
### Note on Patches/Pull Requests
|
52
|
+
|
53
|
+
* Fork the project.
|
54
|
+
* Make your feature addition or bug fix.
|
55
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
56
|
+
* Commit, do not mess with rakefile, version, or history.
|
57
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
58
|
+
* Send me a pull request. Bonus points for topic branches.
|
59
|
+
|
60
|
+
## Copyright
|
61
|
+
|
62
|
+
Copyright (c) 2010-2016 Lennart Koopmann and Alexey Palazhchenko. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -11,14 +11,13 @@ begin
|
|
11
11
|
|
12
12
|
Jeweler::Tasks.new do |gem|
|
13
13
|
gem.name = "gelf"
|
14
|
-
gem.summary = 'Library to send GELF messages to
|
15
|
-
gem.description = 'Library to send GELF messages to
|
16
|
-
gem.email = "
|
14
|
+
gem.summary = 'Library to send GELF messages to Graylog logging server.'
|
15
|
+
gem.description = 'Library to send GELF messages to Graylog logging server. Supports plain-text, GELF messages and exceptions via UDP and TCP.'
|
16
|
+
gem.email = "lennart@graylog.com"
|
17
17
|
gem.homepage = "http://github.com/Graylog2/gelf-rb"
|
18
|
-
gem.authors = ["Alexey Palazhchenko", "Lennart Koopmann"]
|
18
|
+
gem.authors = ["Alexey Palazhchenko", "Lennart Koopmann", "Zac Sprackett"]
|
19
19
|
gem.add_dependency "json"
|
20
|
-
gem.
|
21
|
-
gem.add_development_dependency "mocha"
|
20
|
+
gem.licenses = ["MIT"]
|
22
21
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
23
22
|
end
|
24
23
|
rescue LoadError => e
|
@@ -33,7 +32,6 @@ Rake::TestTask.new(:test) do |test|
|
|
33
32
|
test.verbose = true
|
34
33
|
end
|
35
34
|
|
36
|
-
task :test => :check_dependencies
|
37
35
|
task :default => :test
|
38
36
|
|
39
37
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/gelf.gemspec
CHANGED
@@ -2,26 +2,32 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: gelf 2.0.0 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
8
|
s.name = "gelf"
|
8
|
-
s.version = "
|
9
|
+
s.version = "2.0.0"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Alexey Palazhchenko", "Lennart Koopmann", "Zac Sprackett"]
|
14
|
+
s.date = "2016-02-03"
|
15
|
+
s.description = "Library to send GELF messages to Graylog logging server. Supports plain-text, GELF messages and exceptions via UDP and TCP."
|
16
|
+
s.email = "lennart@graylog.com"
|
15
17
|
s.extra_rdoc_files = [
|
18
|
+
"CHANGELOG",
|
16
19
|
"LICENSE",
|
17
|
-
"README.
|
20
|
+
"README.md"
|
18
21
|
]
|
19
22
|
s.files = [
|
20
23
|
".gemtest",
|
21
24
|
".travis.yml",
|
22
25
|
"CHANGELOG",
|
26
|
+
"CONTRIBUTING.md",
|
27
|
+
"Gemfile",
|
28
|
+
"Gemfile.lock",
|
23
29
|
"LICENSE",
|
24
|
-
"README.
|
30
|
+
"README.md",
|
25
31
|
"Rakefile",
|
26
32
|
"VERSION",
|
27
33
|
"benchmarks/notifier.rb",
|
@@ -38,26 +44,32 @@ Gem::Specification.new do |s|
|
|
38
44
|
"test/test_severity.rb"
|
39
45
|
]
|
40
46
|
s.homepage = "http://github.com/Graylog2/gelf-rb"
|
41
|
-
s.
|
42
|
-
s.rubygems_version = "
|
43
|
-
s.summary = "Library to send GELF messages to
|
47
|
+
s.licenses = ["MIT"]
|
48
|
+
s.rubygems_version = "2.4.5.1"
|
49
|
+
s.summary = "Library to send GELF messages to Graylog logging server."
|
44
50
|
|
45
51
|
if s.respond_to? :specification_version then
|
46
|
-
s.specification_version =
|
52
|
+
s.specification_version = 4
|
47
53
|
|
48
54
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_development_dependency(%q<shoulda>, ["~> 2.11.3"])
|
56
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
|
57
|
+
s.add_development_dependency(%q<mocha>, ["~> 0.14.0"])
|
58
|
+
s.add_development_dependency(%q<test-unit>, ["~> 3.0.8"])
|
49
59
|
s.add_runtime_dependency(%q<json>, [">= 0"])
|
50
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
51
|
-
s.add_development_dependency(%q<mocha>, [">= 0"])
|
52
60
|
else
|
61
|
+
s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
|
62
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
63
|
+
s.add_dependency(%q<mocha>, ["~> 0.14.0"])
|
64
|
+
s.add_dependency(%q<test-unit>, ["~> 3.0.8"])
|
53
65
|
s.add_dependency(%q<json>, [">= 0"])
|
54
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
55
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
56
66
|
end
|
57
67
|
else
|
68
|
+
s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
|
69
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
70
|
+
s.add_dependency(%q<mocha>, ["~> 0.14.0"])
|
71
|
+
s.add_dependency(%q<test-unit>, ["~> 3.0.8"])
|
58
72
|
s.add_dependency(%q<json>, [">= 0"])
|
59
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
60
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
data/lib/gelf.rb
CHANGED
data/lib/gelf/logger.rb
CHANGED
@@ -4,53 +4,47 @@ module GELF
|
|
4
4
|
|
5
5
|
attr_accessor :formatter
|
6
6
|
|
7
|
-
# Does nothing.
|
8
|
-
def close
|
9
|
-
end
|
10
|
-
|
11
7
|
# Use it like Logger#add... or better not to use at all.
|
12
|
-
def add(level,
|
13
|
-
|
8
|
+
def add(level, message = nil, progname = nil, &block)
|
9
|
+
progname ||= default_options['facility']
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
11
|
+
if message.nil?
|
12
|
+
if block_given?
|
13
|
+
message = yield
|
14
|
+
else
|
15
|
+
message = progname
|
16
|
+
progname = default_options['facility']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
message_hash = { 'facility' => progname }
|
25
21
|
|
26
22
|
if message.is_a?(Hash)
|
27
23
|
# Stringify keys.
|
28
|
-
hash = {}
|
29
24
|
message.each do |k,v|
|
30
|
-
|
25
|
+
message_hash[k.to_s] = message[k]
|
31
26
|
end
|
32
|
-
|
33
|
-
hash['facility'] = progname
|
34
27
|
else
|
35
|
-
|
28
|
+
message_hash['short_message'] = message
|
36
29
|
end
|
37
30
|
|
38
|
-
|
31
|
+
if message.is_a?(Exception)
|
32
|
+
message_hash.merge!(self.class.extract_hash_from_exception(message))
|
33
|
+
end
|
39
34
|
|
40
|
-
notify_with_level(level,
|
35
|
+
notify_with_level(level, message_hash)
|
41
36
|
end
|
42
37
|
|
43
38
|
# Redefines methods in +Notifier+.
|
44
39
|
GELF::Levels.constants.each do |const|
|
45
40
|
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
46
|
-
def #{const.downcase}(
|
47
|
-
|
48
|
-
|
49
|
-
end # end
|
41
|
+
def #{const.downcase}(progname = nil, &block) # def debug(progname = nil, &block)
|
42
|
+
add(GELF::#{const}, nil, progname, &block) # add(GELF::DEBUG, nil, progname, &block)
|
43
|
+
end # end
|
50
44
|
|
51
|
-
def #{const.downcase}?
|
52
|
-
GELF::#{const} >= level
|
53
|
-
end
|
45
|
+
def #{const.downcase}? # def debug?
|
46
|
+
GELF::#{const} >= level # GELF::DEBUG >= level
|
47
|
+
end # end
|
54
48
|
EOT
|
55
49
|
end
|
56
50
|
|
@@ -65,7 +59,6 @@ module GELF
|
|
65
59
|
# config.colorize_logging = false
|
66
60
|
class Logger < Notifier
|
67
61
|
include LoggerCompatibility
|
68
|
-
@last_chunk_id = 0
|
69
62
|
end
|
70
63
|
|
71
64
|
end
|
data/lib/gelf/notifier.rb
CHANGED
@@ -25,8 +25,13 @@ module GELF
|
|
25
25
|
self.default_options['host'] ||= Socket.gethostname
|
26
26
|
self.default_options['level'] ||= GELF::UNKNOWN
|
27
27
|
self.default_options['facility'] ||= 'gelf-rb'
|
28
|
+
self.default_options['protocol'] ||= GELF::Protocol::UDP
|
28
29
|
|
29
|
-
|
30
|
+
if self.default_options['protocol'] == GELF::Protocol::TCP
|
31
|
+
@sender = RubyTcpSender.new([[host, port]])
|
32
|
+
else
|
33
|
+
@sender = RubyUdpSender.new([[host, port]])
|
34
|
+
end
|
30
35
|
self.level_mapping = :logger
|
31
36
|
end
|
32
37
|
|
@@ -98,6 +103,11 @@ module GELF
|
|
98
103
|
@enabled = true
|
99
104
|
end
|
100
105
|
|
106
|
+
# Closes sender
|
107
|
+
def close
|
108
|
+
@sender.close
|
109
|
+
end
|
110
|
+
|
101
111
|
# Same as notify!, but rescues all exceptions (including +ArgumentError+)
|
102
112
|
# and sends them instead.
|
103
113
|
def notify(*args)
|
@@ -140,7 +150,12 @@ module GELF
|
|
140
150
|
extract_hash(*args)
|
141
151
|
@hash['level'] = message_level unless message_level.nil?
|
142
152
|
if @hash['level'] >= level
|
143
|
-
|
153
|
+
if self.default_options['protocol'] == GELF::Protocol::TCP
|
154
|
+
validate_hash
|
155
|
+
@sender.send(@hash.to_json + "\0")
|
156
|
+
else
|
157
|
+
@sender.send_datagrams(datagrams_from_hash)
|
158
|
+
end
|
144
159
|
end
|
145
160
|
end
|
146
161
|
|
@@ -208,7 +223,7 @@ module GELF
|
|
208
223
|
|
209
224
|
# Maximum total size is 8192 byte for UDP datagram. Split to chunks if bigger. (GELF v1.0 supports chunking)
|
210
225
|
if data.count > @max_chunk_size
|
211
|
-
id =
|
226
|
+
id = GELF::Notifier.last_chunk_id += 1
|
212
227
|
msg_id = Digest::MD5.digest("#{Time.now.to_f}-#{id}")[0, 8]
|
213
228
|
num, count = 0, (data.count.to_f / @max_chunk_size).ceil
|
214
229
|
data.each_slice(@max_chunk_size) do |slice|
|
@@ -222,10 +237,14 @@ module GELF
|
|
222
237
|
datagrams
|
223
238
|
end
|
224
239
|
|
225
|
-
def
|
240
|
+
def validate_hash
|
226
241
|
raise ArgumentError.new("Hash is empty.") if @hash.nil? || @hash.empty?
|
227
242
|
|
228
243
|
@hash['level'] = @level_mapping[@hash['level']]
|
244
|
+
end
|
245
|
+
|
246
|
+
def serialize_hash
|
247
|
+
validate_hash
|
229
248
|
|
230
249
|
Zlib::Deflate.deflate(@hash.to_json).bytes
|
231
250
|
end
|
data/lib/gelf/ruby_sender.rb
CHANGED
@@ -16,5 +16,132 @@ module GELF
|
|
16
16
|
@socket.send(datagram, 0, host, port)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
@socket.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class RubyTcpSocket
|
26
|
+
attr_accessor :socket
|
27
|
+
|
28
|
+
def initialize(host, port)
|
29
|
+
@host = host
|
30
|
+
@port = port
|
31
|
+
connect
|
32
|
+
end
|
33
|
+
|
34
|
+
def connected?
|
35
|
+
if not @connected
|
36
|
+
begin
|
37
|
+
if @socket.nil?
|
38
|
+
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
39
|
+
end
|
40
|
+
sockaddr = Socket.sockaddr_in(@port, @host)
|
41
|
+
@socket.connect_nonblock(sockaddr)
|
42
|
+
rescue Errno::EISCONN
|
43
|
+
@connected = true
|
44
|
+
rescue Errno::EINPROGRESS, Errno::EALREADY
|
45
|
+
@connected = false
|
46
|
+
rescue SystemCallError
|
47
|
+
@socket = nil
|
48
|
+
@connected = false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return @connected
|
52
|
+
end
|
53
|
+
|
54
|
+
def connect
|
55
|
+
@connected = false
|
56
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
57
|
+
sockaddr = Socket.sockaddr_in(@port, @host)
|
58
|
+
begin
|
59
|
+
socket.connect_nonblock(sockaddr)
|
60
|
+
rescue Errno::EISCONN
|
61
|
+
@connected = true
|
62
|
+
rescue SystemCallError
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
@socket = socket
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
|
69
|
+
def matches?(host, port)
|
70
|
+
if @host == host and @port == port
|
71
|
+
true
|
72
|
+
else
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class RubyTcpSender
|
79
|
+
attr_reader :addresses
|
80
|
+
|
81
|
+
def initialize(addresses)
|
82
|
+
@sockets = []
|
83
|
+
addresses.each do |address|
|
84
|
+
s = RubyTcpSocket.new(address[0], address[1])
|
85
|
+
@sockets.push(s)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def addresses=(addresses)
|
90
|
+
addresses.each do |address|
|
91
|
+
found = false
|
92
|
+
# handle pre existing sockets
|
93
|
+
@sockets.each do |socket|
|
94
|
+
if socket.matches?(address[0], address[1])
|
95
|
+
found = true
|
96
|
+
break
|
97
|
+
end
|
98
|
+
end
|
99
|
+
if not found
|
100
|
+
s = RubyTcpSocket.new(address[0], address[1])
|
101
|
+
@sockets.push(s)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def send(message)
|
107
|
+
while true do
|
108
|
+
sent = false
|
109
|
+
sockets = @sockets.map { |s|
|
110
|
+
if s.connected?
|
111
|
+
s.socket
|
112
|
+
end
|
113
|
+
}
|
114
|
+
sockets.compact!
|
115
|
+
next unless not sockets.empty?
|
116
|
+
begin
|
117
|
+
result = select( nil, sockets, nil, 1)
|
118
|
+
if result
|
119
|
+
writers = result[1]
|
120
|
+
sent = write_any(writers, message)
|
121
|
+
end
|
122
|
+
break if sent
|
123
|
+
rescue SystemCallError, IOError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
def write_any(writers, message)
|
130
|
+
writers.shuffle.each do |w|
|
131
|
+
begin
|
132
|
+
w.write(message)
|
133
|
+
return true
|
134
|
+
rescue Errno::EPIPE
|
135
|
+
@sockets.each do |s|
|
136
|
+
if s.socket == w
|
137
|
+
s.socket.close
|
138
|
+
s.socket = nil
|
139
|
+
s.connect
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
return false
|
145
|
+
end
|
19
146
|
end
|
20
147
|
end
|
data/test/test_logger.rb
CHANGED
@@ -21,7 +21,7 @@ class TestLogger < Test::Unit::TestCase
|
|
21
21
|
hash['short_message'] == 'Message' &&
|
22
22
|
hash['facility'] == 'gelf-rb'
|
23
23
|
end
|
24
|
-
@logger.add(GELF::INFO, 'Message')
|
24
|
+
@logger.add(GELF::INFO, nil, 'Message')
|
25
25
|
end
|
26
26
|
|
27
27
|
# logger.add(Logger::INFO, RuntimeError.new('Boom!'))
|
@@ -32,7 +32,7 @@ class TestLogger < Test::Unit::TestCase
|
|
32
32
|
hash['full_message'] =~ /^Backtrace/ &&
|
33
33
|
hash['facility'] == 'gelf-rb'
|
34
34
|
end
|
35
|
-
@logger.add(GELF::INFO, RuntimeError.new('Boom!'))
|
35
|
+
@logger.add(GELF::INFO, nil, RuntimeError.new('Boom!'))
|
36
36
|
end
|
37
37
|
|
38
38
|
# logger.add(Logger::INFO) { 'Message' }
|
@@ -42,7 +42,7 @@ class TestLogger < Test::Unit::TestCase
|
|
42
42
|
hash['short_message'] == 'Message' &&
|
43
43
|
hash['facility'] == 'gelf-rb'
|
44
44
|
end
|
45
|
-
@logger.add(GELF::INFO) { 'Message' }
|
45
|
+
@logger.add(GELF::INFO, nil, nil) { 'Message' }
|
46
46
|
end
|
47
47
|
|
48
48
|
# logger.add(Logger::INFO) { RuntimeError.new('Boom!') }
|
@@ -53,7 +53,7 @@ class TestLogger < Test::Unit::TestCase
|
|
53
53
|
hash['full_message'] =~ /^Backtrace/ &&
|
54
54
|
hash['facility'] == 'gelf-rb'
|
55
55
|
end
|
56
|
-
@logger.add(GELF::INFO) { RuntimeError.new('Boom!') }
|
56
|
+
@logger.add(GELF::INFO, nil, nil) { RuntimeError.new('Boom!') }
|
57
57
|
end
|
58
58
|
|
59
59
|
# logger.add(Logger::INFO, 'Message', 'Facility')
|
@@ -66,6 +66,27 @@ class TestLogger < Test::Unit::TestCase
|
|
66
66
|
@logger.add(GELF::INFO, 'Message', 'Facility')
|
67
67
|
end
|
68
68
|
|
69
|
+
# logger.add(Logger::INFO, 'Message', nil)
|
70
|
+
should "use facility from initialization if facility is nil" do
|
71
|
+
logger = GELF::Logger.new('localhost', 12202, 'WAN', :facility => 'foo-bar')
|
72
|
+
logger.expects(:notify_with_level!).with do |level, hash|
|
73
|
+
level == GELF::INFO &&
|
74
|
+
hash['short_message'] == 'Message' &&
|
75
|
+
hash['facility'] == 'foo-bar'
|
76
|
+
end
|
77
|
+
logger.add(GELF::INFO, 'Message', nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
# logger.add(Logger::INFO, 'Message', nil)
|
81
|
+
should "use default facility if facility is nil" do
|
82
|
+
@logger.expects(:notify_with_level!).with do |level, hash|
|
83
|
+
level == GELF::INFO &&
|
84
|
+
hash['short_message'] == 'Message' &&
|
85
|
+
hash['facility'] == 'gelf-rb'
|
86
|
+
end
|
87
|
+
@logger.add(GELF::INFO, 'Message', nil)
|
88
|
+
end
|
89
|
+
|
69
90
|
# logger.add(Logger::INFO, RuntimeError.new('Boom!'), 'Facility')
|
70
91
|
should "implement add method with level, exception and facility from parameters" do
|
71
92
|
@logger.expects(:notify_with_level!).with do |level, hash|
|
@@ -77,17 +98,17 @@ class TestLogger < Test::Unit::TestCase
|
|
77
98
|
@logger.add(GELF::INFO, RuntimeError.new('Boom!'), 'Facility')
|
78
99
|
end
|
79
100
|
|
80
|
-
# logger.add(Logger::INFO, 'Facility') { 'Message' }
|
101
|
+
# logger.add(Logger::INFO, nil, 'Facility') { 'Message' }
|
81
102
|
should "implement add method with level and facility from parameters, message from block" do
|
82
103
|
@logger.expects(:notify_with_level!).with do |level, hash|
|
83
104
|
level == GELF::INFO &&
|
84
105
|
hash['short_message'] == 'Message' &&
|
85
106
|
hash['facility'] == 'Facility'
|
86
107
|
end
|
87
|
-
@logger.add(GELF::INFO, 'Facility') { 'Message' }
|
108
|
+
@logger.add(GELF::INFO, nil, 'Facility') { 'Message' }
|
88
109
|
end
|
89
110
|
|
90
|
-
# logger.add(Logger::INFO, 'Facility') { RuntimeError.new('Boom!') }
|
111
|
+
# logger.add(Logger::INFO, nil, 'Facility') { RuntimeError.new('Boom!') }
|
91
112
|
should "implement add method with level and facility from parameters, exception from block" do
|
92
113
|
@logger.expects(:notify_with_level!).with do |level, hash|
|
93
114
|
level == GELF::INFO &&
|
@@ -95,7 +116,7 @@ class TestLogger < Test::Unit::TestCase
|
|
95
116
|
hash['full_message'] =~ /^Backtrace/ &&
|
96
117
|
hash['facility'] == 'Facility'
|
97
118
|
end
|
98
|
-
@logger.add(GELF::INFO, 'Facility') { RuntimeError.new('Boom!') }
|
119
|
+
@logger.add(GELF::INFO, nil, 'Facility') { RuntimeError.new('Boom!') }
|
99
120
|
end
|
100
121
|
|
101
122
|
|
@@ -123,7 +144,7 @@ class TestLogger < Test::Unit::TestCase
|
|
123
144
|
@logger.add(GELF::INFO, { :short_message => "Some message", :_foo => "bar", "_zomg" => "wat"})
|
124
145
|
end
|
125
146
|
|
126
|
-
# logger.add(Logger::INFO,
|
147
|
+
# logger.add(Logger::INFO, { :short_message => "Some message", :_foo => "bar", "_zomg" => "wat" }, 'somefac')
|
127
148
|
should "implement add method with level and message from hash, facility from parameters and some additional fields" do
|
128
149
|
@logger.expects(:notify_with_level!).with do |level, hash|
|
129
150
|
level == GELF::INFO &&
|
@@ -139,19 +160,31 @@ class TestLogger < Test::Unit::TestCase
|
|
139
160
|
GELF::Levels.constants.each do |const|
|
140
161
|
# logger.error "Argument #{ @foo } mismatch."
|
141
162
|
should "call add with level #{const} from method name, message from parameter" do
|
142
|
-
@logger.expects(:
|
163
|
+
@logger.expects(:notify_with_level!).with do |level, hash|
|
164
|
+
level == GELF.const_get(const) &&
|
165
|
+
hash['short_message'] == 'message' &&
|
166
|
+
hash['facility'] == 'gelf-rb'
|
167
|
+
end
|
143
168
|
@logger.__send__(const.downcase, 'message')
|
144
169
|
end
|
145
170
|
|
146
171
|
# logger.fatal { "Argument 'foo' not given." }
|
147
172
|
should "call add with level #{const} from method name, message from block" do
|
148
|
-
@logger.expects(:
|
173
|
+
@logger.expects(:notify_with_level!).with do |level, hash|
|
174
|
+
level == GELF.const_get(const) &&
|
175
|
+
hash['short_message'] == 'message' &&
|
176
|
+
hash['facility'] == 'gelf-rb'
|
177
|
+
end
|
149
178
|
@logger.__send__(const.downcase) { 'message' }
|
150
179
|
end
|
151
180
|
|
152
181
|
# logger.info('initialize') { "Initializing..." }
|
153
182
|
should "call add with level #{const} from method name, facility from parameter, message from block" do
|
154
|
-
@logger.expects(:
|
183
|
+
@logger.expects(:notify_with_level!).with do |level, hash|
|
184
|
+
level == GELF.const_get(const) &&
|
185
|
+
hash['short_message'] == 'message' &&
|
186
|
+
hash['facility'] == 'facility'
|
187
|
+
end
|
155
188
|
@logger.__send__(const.downcase, 'facility') { 'message' }
|
156
189
|
end
|
157
190
|
|
@@ -176,5 +209,13 @@ class TestLogger < Test::Unit::TestCase
|
|
176
209
|
should "have formatter attribute" do
|
177
210
|
@logger.formatter
|
178
211
|
end
|
212
|
+
|
213
|
+
|
214
|
+
context "close" do
|
215
|
+
should "close socket" do
|
216
|
+
@sender.expects(:close).once
|
217
|
+
@logger.close
|
218
|
+
end
|
219
|
+
end
|
179
220
|
end
|
180
221
|
end
|
data/test/test_notifier.rb
CHANGED
@@ -149,7 +149,16 @@ class TestNotifier < Test::Unit::TestCase
|
|
149
149
|
datagrams = @notifier.__send__(:datagrams_from_hash)
|
150
150
|
assert_equal 1, datagrams.count
|
151
151
|
assert_instance_of String, datagrams[0]
|
152
|
-
|
152
|
+
|
153
|
+
asserted = "\x78\x9c"
|
154
|
+
if RUBY_VERSION[0,1].to_i >= 2
|
155
|
+
puts "I'm a Ruby > 2.0.0. Enforcing ASCII-8BIT. (#{RUBY_VERSION}/#{RUBY_VERSION[0,1].to_i})"
|
156
|
+
# lol well yeah, Rubby.
|
157
|
+
# http://stackoverflow.com/questions/15843684/binary-string-literals-in-ruby-2-0
|
158
|
+
asserted = asserted.b
|
159
|
+
end
|
160
|
+
|
161
|
+
assert_equal asserted, datagrams[0][0..1] # zlib header
|
153
162
|
end
|
154
163
|
|
155
164
|
should "split long data" do
|
@@ -168,6 +177,29 @@ class TestNotifier < Test::Unit::TestCase
|
|
168
177
|
assert_equal datagrams.count, datagram[11].ord
|
169
178
|
end
|
170
179
|
end
|
180
|
+
|
181
|
+
should "split long data when subclassed" do
|
182
|
+
class MyNotifier < GELF::Notifier; end
|
183
|
+
|
184
|
+
@notifier = MyNotifier.new('host', 1234)
|
185
|
+
@sender = mock
|
186
|
+
@notifier.instance_variable_set('@sender', @sender)
|
187
|
+
|
188
|
+
srand(1) # for stable tests
|
189
|
+
hash = { 'version' => '1.0', 'short_message' => 'message' }
|
190
|
+
hash.merge!('something' => (0..3000).map { RANDOM_DATA[rand(RANDOM_DATA.count)] }.join) # or it will be compressed too good
|
191
|
+
@notifier.instance_variable_set('@hash', hash)
|
192
|
+
datagrams = @notifier.__send__(:datagrams_from_hash)
|
193
|
+
assert_equal 2, datagrams.count
|
194
|
+
datagrams.each_index do |i|
|
195
|
+
datagram = datagrams[i]
|
196
|
+
assert_instance_of String, datagram
|
197
|
+
assert datagram[0..1] == "\x1e\x0f" # chunked GELF magic number
|
198
|
+
# datagram[2..9] is a message id
|
199
|
+
assert_equal i, datagram[10].ord
|
200
|
+
assert_equal datagrams.count, datagram[11].ord
|
201
|
+
end
|
202
|
+
end
|
171
203
|
end
|
172
204
|
|
173
205
|
context "level threshold" do
|
@@ -194,6 +226,13 @@ class TestNotifier < Test::Unit::TestCase
|
|
194
226
|
end
|
195
227
|
end
|
196
228
|
|
229
|
+
context "close" do
|
230
|
+
should "close sender" do
|
231
|
+
@sender.expects(:close).once
|
232
|
+
@notifier.close
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
197
236
|
context "when disabled" do
|
198
237
|
setup do
|
199
238
|
@notifier.disable
|
metadata
CHANGED
@@ -1,79 +1,105 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gelf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Alexey Palazhchenko
|
9
8
|
- Lennart Koopmann
|
9
|
+
- Zac Sprackett
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-02-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: shoulda
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
18
|
requirements:
|
20
|
-
- -
|
19
|
+
- - "~>"
|
21
20
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
23
|
-
type: :
|
21
|
+
version: 2.11.3
|
22
|
+
type: :development
|
24
23
|
prerelease: false
|
25
24
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
25
|
requirements:
|
28
|
-
- -
|
26
|
+
- - "~>"
|
29
27
|
- !ruby/object:Gem::Version
|
30
|
-
version:
|
28
|
+
version: 2.11.3
|
31
29
|
- !ruby/object:Gem::Dependency
|
32
|
-
name:
|
30
|
+
name: jeweler
|
33
31
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
32
|
requirements:
|
36
|
-
- -
|
33
|
+
- - "~>"
|
37
34
|
- !ruby/object:Gem::Version
|
38
|
-
version:
|
35
|
+
version: 1.8.7
|
39
36
|
type: :development
|
40
37
|
prerelease: false
|
41
38
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
39
|
requirements:
|
44
|
-
- -
|
40
|
+
- - "~>"
|
45
41
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
42
|
+
version: 1.8.7
|
47
43
|
- !ruby/object:Gem::Dependency
|
48
44
|
name: mocha
|
49
45
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
46
|
requirements:
|
52
|
-
- -
|
47
|
+
- - "~>"
|
53
48
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
49
|
+
version: 0.14.0
|
55
50
|
type: :development
|
56
51
|
prerelease: false
|
57
52
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
53
|
requirements:
|
60
|
-
- -
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.14.0
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: test-unit
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 3.0.8
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 3.0.8
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: json
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
61
76
|
- !ruby/object:Gem::Version
|
62
77
|
version: '0'
|
63
|
-
|
64
|
-
|
65
|
-
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
description: Library to send GELF messages to Graylog logging server. Supports plain-text,
|
86
|
+
GELF messages and exceptions via UDP and TCP.
|
87
|
+
email: lennart@graylog.com
|
66
88
|
executables: []
|
67
89
|
extensions: []
|
68
90
|
extra_rdoc_files:
|
91
|
+
- CHANGELOG
|
69
92
|
- LICENSE
|
70
|
-
- README.
|
93
|
+
- README.md
|
71
94
|
files:
|
72
|
-
- .gemtest
|
73
|
-
- .travis.yml
|
95
|
+
- ".gemtest"
|
96
|
+
- ".travis.yml"
|
74
97
|
- CHANGELOG
|
98
|
+
- CONTRIBUTING.md
|
99
|
+
- Gemfile
|
100
|
+
- Gemfile.lock
|
75
101
|
- LICENSE
|
76
|
-
- README.
|
102
|
+
- README.md
|
77
103
|
- Rakefile
|
78
104
|
- VERSION
|
79
105
|
- benchmarks/notifier.rb
|
@@ -89,27 +115,27 @@ files:
|
|
89
115
|
- test/test_ruby_sender.rb
|
90
116
|
- test/test_severity.rb
|
91
117
|
homepage: http://github.com/Graylog2/gelf-rb
|
92
|
-
licenses:
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata: {}
|
93
121
|
post_install_message:
|
94
122
|
rdoc_options: []
|
95
123
|
require_paths:
|
96
124
|
- lib
|
97
125
|
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
126
|
requirements:
|
100
|
-
- -
|
127
|
+
- - ">="
|
101
128
|
- !ruby/object:Gem::Version
|
102
129
|
version: '0'
|
103
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
-
none: false
|
105
131
|
requirements:
|
106
|
-
- -
|
132
|
+
- - ">="
|
107
133
|
- !ruby/object:Gem::Version
|
108
134
|
version: '0'
|
109
135
|
requirements: []
|
110
136
|
rubyforge_project:
|
111
|
-
rubygems_version:
|
137
|
+
rubygems_version: 2.4.5.1
|
112
138
|
signing_key:
|
113
|
-
specification_version:
|
114
|
-
summary: Library to send GELF messages to
|
139
|
+
specification_version: 4
|
140
|
+
summary: Library to send GELF messages to Graylog logging server.
|
115
141
|
test_files: []
|
data/README.rdoc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
= GELF
|
2
|
-
|
3
|
-
This is the new GELF gem written by Alexey Palazhchenko. It is based on the old gem by Lennart Koopmann and allows you to send GELF messages to Graylog2 server instances. See http://www.graylog2.org/about/gelf for more information about GELF and http://rdoc.info/github/Graylog2/gelf-rb/master/frames for API documentation.
|
4
|
-
|
5
|
-
Works with Ruby 1.8.7 and 1.9.x. 1.8.6 is not supported.
|
6
|
-
|
7
|
-
== Note on Patches/Pull Requests
|
8
|
-
|
9
|
-
* Fork the project.
|
10
|
-
* Make your feature addition or bug fix.
|
11
|
-
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
12
|
-
* Commit, do not mess with rakefile, version, or history.
|
13
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
14
|
-
* Send me a pull request. Bonus points for topic branches.
|
15
|
-
|
16
|
-
== Copyright
|
17
|
-
|
18
|
-
Copyright (c) 2010-2011 Lennart Koopmann and Alexey Palazhchenko. See LICENSE for details.
|