yeller_ruby 0.0.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.
- checksums.yaml +7 -0
- data/lib/yeller/client.rb +43 -0
- data/lib/yeller/configuration.rb +65 -0
- data/lib/yeller/exception_formatter.rb +44 -0
- data/lib/yeller/log_error_handler.rb +12 -0
- data/lib/yeller/rack.rb +40 -0
- data/lib/yeller/rails.rb +49 -0
- data/lib/yeller/server.rb +22 -0
- data/lib/yeller/startup_params.rb +23 -0
- data/lib/yeller/version.rb +3 -0
- data/lib/yeller.rb +27 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 69148c3deef072819ef088784bbab18ba78499ff
|
4
|
+
data.tar.gz: dcb6d17d8c297cc968ea8915f562200498af1003
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a5e13ea29a5fb9b3385f50201fe2776d8ca105b5f75ce4b0a589e176a24e339c21caa0015330bf7215e1a1ef9f4618a5ee39749efc3308cc5efd45b1aa1cd90
|
7
|
+
data.tar.gz: a63d64093d5e56edc5b773829e1024edc835fac1341bd213991c78b393323e9f65e8bb92e08cad52198b548b6b9d907f4c2cb7acd2bb1ecdd6462e69ef9bd63e
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Yeller
|
2
|
+
class Client
|
3
|
+
def initialize(servers, token, startup_params, error_handler)
|
4
|
+
@servers = servers
|
5
|
+
@last_server = rand(servers.size)
|
6
|
+
@startup_params = startup_params
|
7
|
+
@token = token
|
8
|
+
@error_handler = error_handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def report(exception, options={})
|
12
|
+
hash = ExceptionFormatter.format(exception, options)
|
13
|
+
serialized = JSON.dump(@startup_params.merge(hash))
|
14
|
+
report_with_roundtrip(serialized, 0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def report_with_roundtrip(serialized, error_count)
|
18
|
+
next_server.client.post("/#{@token}", serialized, {"Content-Type" => "application/json"})
|
19
|
+
rescue StandardError => e
|
20
|
+
if error_count <= (@servers.size * 2)
|
21
|
+
report_with_roundtrip(serialized, error_count + 1)
|
22
|
+
else
|
23
|
+
@error_handler.handle(e)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def record_deploy(revision, user, environment)
|
28
|
+
post = Net::HTTP::Post.new("/#{@token}/deploys")
|
29
|
+
post.set_form_data('revision' => revision,
|
30
|
+
'user' => user,
|
31
|
+
'environment' => environment)
|
32
|
+
next_server.client.request(post)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def next_server
|
38
|
+
index = @last_server
|
39
|
+
@last_server = (index + 1) % @servers.size
|
40
|
+
@servers[index]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative 'server'
|
2
|
+
|
3
|
+
module Yeller
|
4
|
+
class Configuration
|
5
|
+
DEFAULT_SERVERS = [
|
6
|
+
Yeller::SecureServer.new("collector1.yellerapp.com", 443),
|
7
|
+
Yeller::SecureServer.new("collector2.yellerapp.com", 443),
|
8
|
+
Yeller::SecureServer.new("collector3.yellerapp.com", 443),
|
9
|
+
Yeller::SecureServer.new("collector4.yellerapp.com", 443),
|
10
|
+
Yeller::SecureServer.new("collector5.yellerapp.com", 443),
|
11
|
+
]
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@servers = DEFAULT_SERVERS
|
15
|
+
@startup_params = {}
|
16
|
+
@error_handler = Yeller::LogErrorHandler.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_default_servers
|
20
|
+
@servers = []
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_server(host, port=443)
|
25
|
+
@servers << Yeller::SecureServer.new(host, port)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_insecure_server(host, port=80)
|
30
|
+
@servers << Yeller::Server.new(host, port)
|
31
|
+
end
|
32
|
+
|
33
|
+
def environment=(new_environment)
|
34
|
+
@startup_params[:"application-environment"] = new_environment
|
35
|
+
end
|
36
|
+
|
37
|
+
def host=(new_host)
|
38
|
+
@startup_params[:host] = new_host
|
39
|
+
end
|
40
|
+
|
41
|
+
def token=(token)
|
42
|
+
@token = token
|
43
|
+
end
|
44
|
+
|
45
|
+
def token
|
46
|
+
@token
|
47
|
+
end
|
48
|
+
|
49
|
+
def servers
|
50
|
+
@servers
|
51
|
+
end
|
52
|
+
|
53
|
+
def startup_params
|
54
|
+
@startup_params
|
55
|
+
end
|
56
|
+
|
57
|
+
def error_handler
|
58
|
+
@error_handler
|
59
|
+
end
|
60
|
+
|
61
|
+
def error_handler=(new_error_handler)
|
62
|
+
@error_handler = new_error_handler
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Yeller
|
2
|
+
class ExceptionFormatter
|
3
|
+
BACKTRACE_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
4
|
+
|
5
|
+
def self.format(exception, options={})
|
6
|
+
new(exception, options).to_hash
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :type, :options
|
10
|
+
|
11
|
+
def initialize(exception, options)
|
12
|
+
@type = exception.class.name
|
13
|
+
@message = exception.message
|
14
|
+
@backtrace = exception.backtrace
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def message
|
19
|
+
# If a message is not given, rubby will set message to the class name
|
20
|
+
@message == type ? nil : @message
|
21
|
+
end
|
22
|
+
|
23
|
+
def formatted_backtrace
|
24
|
+
return [] unless @backtrace
|
25
|
+
|
26
|
+
@backtrace.map do |line|
|
27
|
+
_, file, number, method = line.match(BACKTRACE_FORMAT).to_a
|
28
|
+
[file, number, method]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
result = {
|
34
|
+
message: message,
|
35
|
+
stacktrace: formatted_backtrace,
|
36
|
+
type: type,
|
37
|
+
:"custom-data" => options.fetch(:custom_data, {})
|
38
|
+
}
|
39
|
+
result[:url] = options[:url] if options.key?(:url)
|
40
|
+
result[:location] = options[:location] if options.key?(:location)
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/yeller/rack.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
require_relative '../yeller'
|
3
|
+
|
4
|
+
module Yeller
|
5
|
+
class Rack
|
6
|
+
def self.configure(&block)
|
7
|
+
@client = Yeller.client(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.report(exception, options={})
|
11
|
+
@client.report(exception, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(app)
|
15
|
+
@app = app
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
begin
|
20
|
+
@app.call(env)
|
21
|
+
rescue Exception => exception
|
22
|
+
Yeller::Rack.rescue_rack_exception(exception, env)
|
23
|
+
raise exception
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.rescue_rack_exception(exception, env)
|
28
|
+
::Rails.logger.info("sending exception to yeller")
|
29
|
+
request = ::Rack::Request.new(env)
|
30
|
+
Yeller::Rack.report(
|
31
|
+
exception,
|
32
|
+
:url => request.url,
|
33
|
+
:custom_data => {
|
34
|
+
:params => request.params,
|
35
|
+
:session => env.fetch('rack.session', {}),
|
36
|
+
})
|
37
|
+
::Rails.logger.info("sent exception to yeller")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/yeller/rails.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'yeller'
|
3
|
+
require 'yeller/rack'
|
4
|
+
|
5
|
+
module Yeller
|
6
|
+
class Rails
|
7
|
+
def self.configure(&block)
|
8
|
+
Yeller::Rack.configure do |config|
|
9
|
+
config.error_handler = Yeller::LogErrorHandler.new(::Rails.logger)
|
10
|
+
block.call(config)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ActionControllerCatchingHooks
|
15
|
+
def self.included(base)
|
16
|
+
base.send(:alias_method, :render_exception_without_yeller, :render_exception)
|
17
|
+
base.send(:alias_method, :render_exception, :render_exception_with_yeller)
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
def render_exception_with_yeller(env, exception)
|
22
|
+
::Rails.logger.info("yeller: caught exception")
|
23
|
+
Yeller::Rack.rescue_rack_exception(exception, env)
|
24
|
+
render_exception_without_yeller(env, exception)
|
25
|
+
rescue Exception => e
|
26
|
+
::Rails.logger.info("exception whilst handling exception: #{e} #{e.class} #{e.backtrace.join("\n")}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Railtie < ::Rails::Railtie
|
31
|
+
initializer "yeller.use_rack_middleware" do |app|
|
32
|
+
app.config.middleware.insert 0, "Yeller::Rack"
|
33
|
+
end
|
34
|
+
|
35
|
+
initializer "yeller.action_controller" do
|
36
|
+
ActiveSupport.on_load :action_controller do
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
config.after_initialize do
|
41
|
+
if defined?(::ActionDispatch::DebugExceptions)
|
42
|
+
::ActionDispatch::DebugExceptions.send(:include, Yeller::Rails::ActionControllerCatchingHooks)
|
43
|
+
elsif defined(::ActionDispatch::ShowExceptions)
|
44
|
+
::ActionDispatch::ShowExceptions.send(:include, Yeller::Rails::ActionControllerCatchingHooks)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
module Yeller
|
3
|
+
Server = Struct.new(:host, :port) do
|
4
|
+
def client
|
5
|
+
@client ||= Net::HTTP.new(host, port)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
SecureServer = Struct.new(:host, :port) do
|
10
|
+
def client
|
11
|
+
@client ||= setup_client
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup_client
|
15
|
+
http = Net::HTTP.new(host, port)
|
16
|
+
http.use_ssl = true
|
17
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
18
|
+
http.ciphers = "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2"
|
19
|
+
http
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
|
3
|
+
module Yeller
|
4
|
+
class StartupParams
|
5
|
+
PRODUCTION = 'production'.freeze
|
6
|
+
VERSION = "yeller_rubby: #{Yeller::VERSION}"
|
7
|
+
|
8
|
+
def self.defaults(options={})
|
9
|
+
{
|
10
|
+
:host => Socket.gethostname,
|
11
|
+
:"application-environment" => application_environment(options),
|
12
|
+
:"client-version" => VERSION,
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.application_environment(options)
|
17
|
+
options[:"application-environment"] ||
|
18
|
+
ENV['RAILS_ENV'] ||
|
19
|
+
ENV['RACK_ENV'] ||
|
20
|
+
PRODUCTION
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/yeller.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'yajl/json_gem'
|
3
|
+
|
4
|
+
require_relative 'yeller/client'
|
5
|
+
require_relative 'yeller/configuration'
|
6
|
+
require_relative 'yeller/exception_formatter'
|
7
|
+
require_relative 'yeller/server'
|
8
|
+
require_relative 'yeller/version'
|
9
|
+
require_relative 'yeller/startup_params'
|
10
|
+
require_relative 'yeller/log_error_handler'
|
11
|
+
|
12
|
+
module Yeller
|
13
|
+
def self.client(&block)
|
14
|
+
config = Yeller::Configuration.new
|
15
|
+
block.call(config)
|
16
|
+
build_client(config)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.build_client(config)
|
20
|
+
Yeller::Client.new(
|
21
|
+
config.servers,
|
22
|
+
config.token,
|
23
|
+
Yeller::StartupParams.defaults(config.startup_params),
|
24
|
+
config.error_handler
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yeller_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Crayford
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yajl-ruby
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.2.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.0
|
55
|
+
description: A Ruby/Rack/Rails client for yellerapp.com
|
56
|
+
email:
|
57
|
+
- tcrayford@googlemail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/yeller.rb
|
63
|
+
- lib/yeller/client.rb
|
64
|
+
- lib/yeller/configuration.rb
|
65
|
+
- lib/yeller/exception_formatter.rb
|
66
|
+
- lib/yeller/log_error_handler.rb
|
67
|
+
- lib/yeller/rack.rb
|
68
|
+
- lib/yeller/rails.rb
|
69
|
+
- lib/yeller/server.rb
|
70
|
+
- lib/yeller/startup_params.rb
|
71
|
+
- lib/yeller/version.rb
|
72
|
+
homepage: https://github.com/tcrayford/yeller_rubby
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.2.0
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: A Ruby/Rack/Rails client for yellerapp.com
|
96
|
+
test_files: []
|