friendlyfashion-graylog2_exceptions 1.3.1
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/README +5 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/graylog2_exceptions.gemspec +48 -0
- data/lib/graylog2_exceptions.rb +89 -0
- data/test/helper.rb +6 -0
- data/test/test_graylog2_exceptions.rb +172 -0
- metadata +79 -0
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
task :default => :test
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "graylog2_exceptions"
|
10
|
+
gem.summary = 'Graylog2 exception notifier'
|
11
|
+
gem.description = 'A Rack middleware that sends every Exception as GELF message to your Graylog2 server'
|
12
|
+
gem.email = "lennart@socketfeed.com"
|
13
|
+
gem.homepage = "http://www.graylog2.org/"
|
14
|
+
gem.authors = "Lennart Koopmann"
|
15
|
+
gem.add_dependency "gelf", "= 1.1.3"
|
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
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.3.0
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{friendlyfashion-graylog2_exceptions}
|
8
|
+
s.version = "1.3.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Laurynas Butkus", "Tomas Didziokas", "Justas Janauskas", "Edvinas Bartkus"]
|
12
|
+
s.email = ["laurynas.butkus@gmail.com", "tomas.did@gmail.com", "jjanauskas@gmail.com", "edvinas.bartkus@gmail.com"]
|
13
|
+
s.date = %q{2012-08-21}
|
14
|
+
s.description = %q{A Rack middleware that sends every Exception as GELF message to your Graylog2 server}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"graylog2_exceptions.gemspec",
|
23
|
+
"lib/graylog2_exceptions.rb",
|
24
|
+
"test/helper.rb",
|
25
|
+
"test/test_graylog2_exceptions.rb"
|
26
|
+
]
|
27
|
+
s.homepage = %q{http://www.graylog2.org/}
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
s.rubygems_version = %q{1.3.7}
|
30
|
+
s.summary = %q{Graylog2 exception notifier}
|
31
|
+
s.test_files = [
|
32
|
+
"test/helper.rb",
|
33
|
+
"test/test_graylog2_exceptions.rb"
|
34
|
+
]
|
35
|
+
|
36
|
+
if s.respond_to? :specification_version then
|
37
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
38
|
+
s.specification_version = 3
|
39
|
+
|
40
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
+
s.add_runtime_dependency(%q<gelf>, ["~> 1.3"])
|
42
|
+
else
|
43
|
+
s.add_dependency(%q<gelf>, ["~> 1.3"])
|
44
|
+
end
|
45
|
+
else
|
46
|
+
s.add_dependency(%q<gelf>, ["~> 1.3"])
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'gelf'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
class Graylog2Exceptions
|
6
|
+
attr_reader :args
|
7
|
+
|
8
|
+
def initialize(app, args = {})
|
9
|
+
standard_args = {
|
10
|
+
:hostname => "localhost",
|
11
|
+
:port => 12201,
|
12
|
+
:local_app_name => Socket::gethostname,
|
13
|
+
:facility => 'graylog2_exceptions',
|
14
|
+
:max_chunk_size => 'LAN',
|
15
|
+
:level => 3,
|
16
|
+
:host => nil,
|
17
|
+
:short_message => nil,
|
18
|
+
:full_message => nil,
|
19
|
+
:file => nil,
|
20
|
+
:line => nil
|
21
|
+
}
|
22
|
+
|
23
|
+
@args = standard_args.merge(args).reject {|k, v| v.nil? }
|
24
|
+
@extra_args = @args.reject {|k, v| standard_args.has_key?(k) }
|
25
|
+
@app = app
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(env)
|
29
|
+
# Make thread safe
|
30
|
+
dup._call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
def _call(env)
|
34
|
+
begin
|
35
|
+
# Call the app we are monitoring
|
36
|
+
response = @app.call(env)
|
37
|
+
rescue => err
|
38
|
+
# An exception has been raised. Send to Graylog2!
|
39
|
+
send_to_graylog2(err, env)
|
40
|
+
|
41
|
+
# Raise the exception again to pass back to app.
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
|
45
|
+
if env['rack.exception']
|
46
|
+
send_to_graylog2(env['rack.exception'], env)
|
47
|
+
end
|
48
|
+
|
49
|
+
response
|
50
|
+
end
|
51
|
+
|
52
|
+
def send_to_graylog2(err, env=nil)
|
53
|
+
begin
|
54
|
+
notifier = GELF::Notifier.new(@args[:hostname], @args[:port], @args[:max_chunk_size])
|
55
|
+
notifier.collect_file_and_line = false
|
56
|
+
|
57
|
+
opts = {
|
58
|
+
:short_message => err.message,
|
59
|
+
:facility => @args[:facility],
|
60
|
+
:level => @args[:level],
|
61
|
+
:host => @args[:local_app_name]
|
62
|
+
}
|
63
|
+
|
64
|
+
if err.backtrace && err.backtrace.size > 0
|
65
|
+
opts[:full_message] = "Backtrace:\n" + err.backtrace.join("\n")
|
66
|
+
opts[:file] = err.backtrace[0].split(":")[0]
|
67
|
+
opts[:line] = err.backtrace[0].split(":")[1]
|
68
|
+
end
|
69
|
+
|
70
|
+
if env and env.size > 0
|
71
|
+
opts[:full_message] ||= ""
|
72
|
+
opts[:full_message] << "\n\nEnvironment:\n"
|
73
|
+
|
74
|
+
env.each do |k, v|
|
75
|
+
begin
|
76
|
+
opts[:full_message] << "#{k}: #{v}\n"
|
77
|
+
#opts[:full_message] << "#{k}: #{v.inspect}\n"
|
78
|
+
rescue
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
notifier.notify!(opts.merge(@extra_args))
|
84
|
+
rescue Exception => i_err
|
85
|
+
puts "Graylog2 Exception logger. Could not send message: " + i_err.message
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
class TestGraylog2Exceptions < Test::Unit::TestCase
|
5
|
+
|
6
|
+
# Exceptions raised in the app should be thrown back
|
7
|
+
# to the app after handling. Simulating this by giving
|
8
|
+
# a nil app and expecting the caused exceptions.
|
9
|
+
def test_should_rethrow_exception
|
10
|
+
c = Graylog2Exceptions.new(nil, {})
|
11
|
+
assert_raise NoMethodError do
|
12
|
+
c.call nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_correct_parameters_when_custom_set
|
17
|
+
c = Graylog2Exceptions.new(nil, {:host => "localhost", :port => 1337, :max_chunk_size => 'WAN', :local_app_name => "yomama", :level => 1})
|
18
|
+
|
19
|
+
assert_equal "yomama", c.args[:local_app_name]
|
20
|
+
assert_equal "localhost", c.args[:hostname]
|
21
|
+
assert_equal 1337, c.args[:port]
|
22
|
+
assert_equal 'WAN', c.args[:max_chunk_size]
|
23
|
+
assert_equal 1, c.args[:level]
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_add_custom_attributes_to_parameters
|
27
|
+
c = Graylog2Exceptions.new(nil, {:_app => "my_awesome_app", :_rails_env => "staging"})
|
28
|
+
|
29
|
+
assert_equal "my_awesome_app", c.args[:_app]
|
30
|
+
assert_equal "staging", c.args[:_rails_env]
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_custom_attributes_dont_override_standard
|
34
|
+
ex = build_exception
|
35
|
+
c = Graylog2Exceptions.new(nil, {:line => 9999})
|
36
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
37
|
+
json = JSON.parse(sent)
|
38
|
+
|
39
|
+
assert 9999 != json["line"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_correct_parameters_when_not_custom_set
|
43
|
+
c = Graylog2Exceptions.new(nil, {})
|
44
|
+
|
45
|
+
assert_equal Socket.gethostname, c.args[:local_app_name]
|
46
|
+
assert_equal "localhost", c.args[:hostname]
|
47
|
+
assert_equal 12201, c.args[:port]
|
48
|
+
assert_equal 'LAN', c.args[:max_chunk_size]
|
49
|
+
assert_equal 3, c.args[:level]
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_send_exception_to_graylog2_without_custom_parameters
|
53
|
+
ex = build_exception
|
54
|
+
c = Graylog2Exceptions.new(nil, {})
|
55
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
56
|
+
json = JSON.parse(sent)
|
57
|
+
|
58
|
+
assert json["short_message"].include?('undefined method `klopfer!')
|
59
|
+
assert json["full_message"].include?('in `build_exception')
|
60
|
+
assert_equal 'graylog2_exceptions', json["facility"]
|
61
|
+
assert_equal 4, json["level"]
|
62
|
+
assert_equal Socket.gethostname, json["host"]
|
63
|
+
assert_equal ex.backtrace[0].split(":")[1], json["line"]
|
64
|
+
assert_equal ex.backtrace[0].split(":")[0], json["file"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_send_exception_to_graylog2_with_custom_parameters
|
68
|
+
ex = build_exception
|
69
|
+
|
70
|
+
c = Graylog2Exceptions.new(nil, {:local_app_name => "machinexx", :level => 4, :facility => 'myfacility'})
|
71
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
72
|
+
json = JSON.parse(sent)
|
73
|
+
|
74
|
+
assert json["short_message"].include?('undefined method `klopfer!')
|
75
|
+
assert json["full_message"].include?('in `build_exception')
|
76
|
+
assert_equal 'myfacility', json["facility"]
|
77
|
+
assert_equal 3, json["level"]
|
78
|
+
assert_equal "machinexx", json["host"]
|
79
|
+
assert_equal ex.backtrace[0].split(":")[1], json["line"]
|
80
|
+
assert_equal ex.backtrace[0].split(":")[0], json["file"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_send_exception_to_graylog2_with_custom_attributes
|
84
|
+
ex = build_exception
|
85
|
+
|
86
|
+
c = Graylog2Exceptions.new(nil, {
|
87
|
+
:local_app_name => "machinexx", :level => 4, :facility => 'myfacility',
|
88
|
+
:_app => "my_awesome_app", :_rails_env => "staging"
|
89
|
+
})
|
90
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
91
|
+
json = JSON.parse(sent)
|
92
|
+
|
93
|
+
assert json["short_message"].include?('undefined method `klopfer!')
|
94
|
+
assert json["full_message"].include?('in `build_exception')
|
95
|
+
assert_equal 'myfacility', json["facility"]
|
96
|
+
assert_equal 3, json["level"]
|
97
|
+
assert_equal "machinexx", json["host"]
|
98
|
+
assert_equal ex.backtrace[0].split(":")[1], json["line"]
|
99
|
+
assert_equal ex.backtrace[0].split(":")[0], json["file"]
|
100
|
+
assert_equal 'my_awesome_app', json["_app"]
|
101
|
+
assert_equal 'staging', json["_rails_env"]
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_send_backtraceless_exception_to_graylog2
|
105
|
+
ex = Exception.new("bad")
|
106
|
+
c = Graylog2Exceptions.new(nil, {})
|
107
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
108
|
+
json = JSON.parse(sent)
|
109
|
+
|
110
|
+
assert json["short_message"].include?('bad')
|
111
|
+
assert json["full_message"].nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_send_rack_environment_to_graylog2
|
115
|
+
ex = build_exception
|
116
|
+
c = Graylog2Exceptions.new(nil, {})
|
117
|
+
|
118
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex).join)
|
119
|
+
json = JSON.parse(sent)
|
120
|
+
assert json.keys.none? {|k| k =~/^_env_/ }
|
121
|
+
|
122
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex, {}).join)
|
123
|
+
json = JSON.parse(sent)
|
124
|
+
assert json.keys.none? {|k| k =~/^_env_/ }
|
125
|
+
|
126
|
+
bad = Object.new
|
127
|
+
def bad.inspect; raise "bad"; end
|
128
|
+
data = {
|
129
|
+
"nil" => nil,
|
130
|
+
"str" => "bar",
|
131
|
+
"int" => 123,
|
132
|
+
"arr" => ["a", 2],
|
133
|
+
"hash" => {"a" => 1},
|
134
|
+
"obj" => Object.new,
|
135
|
+
"bad" => bad
|
136
|
+
}
|
137
|
+
|
138
|
+
sent = Zlib::Inflate.inflate(c.send_to_graylog2(ex, data).join)
|
139
|
+
json = JSON.parse(sent)
|
140
|
+
assert_equal('nil', json["_env_nil"])
|
141
|
+
assert_equal('"bar"', json["_env_str"])
|
142
|
+
assert_equal('123', json["_env_int"])
|
143
|
+
assert_equal('["a", 2]', json["_env_arr"])
|
144
|
+
assert_equal('{"a"=>1}', json["_env_hash"])
|
145
|
+
assert_match(/#<Object:.*>/, json["_env_obj"])
|
146
|
+
assert ! json.has_key?("_env_bad")
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_invalid_port_detection
|
150
|
+
ex = build_exception
|
151
|
+
|
152
|
+
c = Graylog2Exceptions.new(nil, {:port => 0})
|
153
|
+
|
154
|
+
# send_to_graylog2 returns nil when nothing was sent
|
155
|
+
# the test is fine when the message is just not sent
|
156
|
+
# and there are no exceptions. the method informs
|
157
|
+
# the user via puts
|
158
|
+
assert_nil c.send_to_graylog2(ex)
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
# Returns a self-caused exception we can send.
|
164
|
+
def build_exception
|
165
|
+
begin
|
166
|
+
klopfer!
|
167
|
+
rescue => e
|
168
|
+
return e
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: friendlyfashion-graylog2_exceptions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Laurynas Butkus
|
9
|
+
- Tomas Didziokas
|
10
|
+
- Justas Janauskas
|
11
|
+
- Edvinas Bartkus
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2012-08-21 00:00:00.000000000 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: gelf
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '1.3'
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.3'
|
33
|
+
description: A Rack middleware that sends every Exception as GELF message to your
|
34
|
+
Graylog2 server
|
35
|
+
email:
|
36
|
+
- laurynas.butkus@gmail.com
|
37
|
+
- tomas.did@gmail.com
|
38
|
+
- jjanauskas@gmail.com
|
39
|
+
- edvinas.bartkus@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README
|
44
|
+
files:
|
45
|
+
- README
|
46
|
+
- Rakefile
|
47
|
+
- VERSION
|
48
|
+
- graylog2_exceptions.gemspec
|
49
|
+
- lib/graylog2_exceptions.rb
|
50
|
+
- test/helper.rb
|
51
|
+
- test/test_graylog2_exceptions.rb
|
52
|
+
homepage: http://www.graylog2.org/
|
53
|
+
licenses: []
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.8.24
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Graylog2 exception notifier
|
76
|
+
test_files:
|
77
|
+
- test/helper.rb
|
78
|
+
- test/test_graylog2_exceptions.rb
|
79
|
+
has_rdoc:
|