/
sender.rb
128 lines (110 loc) · 3.65 KB
/
sender.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
module Airbrake
# Sends out the notice to Airbrake
class Sender
NOTICES_URI = '/notifier_api/v2/notices/'.freeze
HTTP_ERRORS = [Timeout::Error,
Errno::EINVAL,
Errno::ECONNRESET,
EOFError,
Net::HTTPBadResponse,
Net::HTTPHeaderSyntaxError,
Net::ProtocolError,
Errno::ECONNREFUSED].freeze
def initialize(options = {})
[ :proxy_host,
:proxy_port,
:proxy_user,
:proxy_pass,
:protocol,
:host,
:port,
:secure,
:use_system_ssl_cert_chain,
:http_open_timeout,
:http_read_timeout
].each do |option|
instance_variable_set("@#{option}", options[option])
end
end
# Sends the notice data off to Airbrake for processing.
#
# @param [Notice] notice The notice to be sent off
def send_to_airbrake(notice)
data = notice.to_xml
http = setup_http_connection
response = begin
http.post(url.path, data, HEADERS)
rescue *HTTP_ERRORS => e
log :level => :error,
:message => "Unable to contact the Airbrake server. HTTP Error=#{e}"
nil
end
case response
when Net::HTTPSuccess then
log :level => :info,
:message => "Success: #{response.class}",
:response => response
else
log :level => :error,
:message => "Failure: #{response.class}",
:response => response,
:notice => notice
end
if response && response.respond_to?(:body)
error_id = response.body.match(%r{<id[^>]*>(.*?)</id>})
error_id[1] if error_id
end
rescue => e
log :level => :error,
:message => "[Airbrake::Sender#send_to_airbrake] Cannot send notification. Error: #{e.class}" +
" - #{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}"
nil
end
attr_reader :proxy_host,
:proxy_port,
:proxy_user,
:proxy_pass,
:protocol,
:host,
:port,
:secure,
:use_system_ssl_cert_chain,
:http_open_timeout,
:http_read_timeout
alias_method :secure?, :secure
alias_method :use_system_ssl_cert_chain?, :use_system_ssl_cert_chain
private
def url
URI.parse("#{protocol}://#{host}:#{port}").merge(NOTICES_URI)
end
def log(opts = {})
opts[:logger].send opts[:level], LOG_PREFIX + opts[:message] if opts[:logger]
Airbrake.report_environment_info
Airbrake.report_response_body(opts[:response].body) if opts[:response] && opts[:response].respond_to?(:body)
Airbrake.report_notice(opts[:notice]) if opts[:notice]
end
def logger
Airbrake.logger
end
def setup_http_connection
http =
Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass).
new(url.host, url.port)
http.read_timeout = http_read_timeout
http.open_timeout = http_open_timeout
if secure?
http.use_ssl = true
http.ca_file = Airbrake.configuration.ca_bundle_path
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
else
http.use_ssl = false
end
http
rescue => e
log :level => :error,
:message => "[Airbrake::Sender#setup_http_connection] Failure initializing the HTTP connection.\n" +
"Error: #{e.class} - #{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}"
raise e
end
end
end