gelf 0.9.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/CHANGELOG +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +20 -0
- data/Rakefile +52 -6
- data/VERSION +1 -0
- data/gelf.gemspec +45 -11
- data/lib/gelf.rb +2 -90
- data/lib/gelf/deprecations.rb +37 -0
- data/lib/gelf/notifier.rb +118 -0
- data/test/helper.rb +11 -0
- data/test/test_deprecations.rb +38 -0
- data/test/test_notifier.rb +130 -0
- metadata +69 -25
- data/Manifest +0 -3
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Lennart Koopmann
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
= GELF
|
2
|
+
|
3
|
+
This is the new GELF gem written by Aleksey Palazhchenko. It is based on the old gem by Lennart Koopmann and allows you to send GELF
|
4
|
+
messages to Graylog2 server instances. See http://www.graylog2.org/about/gelf for more information about GELF and
|
5
|
+
http://www.graylog2.org/documentation/libraries for usage examples.
|
6
|
+
|
7
|
+
Works with Ruby 1.8.7 and 1.9.2. 1.8.6 is not supported.
|
8
|
+
|
9
|
+
== Note on Patches/Pull Requests
|
10
|
+
|
11
|
+
* Fork the project.
|
12
|
+
* Make your feature addition or bug fix.
|
13
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
14
|
+
* Commit, do not mess with rakefile, version, or history.
|
15
|
+
(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)
|
16
|
+
* Send me a pull request. Bonus points for topic branches.
|
17
|
+
|
18
|
+
== Copyright
|
19
|
+
|
20
|
+
Copyright (c) 2010 Lennart Koopmann. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,10 +1,56 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
-
require 'echoe'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "gelf"
|
8
|
+
gem.summary = 'Library to send GELF messages to Graylog2 logging server'
|
9
|
+
gem.description = 'Suports plain-text, GELF messages and exceptions.'
|
10
|
+
gem.email = "lennart@socketfeed.com"
|
11
|
+
gem.homepage = "http://github.com/Graylog2/gelf-rb"
|
12
|
+
gem.authors = ["Alexey Palazhchenko", "Lennart Koopmann"]
|
13
|
+
gem.add_dependency "json"
|
14
|
+
gem.add_development_dependency "shoulda"
|
15
|
+
gem.add_development_dependency "mocha"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/test_*.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.rcov_opts << '--exclude gem'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
rescue LoadError
|
39
|
+
task :rcov do
|
40
|
+
abort "RCov is not available. In order to run rcov, you must: gem install rcov"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
task :test => :check_dependencies
|
45
|
+
|
46
|
+
task :default => :test
|
47
|
+
|
48
|
+
require 'rake/rdoctask'
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "gelf #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
10
56
|
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/gelf.gemspec
CHANGED
@@ -1,30 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{gelf}
|
5
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.0"
|
6
9
|
|
7
|
-
s.required_rubygems_version = Gem::Requirement.new(">=
|
8
|
-
s.authors = ["Lennart Koopmann"]
|
9
|
-
s.date = %q{2010-
|
10
|
-
s.description = %q{
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Alexey Palazhchenko", "Lennart Koopmann"]
|
12
|
+
s.date = %q{2010-11-12}
|
13
|
+
s.description = %q{Suports plain-text, GELF messages and exceptions.}
|
11
14
|
s.email = %q{lennart@socketfeed.com}
|
12
|
-
s.extra_rdoc_files = [
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"CHANGELOG",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"gelf.gemspec",
|
27
|
+
"lib/gelf.rb",
|
28
|
+
"lib/gelf/deprecations.rb",
|
29
|
+
"lib/gelf/notifier.rb",
|
30
|
+
"test/helper.rb",
|
31
|
+
"test/test_deprecations.rb",
|
32
|
+
"test/test_notifier.rb"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://github.com/Graylog2/gelf-rb}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
16
36
|
s.require_paths = ["lib"]
|
17
|
-
s.rubyforge_project = %q{gelf}
|
18
37
|
s.rubygems_version = %q{1.3.7}
|
19
|
-
s.summary = %q{Library to send
|
38
|
+
s.summary = %q{Library to send GELF messages to Graylog2 logging server}
|
39
|
+
s.test_files = [
|
40
|
+
"test/helper.rb",
|
41
|
+
"test/test_notifier.rb",
|
42
|
+
"test/test_deprecations.rb"
|
43
|
+
]
|
20
44
|
|
21
45
|
if s.respond_to? :specification_version then
|
22
46
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
47
|
s.specification_version = 3
|
24
48
|
|
25
49
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
51
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
52
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
26
53
|
else
|
54
|
+
s.add_dependency(%q<json>, [">= 0"])
|
55
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
56
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
27
57
|
end
|
28
58
|
else
|
59
|
+
s.add_dependency(%q<json>, [">= 0"])
|
60
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
61
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
29
62
|
end
|
30
63
|
end
|
64
|
+
|
data/lib/gelf.rb
CHANGED
@@ -1,95 +1,7 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'json'
|
3
2
|
require 'socket'
|
4
3
|
require 'zlib'
|
5
4
|
require 'digest/sha2'
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
MAX_CHUNK_SIZE = 8154
|
10
|
-
|
11
|
-
attr_accessor :short_message, :full_message, :level, :host, :line, :file
|
12
|
-
|
13
|
-
@@additional = []
|
14
|
-
|
15
|
-
def initialize hostname, port
|
16
|
-
@hostname = hostname
|
17
|
-
@port = port
|
18
|
-
end
|
19
|
-
|
20
|
-
def add_additional key, value
|
21
|
-
@@additional << { :key => key, :value => value }
|
22
|
-
end
|
23
|
-
|
24
|
-
def send
|
25
|
-
# Check if all required parameters are set.
|
26
|
-
if self.short_message == nil or self.host == nil
|
27
|
-
raise "Missing required information. Attributes short_message and host must be set."
|
28
|
-
end
|
29
|
-
|
30
|
-
data = {
|
31
|
-
"short_message" => self.short_message,
|
32
|
-
"full_message" => self.full_message,
|
33
|
-
"level" => self.level,
|
34
|
-
"host" => self.host,
|
35
|
-
"line" => self.line,
|
36
|
-
"file" => self.file
|
37
|
-
}
|
38
|
-
|
39
|
-
# Add additional fields if there are some.
|
40
|
-
if @@additional.count > 0
|
41
|
-
@@additional.each do |additional|
|
42
|
-
data[additional[:key].delete(' ')] = additional[:value]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Convert to JSON and deflate (ZLIB)
|
47
|
-
data = Zlib::Deflate.deflate(data.to_json)
|
48
|
-
|
49
|
-
# Create a socket to send the data.
|
50
|
-
sock = UDPSocket.open
|
51
|
-
|
52
|
-
# Maximum total size is 8192 byte for UDP datagram. Split to chunks if bigger. (GELFv2 supports chunking)
|
53
|
-
if data.length > MAX_CHUNK_SIZE
|
54
|
-
# Too big for one datagram. Send in chunks.
|
55
|
-
|
56
|
-
# Build a message ID.
|
57
|
-
msg_id = Time.now.to_f.to_s + rand(10000).to_s
|
58
|
-
|
59
|
-
# Split data to chunks
|
60
|
-
data_chunks = Array.new
|
61
|
-
data.chars.each_slice(MAX_CHUNK_SIZE){|slice| data_chunks << slice.join}
|
62
|
-
|
63
|
-
# Send every chunk
|
64
|
-
i = 0
|
65
|
-
data_chunks.each do |chunk|
|
66
|
-
sock.send prepend_chunk_data(chunk, msg_id, i, data_chunks.size), 0, @hostname, @port
|
67
|
-
i += 1
|
68
|
-
end
|
69
|
-
else
|
70
|
-
# Data fits in datagram without chunking. Send!
|
71
|
-
sock.send data, 0, @hostname, @port
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def prepend_chunk_data data, msg_id, sequence_number, sequence_count
|
76
|
-
raise "Data must be a string and not be empty." if data == nil or data.length == 0
|
77
|
-
raise "Message ID must be a string and not be empty." if msg_id == nil or msg_id.length == 0
|
78
|
-
raise "Sequence count must be bigger than 0." if sequence_count <= 0
|
79
|
-
raise "Sequence number must not be higher than sequence count." if sequence_number > sequence_count
|
80
|
-
|
81
|
-
# Get raw binary (packed) GELF ID
|
82
|
-
gelf_id_bin = [ 30, 15 ].pack('CC')
|
83
|
-
|
84
|
-
# Get raw binary SHA256 hash of message ID
|
85
|
-
digest = Digest::SHA256.new << msg_id
|
86
|
-
msg_id_bin = digest.digest
|
87
|
-
|
88
|
-
# Get raw binary (packed) sequence count and number
|
89
|
-
sequence_nums_bin = [ sequence_number, sequence_count ].pack('nn');
|
90
|
-
|
91
|
-
# Combine and prepend to message chunk
|
92
|
-
return gelf_id_bin + msg_id_bin + sequence_nums_bin + data
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
6
|
+
require 'gelf/notifier'
|
7
|
+
require 'gelf/deprecations'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Deprecated, do not use in new code, to be removed.
|
2
|
+
class Gelf
|
3
|
+
def deprecate(instead)
|
4
|
+
Kernel.caller.first =~ /:in `(.+)'$/
|
5
|
+
warn "Gelf##{$1} is deprecated. Use #{instead} instead."
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :notifier, :message
|
9
|
+
|
10
|
+
def initialize(hostname, port)
|
11
|
+
deprecate('GELF::Notifier.new(hostname, port) and GELF::Message.new')
|
12
|
+
@notifier = GELF::Notifier.new(hostname, port)
|
13
|
+
@message = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# bizarre, but Gelf did this...
|
17
|
+
def send
|
18
|
+
deprecate('GELF::Notifier#notify(message)')
|
19
|
+
@notifier.notify(@message)
|
20
|
+
end
|
21
|
+
|
22
|
+
[:short_message, :full_message, :level, :host, :line, :file].each do |a|
|
23
|
+
define_method a do
|
24
|
+
deprecate("GELF::Message##{a}")
|
25
|
+
@message[a]
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method "#{a}=" do |value|
|
29
|
+
deprecate("GELF::Message##{a} = value")
|
30
|
+
@message[a] = value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_additional(key, value)
|
35
|
+
@message[key] = value
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module GELF
|
2
|
+
class Notifier
|
3
|
+
@@id = 0
|
4
|
+
|
5
|
+
attr_accessor :host, :port
|
6
|
+
attr_reader :max_chunk_size
|
7
|
+
|
8
|
+
# +host+ and +port+ are host/ip and port of graylog2-server.
|
9
|
+
def initialize(host = 'localhost', port = 12201, max_size = 'WAN')
|
10
|
+
@host, @port, self.max_chunk_size = host, port, max_size
|
11
|
+
end
|
12
|
+
|
13
|
+
# +size+ may be a number of bytes, 'WAN' (1420 bytes) or 'LAN' (8154).
|
14
|
+
# Default (safe) value is 'WAN'.
|
15
|
+
def max_chunk_size=(size)
|
16
|
+
s = size.to_s.downcase
|
17
|
+
if s == 'wan'
|
18
|
+
@max_chunk_size = 1420
|
19
|
+
elsif s == 'lan'
|
20
|
+
@max_chunk_size = 8154
|
21
|
+
else
|
22
|
+
@max_chunk_size = size.to_int
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Same as notify!, but rescues all exceptions (including +ArgumentError+)
|
27
|
+
# and sends them instead.
|
28
|
+
def notify(*args)
|
29
|
+
notify!(*args)
|
30
|
+
rescue Exception => e
|
31
|
+
notify!(e)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sends message to Graylog2 server.
|
35
|
+
# +args+ can be:
|
36
|
+
# - hash-like object (any object which responds to +to_hash+, including +Hash+ instance)
|
37
|
+
# notify!(:short_message => 'All your rebase are belong to us', :user => 'AlekSi')
|
38
|
+
# - exception with optional hash-like object
|
39
|
+
# notify!(SecurityError.new('ALARM!'), :trespasser => 'AlekSi')
|
40
|
+
# - string-like object (anything which responds to +to_s+) with optional hash-like object
|
41
|
+
# notify!('Plain olde text message', :scribe => 'AlekSi')
|
42
|
+
# This method will raise +ArgumentError+ if arguments are wrong. Consider using notify instead.
|
43
|
+
def notify!(*args)
|
44
|
+
do_notify(extract_hash(*args))
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def extract_hash(object_or_exception, args = {})
|
49
|
+
primary_data = if object_or_exception.respond_to?(:to_hash)
|
50
|
+
object_or_exception.to_hash
|
51
|
+
elsif object_or_exception.is_a?(Exception)
|
52
|
+
bt = object_or_exception.backtrace || ["Backtrace is not available."]
|
53
|
+
{ 'short_message' => "#{object_or_exception.class}: #{object_or_exception.message}",
|
54
|
+
'full_message' => "Backtrace:\n" + bt.join("\n") }
|
55
|
+
else
|
56
|
+
{ 'short_message' => object_or_exception.to_s }
|
57
|
+
end
|
58
|
+
|
59
|
+
hash = args.merge(primary_data)
|
60
|
+
|
61
|
+
hash.keys.each do |key|
|
62
|
+
value, key_s = hash.delete(key), key.to_s
|
63
|
+
raise ArgumentError.new("Both #{key.inspect} and #{key_s} are present.") if hash.has_key?(key_s)
|
64
|
+
hash[key_s] = value
|
65
|
+
end
|
66
|
+
|
67
|
+
hash['host'] ||= @this_host || detect_this_host
|
68
|
+
|
69
|
+
# for compatibility with HoptoadNotifier
|
70
|
+
if hash['short_message'].to_s.empty?
|
71
|
+
if hash.has_key?('error_class') && hash.has_key?('error_message')
|
72
|
+
hash['short_message'] = "#{hash['error_class']}: #{hash['error_message']}"
|
73
|
+
hash.delete('error_class')
|
74
|
+
hash.delete('error_message')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
%w(short_message host).each do |a|
|
79
|
+
if hash[a].to_s.empty?
|
80
|
+
raise ArgumentError.new("Attributes short_message and host must be set.")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
hash
|
85
|
+
end
|
86
|
+
|
87
|
+
def do_notify(hash)
|
88
|
+
data = Zlib::Deflate.deflate(hash.to_json).bytes
|
89
|
+
sock = UDPSocket.open
|
90
|
+
datagrams = []
|
91
|
+
|
92
|
+
# Maximum total size is 8192 byte for UDP datagram. Split to chunks if bigger. (GELFv2 supports chunking)
|
93
|
+
if data.count > @max_chunk_size
|
94
|
+
@@id += 1
|
95
|
+
msg_id = Digest::SHA256.digest("#{Time.now.to_f}-#{@@id}")
|
96
|
+
i, count = 0, (data.count / 1.0 / @max_chunk_size).ceil
|
97
|
+
data.each_slice(@max_chunk_size) do |slice|
|
98
|
+
datagrams << chunk_data(slice, msg_id, i, count)
|
99
|
+
i += 1
|
100
|
+
end
|
101
|
+
else
|
102
|
+
datagrams = [data.map(&:chr).join]
|
103
|
+
end
|
104
|
+
|
105
|
+
datagrams.each { |d| sock.send(d, 0, @host, @port) }
|
106
|
+
datagrams
|
107
|
+
end
|
108
|
+
|
109
|
+
def chunk_data(data, msg_id, sequence_number, sequence_count)
|
110
|
+
# [30, 15].pack('CC') => "\036\017"
|
111
|
+
return "\036\017" + msg_id + [sequence_number, sequence_count].pack('nn') + data.map(&:chr).join
|
112
|
+
end
|
113
|
+
|
114
|
+
def detect_this_host
|
115
|
+
@this_host = Socket.gethostname
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestDeprecations < Test::Unit::TestCase
|
4
|
+
context "with Gelf object" do
|
5
|
+
setup do
|
6
|
+
@verbose, $VERBOSE = $VERBOSE, nil
|
7
|
+
@g = Gelf.new('host', 12345)
|
8
|
+
end
|
9
|
+
|
10
|
+
teardown do
|
11
|
+
$VERBOSE = @verbose
|
12
|
+
end
|
13
|
+
|
14
|
+
should "deprecate Gelf.new" do
|
15
|
+
assert_equal Gelf, @g.class
|
16
|
+
assert_equal 'host', @g.notifier.host
|
17
|
+
assert_equal 12345, @g.notifier.port
|
18
|
+
assert_equal Hash, @g.message.class
|
19
|
+
end
|
20
|
+
|
21
|
+
should "deprecate Gelf#send" do
|
22
|
+
@g.notifier.expects(:notify).with(@g.message)
|
23
|
+
@g.send
|
24
|
+
end
|
25
|
+
|
26
|
+
[:short_message, :full_message, :level, :host, :line, :file].each do |a|
|
27
|
+
should "deprecate Gelf##{a} and Gelf##{a}=" do
|
28
|
+
@g.__send__("#{a}=", 'value')
|
29
|
+
assert_equal 'value', @g.__send__(a)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
should "set add additional params" do
|
34
|
+
@g.add_additional(:key, 'value')
|
35
|
+
assert_equal 'value', @g.message[:key]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
HASH = {'short_message' => 'message', 'host' => 'localhost'}
|
4
|
+
|
5
|
+
RANDOM_DATA = ('A'..'Z').to_a
|
6
|
+
|
7
|
+
class TestNotifier < Test::Unit::TestCase
|
8
|
+
should "allow access to host, port and max_chunk_size" do
|
9
|
+
notifier = GELF::Notifier.new
|
10
|
+
assert_equal ['localhost', 12201, 1420], [notifier.host, notifier.port, notifier.max_chunk_size]
|
11
|
+
notifier.host, notifier.port, notifier.max_chunk_size = 'graylog2.org', 7777, :lan
|
12
|
+
assert_equal ['graylog2.org', 7777, 8154], [notifier.host, notifier.port, notifier.max_chunk_size]
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with notifier" do
|
16
|
+
setup do
|
17
|
+
@notifier = GELF::Notifier.new('host', 12345)
|
18
|
+
end
|
19
|
+
|
20
|
+
context "extract_hash" do
|
21
|
+
should "check number of arguments" do
|
22
|
+
assert_raise(ArgumentError) { @notifier.__send__(:extract_hash) }
|
23
|
+
assert_raise(ArgumentError) { @notifier.__send__(:extract_hash, 1, 2, 3) }
|
24
|
+
end
|
25
|
+
|
26
|
+
should "work with hash" do
|
27
|
+
assert_equal HASH, @notifier.__send__(:extract_hash, HASH)
|
28
|
+
end
|
29
|
+
|
30
|
+
should "work with any object which responds to #to_hash" do
|
31
|
+
o = Object.new
|
32
|
+
o.expects(:to_hash).returns(HASH)
|
33
|
+
assert_equal HASH, @notifier.__send__(:extract_hash, o)
|
34
|
+
end
|
35
|
+
|
36
|
+
should "work with exception with backtrace" do
|
37
|
+
e = RuntimeError.new('message')
|
38
|
+
e.set_backtrace(caller)
|
39
|
+
hash = @notifier.__send__(:extract_hash, e)
|
40
|
+
assert_equal 'RuntimeError: message', hash['short_message']
|
41
|
+
assert_match /Backtrace/, hash['full_message']
|
42
|
+
end
|
43
|
+
|
44
|
+
should "work with exception without backtrace" do
|
45
|
+
e = RuntimeError.new('message')
|
46
|
+
hash = @notifier.__send__(:extract_hash, e)
|
47
|
+
assert_match /Backtrace is not available/, hash['full_message']
|
48
|
+
end
|
49
|
+
|
50
|
+
should "work with exception and hash" do
|
51
|
+
e, h = RuntimeError.new('message'), {'param' => 1, 'short_message' => 'will be hidden by exception'}
|
52
|
+
hash = @notifier.__send__(:extract_hash, e, h)
|
53
|
+
assert_equal 'RuntimeError: message', hash['short_message']
|
54
|
+
assert_equal 1, hash['param']
|
55
|
+
end
|
56
|
+
|
57
|
+
should "work with plain text" do
|
58
|
+
assert_equal 'message', @notifier.__send__(:extract_hash, 'message')['short_message']
|
59
|
+
end
|
60
|
+
|
61
|
+
should "work with plain text and hash" do
|
62
|
+
assert_equal HASH, @notifier.__send__(:extract_hash, 'message', 'host' => 'localhost')
|
63
|
+
end
|
64
|
+
|
65
|
+
should "covert hash keys to strings" do
|
66
|
+
hash = @notifier.__send__(:extract_hash, :short_message => :message)
|
67
|
+
assert hash.has_key?('short_message')
|
68
|
+
assert !hash.has_key?(:short_message)
|
69
|
+
end
|
70
|
+
|
71
|
+
should "not overwrite keys on convert" do
|
72
|
+
assert_raise(ArgumentError) { @notifier.__send__(:extract_hash, :short_message => :message1, 'short_message' => 'message2') }
|
73
|
+
end
|
74
|
+
|
75
|
+
should "be compatible with HoptoadNotifier" do
|
76
|
+
# https://github.com/thoughtbot/hoptoad_notifier/blob/master/README.rdoc, section Going beyond exceptions
|
77
|
+
hash = @notifier.__send__(:extract_hash, :error_class => 'Class', :error_message => 'Message')
|
78
|
+
assert_equal 'Class: Message', hash['short_message']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
should "detect and cache host" do
|
83
|
+
Socket.expects(:gethostname).once.returns("localhost")
|
84
|
+
@notifier.expects(:do_notify).twice
|
85
|
+
2.times { @notifier.notify!('short_message' => 'message') }
|
86
|
+
end
|
87
|
+
|
88
|
+
context "datagrams" do
|
89
|
+
should "not split short datagram" do
|
90
|
+
UDPSocket.any_instance.expects(:send).once
|
91
|
+
@notifier.notify!(HASH)
|
92
|
+
end
|
93
|
+
|
94
|
+
should "split long datagram" do
|
95
|
+
srand(1) # for stable tests
|
96
|
+
UDPSocket.any_instance.expects(:send).twice
|
97
|
+
@notifier.notify!(HASH.merge('something' => (0..3000).map { RANDOM_DATA[rand(RANDOM_DATA.count)] }.join)) # or it will be compressed too good
|
98
|
+
end
|
99
|
+
|
100
|
+
should "send correct short datagram" do
|
101
|
+
UDPSocket.any_instance.expects(:send).with do |data, flags, host, port|
|
102
|
+
host == @notifier.host &&
|
103
|
+
port == @notifier.port &&
|
104
|
+
data[0..1] == "\170\234"
|
105
|
+
end
|
106
|
+
@notifier.notify!(HASH)
|
107
|
+
end
|
108
|
+
|
109
|
+
should "send correct long datagrams" do
|
110
|
+
UDPSocket.any_instance.expects(:send).twice.with do |data, flags, host, port|
|
111
|
+
host == @notifier.host &&
|
112
|
+
port == @notifier.port &&
|
113
|
+
data[0..1] == "\036\017"
|
114
|
+
end
|
115
|
+
srand(1) # for stable tests
|
116
|
+
@notifier.notify!(HASH.merge('something' => (0..3000).map { RANDOM_DATA[rand(RANDOM_DATA.count)] }.join)) # or it will be compressed too good
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
should "not rescue from invalid invocation of #notify!" do
|
121
|
+
assert_raise(ArgumentError) { @notifier.notify!(:no_short_message => 'too bad') }
|
122
|
+
end
|
123
|
+
|
124
|
+
should "rescue from invalid invocation of #notify" do
|
125
|
+
@notifier.expects(:notify!).with(instance_of(Hash)).raises(ArgumentError)
|
126
|
+
@notifier.expects(:notify!).with(instance_of(ArgumentError))
|
127
|
+
assert_nothing_raised { @notifier.notify(:no_short_message => 'too bad') }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,47 +1,92 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gelf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 63
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
6
|
+
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.9.2
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
12
|
+
- Alexey Palazhchenko
|
13
13
|
- Lennart Koopmann
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-11-12 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
22
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: json
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: shoulda
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
type: :development
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: mocha
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id003
|
60
|
+
description: Suports plain-text, GELF messages and exceptions.
|
23
61
|
email: lennart@socketfeed.com
|
24
62
|
executables: []
|
25
63
|
|
26
64
|
extensions: []
|
27
65
|
|
28
66
|
extra_rdoc_files:
|
29
|
-
-
|
67
|
+
- LICENSE
|
68
|
+
- README.rdoc
|
30
69
|
files:
|
31
|
-
-
|
70
|
+
- .gitignore
|
71
|
+
- CHANGELOG
|
72
|
+
- LICENSE
|
73
|
+
- README.rdoc
|
32
74
|
- Rakefile
|
33
|
-
-
|
75
|
+
- VERSION
|
34
76
|
- gelf.gemspec
|
77
|
+
- lib/gelf.rb
|
78
|
+
- lib/gelf/deprecations.rb
|
79
|
+
- lib/gelf/notifier.rb
|
80
|
+
- test/helper.rb
|
81
|
+
- test/test_deprecations.rb
|
82
|
+
- test/test_notifier.rb
|
35
83
|
has_rdoc: true
|
36
|
-
homepage: http://
|
84
|
+
homepage: http://github.com/Graylog2/gelf-rb
|
37
85
|
licenses: []
|
38
86
|
|
39
87
|
post_install_message:
|
40
88
|
rdoc_options:
|
41
|
-
- --
|
42
|
-
- --inline-source
|
43
|
-
- --title
|
44
|
-
- Gelf
|
89
|
+
- --charset=UTF-8
|
45
90
|
require_paths:
|
46
91
|
- lib
|
47
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -49,7 +94,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
94
|
requirements:
|
50
95
|
- - ">="
|
51
96
|
- !ruby/object:Gem::Version
|
52
|
-
hash: 3
|
53
97
|
segments:
|
54
98
|
- 0
|
55
99
|
version: "0"
|
@@ -58,17 +102,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
102
|
requirements:
|
59
103
|
- - ">="
|
60
104
|
- !ruby/object:Gem::Version
|
61
|
-
hash: 11
|
62
105
|
segments:
|
63
|
-
-
|
64
|
-
|
65
|
-
version: "1.2"
|
106
|
+
- 0
|
107
|
+
version: "0"
|
66
108
|
requirements: []
|
67
109
|
|
68
|
-
rubyforge_project:
|
110
|
+
rubyforge_project:
|
69
111
|
rubygems_version: 1.3.7
|
70
112
|
signing_key:
|
71
113
|
specification_version: 3
|
72
|
-
summary: Library to send
|
73
|
-
test_files:
|
74
|
-
|
114
|
+
summary: Library to send GELF messages to Graylog2 logging server
|
115
|
+
test_files:
|
116
|
+
- test/helper.rb
|
117
|
+
- test/test_notifier.rb
|
118
|
+
- test/test_deprecations.rb
|
data/Manifest
DELETED