gelf 0.9.2 → 1.0.0
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/.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