gelf 1.3.2 → 1.4.0.beta1
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/VERSION +1 -1
- data/benchmarks/incremental.rb +17 -0
- data/benchmarks/notifier.rb +19 -7
- data/gelf.gemspec +5 -4
- data/lib/gelf.rb +1 -0
- data/lib/gelf/logger.rb +1 -2
- data/lib/gelf/notifier.rb +73 -43
- data/lib/gelf/ruby_sender.rb +20 -5
- data/test/test_notifier.rb +23 -10
- metadata +16 -11
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0.beta1
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
require 'gelf'
|
7
|
+
|
8
|
+
TARGET_HOST = 'localhost'
|
9
|
+
TARGET_PORT = 5140
|
10
|
+
RANGE = 35000...36000
|
11
|
+
|
12
|
+
n = GELF::Notifier.new(TARGET_HOST, TARGET_PORT, 'WAN')
|
13
|
+
RANGE.each do |size|
|
14
|
+
n.notify!('a' * size)
|
15
|
+
puts size if (size % 100) == 0
|
16
|
+
sleep 0.01
|
17
|
+
end
|
data/benchmarks/notifier.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
|
-
puts "Loading..."
|
4
|
-
|
5
3
|
require 'benchmark'
|
4
|
+
require 'thread'
|
6
5
|
require 'rubygems'
|
7
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
8
|
require 'gelf'
|
10
9
|
|
10
|
+
Thread.abort_on_exception = true
|
11
|
+
|
12
|
+
puts "Running on #{RUBY_DESCRIPTION}"
|
11
13
|
puts "Generating random data..."
|
12
14
|
srand(1)
|
13
15
|
RANDOM_DATA = ('A'..'z').to_a
|
@@ -16,11 +18,21 @@ k3_message = (1..3*1024).map { RANDOM_DATA[rand(RANDOM_DATA.count)] }.join
|
|
16
18
|
TARGET_HOST = 'localhost'
|
17
19
|
TARGET_PORT = 12201
|
18
20
|
DEFAULT_OPTIONS = { '_host' => 'localhost' }
|
19
|
-
|
21
|
+
MESSAGES_COUNT = 5000
|
22
|
+
THREADS_COUNT = 50
|
20
23
|
|
21
24
|
SHORT_HASH = { 'short_message' => 'message' }
|
22
25
|
LONG_HASH = { 'short_message' => 'message', 'long_message' => k3_message }
|
23
26
|
|
27
|
+
def notify(n, hash)
|
28
|
+
threads = []
|
29
|
+
THREADS_COUNT.times do
|
30
|
+
threads << Thread.new do
|
31
|
+
(MESSAGES_COUNT / THREADS_COUNT).times { n.notify!(hash) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
threads.each { |t| t.join }
|
35
|
+
end
|
24
36
|
|
25
37
|
notifier_lan = GELF::Notifier.new(TARGET_HOST, TARGET_PORT, 'LAN', DEFAULT_OPTIONS)
|
26
38
|
notifier_wan = GELF::Notifier.new(TARGET_HOST, TARGET_PORT, 'WAN', DEFAULT_OPTIONS)
|
@@ -29,11 +41,11 @@ notifier_wan = GELF::Notifier.new(TARGET_HOST, TARGET_PORT, 'WAN', DEFAULT_OPTIO
|
|
29
41
|
notifier_lan.notify!(LONG_HASH)
|
30
42
|
sleep(5)
|
31
43
|
|
32
|
-
puts "Sending #{
|
44
|
+
puts "Sending #{MESSAGES_COUNT} notifications...\n"
|
33
45
|
tms = Benchmark.bm(25) do |b|
|
34
|
-
b.report('lan, short data, 1 chunk ') {
|
46
|
+
b.report('lan, short data, 1 chunk ') { notify(notifier_lan, SHORT_HASH) }
|
35
47
|
sleep(5)
|
36
|
-
b.report('lan, long data, 1 chunk ') {
|
48
|
+
b.report('lan, long data, 1 chunk ') { notify(notifier_lan, LONG_HASH) }
|
37
49
|
sleep(5)
|
38
|
-
b.report('wan, long data, 2 chunks') {
|
50
|
+
b.report('wan, long data, 2 chunks') { notify(notifier_wan, LONG_HASH) }
|
39
51
|
end
|
data/gelf.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "gelf"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.4.0.beta1"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alexey Palazhchenko", "Lennart Koopmann"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2012-01-17"
|
13
13
|
s.description = "Library to send GELF messages to Graylog2 logging server. Supports plain-text, GELF messages and exceptions."
|
14
14
|
s.email = "alexey.palazhchenko@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"README.rdoc",
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
|
+
"benchmarks/incremental.rb",
|
27
28
|
"benchmarks/notifier.rb",
|
28
29
|
"gelf.gemspec",
|
29
30
|
"lib/gelf.rb",
|
@@ -39,7 +40,7 @@ Gem::Specification.new do |s|
|
|
39
40
|
]
|
40
41
|
s.homepage = "http://github.com/Graylog2/gelf-rb"
|
41
42
|
s.require_paths = ["lib"]
|
42
|
-
s.rubygems_version = "1.8.
|
43
|
+
s.rubygems_version = "1.8.15"
|
43
44
|
s.summary = "Library to send GELF messages to Graylog2 logging server."
|
44
45
|
|
45
46
|
if s.respond_to? :specification_version then
|
data/lib/gelf.rb
CHANGED
data/lib/gelf/logger.rb
CHANGED
@@ -5,7 +5,7 @@ module GELF
|
|
5
5
|
def close
|
6
6
|
end
|
7
7
|
|
8
|
-
# Use it like Logger#add... or better not
|
8
|
+
# Use it like Logger#add... or better not use directly at all.
|
9
9
|
def add(level, *args)
|
10
10
|
raise ArgumentError.new('Wrong arguments.') unless (0..2).include?(args.count)
|
11
11
|
|
@@ -50,6 +50,5 @@ module GELF
|
|
50
50
|
# config.colorize_logging = false
|
51
51
|
class Logger < Notifier
|
52
52
|
include LoggerCompatibility
|
53
|
-
@last_chunk_id = 0
|
54
53
|
end
|
55
54
|
end
|
data/lib/gelf/notifier.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
module GELF
|
2
2
|
# Graylog2 notifier.
|
3
3
|
class Notifier
|
4
|
-
@last_chunk_id = 0
|
5
|
-
class << self
|
6
|
-
attr_accessor :last_chunk_id
|
7
|
-
end
|
8
|
-
|
9
4
|
attr_accessor :enabled, :collect_file_and_line, :rescue_network_errors
|
10
5
|
attr_reader :max_chunk_size, :level, :default_options, :level_mapping
|
11
6
|
|
@@ -137,14 +132,16 @@ module GELF
|
|
137
132
|
|
138
133
|
def notify_with_level!(message_level, *args)
|
139
134
|
return unless @enabled
|
140
|
-
extract_hash(*args)
|
141
|
-
|
142
|
-
if
|
143
|
-
@sender.send_datagrams(datagrams_from_hash)
|
135
|
+
hash = extract_hash(*args)
|
136
|
+
hash['level'] = message_level unless message_level.nil?
|
137
|
+
if hash['level'] >= level
|
138
|
+
@sender.send_datagrams(datagrams_from_hash(hash))
|
144
139
|
end
|
145
140
|
end
|
146
141
|
|
147
142
|
def extract_hash(object = nil, args = {})
|
143
|
+
args = self.class.stringify_keys(args)
|
144
|
+
|
148
145
|
primary_data = if object.respond_to?(:to_hash)
|
149
146
|
object.to_hash
|
150
147
|
elsif object.is_a?(Exception)
|
@@ -155,61 +152,94 @@ module GELF
|
|
155
152
|
{ 'short_message' => object.to_s }
|
156
153
|
end
|
157
154
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
155
|
+
hash = self.class.stringify_keys(primary_data)
|
156
|
+
hash = default_options.merge(args.merge(hash))
|
157
|
+
hash = convert_airbrake_keys_to_graylog2(hash)
|
158
|
+
hash = set_file_and_line(hash)
|
159
|
+
hash = set_timestamp(hash)
|
160
|
+
check_presence_of_mandatory_attributes(hash)
|
161
|
+
hash
|
164
162
|
end
|
165
163
|
|
164
|
+
CALLER_REGEXP = /^(.*):(\d+).*/
|
165
|
+
|
166
166
|
def self.extract_hash_from_exception(exception)
|
167
|
-
|
168
|
-
|
167
|
+
error_class = exception.class.name
|
168
|
+
error_message = exception.message
|
169
|
+
|
170
|
+
# always collect file and line there (ignore @collect_file_and_line)
|
171
|
+
# since we already know them, no need to call `caller`
|
172
|
+
file, line = nil, nil
|
173
|
+
bt = exception.backtrace
|
174
|
+
if bt
|
175
|
+
match = CALLER_REGEXP.match(bt[0])
|
176
|
+
if match
|
177
|
+
file = match[1]
|
178
|
+
line = match[2].to_i
|
179
|
+
end
|
180
|
+
else
|
181
|
+
bt = ["Backtrace is not available."]
|
182
|
+
end
|
183
|
+
|
184
|
+
{ 'short_message' => "#{error_class}: #{error_message}", 'full_message' => "Backtrace:\n" + bt.join("\n"),
|
185
|
+
'error_class' => error_class, 'error_message' => error_message,
|
186
|
+
'file' => file, 'line' => line }
|
169
187
|
end
|
170
188
|
|
171
|
-
# Converts
|
172
|
-
def
|
173
|
-
if
|
174
|
-
if
|
175
|
-
|
189
|
+
# Converts Airbrake-specific keys in +hash+ to Graylog2-specific.
|
190
|
+
def convert_airbrake_keys_to_graylog2(hash)
|
191
|
+
if hash['short_message'].to_s.empty?
|
192
|
+
if hash.has_key?('error_class') && hash.has_key?('error_message')
|
193
|
+
hash['short_message'] = hash['error_class'] + ': ' + hash['error_message']
|
176
194
|
end
|
177
195
|
end
|
196
|
+
hash
|
178
197
|
end
|
179
198
|
|
180
|
-
CALLER_REGEXP = /^(.*):(\d+).*/
|
181
199
|
LIB_GELF_PATTERN = File.join('lib', 'gelf')
|
182
200
|
|
183
|
-
def set_file_and_line
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
201
|
+
def set_file_and_line(hash)
|
202
|
+
return hash unless hash['file'].nil? || hash['line'].nil?
|
203
|
+
|
204
|
+
if @collect_file_and_line
|
205
|
+
stack = caller
|
206
|
+
begin
|
207
|
+
frame = stack.shift
|
208
|
+
end while frame.include?(LIB_GELF_PATTERN)
|
209
|
+
|
210
|
+
match = CALLER_REGEXP.match(frame)
|
211
|
+
if match
|
212
|
+
hash['file'] = match[1]
|
213
|
+
hash['line'] = match[2].to_i
|
214
|
+
else
|
215
|
+
hash['file'] = 'unknown'
|
216
|
+
hash['line'] = -1
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
hash
|
191
221
|
end
|
192
222
|
|
193
|
-
def set_timestamp
|
194
|
-
|
223
|
+
def set_timestamp(hash)
|
224
|
+
hash['timestamp'] ||= Time.now.utc.to_f
|
225
|
+
hash
|
195
226
|
end
|
196
227
|
|
197
|
-
def check_presence_of_mandatory_attributes
|
228
|
+
def check_presence_of_mandatory_attributes(hash)
|
198
229
|
%w(version short_message host).each do |attribute|
|
199
|
-
if
|
230
|
+
if hash[attribute].to_s.empty?
|
200
231
|
raise ArgumentError.new("#{attribute} is missing. Options version, short_message and host must be set.")
|
201
232
|
end
|
202
233
|
end
|
203
234
|
end
|
204
235
|
|
205
|
-
def datagrams_from_hash
|
206
|
-
data = serialize_hash
|
236
|
+
def datagrams_from_hash(hash)
|
237
|
+
data = serialize_hash(hash)
|
207
238
|
datagrams = []
|
208
239
|
|
209
240
|
# Maximum total size is 8192 byte for UDP datagram. Split to chunks if bigger. (GELF v1.0 supports chunking)
|
210
241
|
if data.count > @max_chunk_size
|
211
|
-
|
212
|
-
msg_id = Digest::MD5.digest("#{Time.now.to_f}-#{id}")[0, 8]
|
242
|
+
msg_id = Digest::MD5.digest("#{Time.now.to_f}-#{hash.object_id}")[0, 8]
|
213
243
|
num, count = 0, (data.count.to_f / @max_chunk_size).ceil
|
214
244
|
data.each_slice(@max_chunk_size) do |slice|
|
215
245
|
datagrams << "\x1e\x0f" + msg_id + [num, count, *slice].pack('C*')
|
@@ -222,12 +252,12 @@ module GELF
|
|
222
252
|
datagrams
|
223
253
|
end
|
224
254
|
|
225
|
-
def serialize_hash
|
226
|
-
raise ArgumentError.new("Hash is empty.") if
|
255
|
+
def serialize_hash(hash)
|
256
|
+
raise ArgumentError.new("Hash is empty.") if hash.nil? || hash.empty?
|
227
257
|
|
228
|
-
|
258
|
+
hash['level'] = @level_mapping[hash['level']]
|
229
259
|
|
230
|
-
Zlib::Deflate.deflate(
|
260
|
+
Zlib::Deflate.deflate(hash.to_json).bytes
|
231
261
|
end
|
232
262
|
|
233
263
|
def self.stringify_keys(hash)
|
data/lib/gelf/ruby_sender.rb
CHANGED
@@ -1,17 +1,32 @@
|
|
1
1
|
module GELF
|
2
2
|
# Plain Ruby UDP sender.
|
3
3
|
class RubyUdpSender
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(addresses)
|
7
|
-
@addresses = addresses
|
8
|
-
@i = 0
|
4
|
+
def initialize(addrs)
|
5
|
+
@mutex = ::Mutex.new
|
9
6
|
@socket = UDPSocket.open
|
7
|
+
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 65507) # 65535 - 20 (ip header) - 8 (udp header)
|
8
|
+
self.addresses = addrs
|
9
|
+
end
|
10
|
+
|
11
|
+
def addresses
|
12
|
+
@mutex.synchronize do
|
13
|
+
@i = 0
|
14
|
+
@addresses
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def addresses=(addrs)
|
19
|
+
@mutex.synchronize do
|
20
|
+
@i = 0
|
21
|
+
@addresses = addrs
|
22
|
+
end
|
10
23
|
end
|
11
24
|
|
12
25
|
def send_datagrams(datagrams)
|
26
|
+
# not thread-safe, but we don't care if round-robin algo fails sometimes
|
13
27
|
host, port = @addresses[@i]
|
14
28
|
@i = (@i + 1) % @addresses.length
|
29
|
+
|
15
30
|
datagrams.each do |datagram|
|
16
31
|
@socket.send(datagram, 0, host, port)
|
17
32
|
end
|
data/test/test_notifier.rb
CHANGED
@@ -52,20 +52,30 @@ class TestNotifier < Test::Unit::TestCase
|
|
52
52
|
e.set_backtrace(caller)
|
53
53
|
hash = @notifier.__send__(:extract_hash, e)
|
54
54
|
assert_equal 'RuntimeError: message', hash['short_message']
|
55
|
+
assert_equal 'RuntimeError', hash['error_class']
|
56
|
+
assert_equal 'message', hash['error_message']
|
57
|
+
assert_match /shoulda/, hash['file']
|
58
|
+
assert hash['line'] > 300 # 382 in shoulda 2.11.3
|
55
59
|
assert_match /Backtrace/, hash['full_message']
|
56
60
|
assert_equal GELF::ERROR, hash['level']
|
57
61
|
end
|
58
62
|
|
59
63
|
should "work with exception without backtrace" do
|
60
64
|
e = RuntimeError.new('message')
|
61
|
-
hash = @notifier.__send__(:extract_hash, e)
|
65
|
+
hash, line = @notifier.__send__(:extract_hash, e), __LINE__
|
66
|
+
assert_equal __FILE__, hash['file']
|
67
|
+
assert_equal line, hash['line']
|
62
68
|
assert_match /Backtrace is not available/, hash['full_message']
|
63
69
|
end
|
64
70
|
|
65
71
|
should "work with exception and hash" do
|
66
72
|
e, h = RuntimeError.new('message'), {'param' => 1, 'level' => GELF::FATAL, 'short_message' => 'will be hidden by exception'}
|
67
|
-
hash = @notifier.__send__(:extract_hash, e, h)
|
73
|
+
hash, line = @notifier.__send__(:extract_hash, e, h), __LINE__
|
68
74
|
assert_equal 'RuntimeError: message', hash['short_message']
|
75
|
+
assert_equal 'RuntimeError', hash['error_class']
|
76
|
+
assert_equal 'message', hash['error_message']
|
77
|
+
assert_equal __FILE__, hash['file']
|
78
|
+
assert_equal line, hash['line']
|
69
79
|
assert_equal GELF::FATAL, hash['level']
|
70
80
|
assert_equal 1, hash['param']
|
71
81
|
end
|
@@ -80,6 +90,10 @@ class TestNotifier < Test::Unit::TestCase
|
|
80
90
|
hash = @notifier.__send__(:extract_hash, 'message', 'level' => GELF::WARN)
|
81
91
|
assert_equal 'message', hash['short_message']
|
82
92
|
assert_equal GELF::WARN, hash['level']
|
93
|
+
|
94
|
+
hash = @notifier.__send__(:extract_hash, 'message', :level => GELF::WARN)
|
95
|
+
assert_equal 'message', hash['short_message']
|
96
|
+
assert_equal GELF::WARN, hash['level']
|
83
97
|
end
|
84
98
|
|
85
99
|
should "covert hash keys to strings" do
|
@@ -99,10 +113,12 @@ class TestNotifier < Test::Unit::TestCase
|
|
99
113
|
assert_equal 'message', hash['short_message']
|
100
114
|
end
|
101
115
|
|
102
|
-
should "be compatible with
|
103
|
-
# https://github.com/
|
116
|
+
should "be compatible with Airbrake" do
|
117
|
+
# https://github.com/airbrake/airbrake/blob/master/README.md, section Going beyond exceptions
|
104
118
|
hash = @notifier.__send__(:extract_hash, :error_class => 'Class', :error_message => 'Message')
|
105
119
|
assert_equal 'Class: Message', hash['short_message']
|
120
|
+
assert_equal 'Class', hash['error_class']
|
121
|
+
assert_equal 'Message', hash['error_message']
|
106
122
|
end
|
107
123
|
|
108
124
|
should "set file and line" do
|
@@ -129,8 +145,7 @@ class TestNotifier < Test::Unit::TestCase
|
|
129
145
|
context "serialize_hash" do
|
130
146
|
setup do
|
131
147
|
@notifier.level_mapping = :direct
|
132
|
-
@notifier.
|
133
|
-
@data = @notifier.__send__(:serialize_hash)
|
148
|
+
@data = @notifier.__send__(:serialize_hash, { 'level' => GELF::WARN, 'field' => 'value' })
|
134
149
|
assert @data.respond_to?(:each) # Enumerable::Enumerator in 1.8, ::Enumerator in 1.9, so...
|
135
150
|
@deserialized_hash = JSON.parse(Zlib::Inflate.inflate(@data.to_a.pack('C*')))
|
136
151
|
assert_instance_of Hash, @deserialized_hash
|
@@ -145,8 +160,7 @@ class TestNotifier < Test::Unit::TestCase
|
|
145
160
|
|
146
161
|
context "datagrams_from_hash" do
|
147
162
|
should "not split short data" do
|
148
|
-
@notifier.
|
149
|
-
datagrams = @notifier.__send__(:datagrams_from_hash)
|
163
|
+
datagrams = @notifier.__send__(:datagrams_from_hash, { 'version' => '1.0', 'short_message' => 'message' })
|
150
164
|
assert_equal 1, datagrams.count
|
151
165
|
assert_instance_of String, datagrams[0]
|
152
166
|
assert_equal "\x78\x9c", datagrams[0][0..1] # zlib header
|
@@ -156,8 +170,7 @@ class TestNotifier < Test::Unit::TestCase
|
|
156
170
|
srand(1) # for stable tests
|
157
171
|
hash = { 'version' => '1.0', 'short_message' => 'message' }
|
158
172
|
hash.merge!('something' => (0..3000).map { RANDOM_DATA[rand(RANDOM_DATA.count)] }.join) # or it will be compressed too good
|
159
|
-
@notifier.
|
160
|
-
datagrams = @notifier.__send__(:datagrams_from_hash)
|
173
|
+
datagrams = @notifier.__send__(:datagrams_from_hash, hash)
|
161
174
|
assert_equal 2, datagrams.count
|
162
175
|
datagrams.each_index do |i|
|
163
176
|
datagram = datagrams[i]
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gelf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: -3453770742
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
- beta
|
11
|
+
- 1
|
12
|
+
version: 1.4.0.beta1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Alexey Palazhchenko
|
@@ -16,7 +18,7 @@ autorequire:
|
|
16
18
|
bindir: bin
|
17
19
|
cert_chain: []
|
18
20
|
|
19
|
-
date:
|
21
|
+
date: 2012-01-17 00:00:00 Z
|
20
22
|
dependencies:
|
21
23
|
- !ruby/object:Gem::Dependency
|
22
24
|
name: json
|
@@ -77,6 +79,7 @@ files:
|
|
77
79
|
- README.rdoc
|
78
80
|
- Rakefile
|
79
81
|
- VERSION
|
82
|
+
- benchmarks/incremental.rb
|
80
83
|
- benchmarks/notifier.rb
|
81
84
|
- gelf.gemspec
|
82
85
|
- lib/gelf.rb
|
@@ -109,16 +112,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
113
|
none: false
|
111
114
|
requirements:
|
112
|
-
- - "
|
115
|
+
- - ">"
|
113
116
|
- !ruby/object:Gem::Version
|
114
|
-
hash:
|
117
|
+
hash: 25
|
115
118
|
segments:
|
116
|
-
-
|
117
|
-
|
119
|
+
- 1
|
120
|
+
- 3
|
121
|
+
- 1
|
122
|
+
version: 1.3.1
|
118
123
|
requirements: []
|
119
124
|
|
120
125
|
rubyforge_project:
|
121
|
-
rubygems_version: 1.8.
|
126
|
+
rubygems_version: 1.8.15
|
122
127
|
signing_key:
|
123
128
|
specification_version: 3
|
124
129
|
summary: Library to send GELF messages to Graylog2 logging server.
|