appsignal 2.1.2 → 2.2.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +14 -0
- data/.rubocop_todo.yml +16 -171
- data/.travis.yml +14 -1
- data/.yardopts +8 -0
- data/CHANGELOG.md +21 -3
- data/README.md +20 -2
- data/Rakefile +60 -62
- data/appsignal.gemspec +24 -23
- data/ext/agent.yml +11 -11
- data/ext/appsignal_extension.c +43 -12
- data/ext/extconf.rb +9 -9
- data/gemfiles/padrino.gemfile +1 -1
- data/lib/appsignal.rb +403 -26
- data/lib/appsignal/auth_check.rb +28 -1
- data/lib/appsignal/cli.rb +1 -0
- data/lib/appsignal/cli/demo.rb +40 -0
- data/lib/appsignal/cli/diagnose.rb +345 -89
- data/lib/appsignal/cli/helpers.rb +9 -4
- data/lib/appsignal/cli/install.rb +6 -6
- data/lib/appsignal/cli/notify_of_deploy.rb +58 -0
- data/lib/appsignal/config.rb +40 -38
- data/lib/appsignal/demo.rb +20 -0
- data/lib/appsignal/event_formatter.rb +4 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +1 -0
- data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +1 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +1 -0
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +1 -0
- data/lib/appsignal/event_formatter/faraday/request_formatter.rb +1 -0
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +2 -1
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +1 -0
- data/lib/appsignal/extension.rb +1 -0
- data/lib/appsignal/garbage_collection_profiler.rb +20 -19
- data/lib/appsignal/hooks.rb +1 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +1 -0
- data/lib/appsignal/hooks/celluloid.rb +1 -0
- data/lib/appsignal/hooks/data_mapper.rb +1 -0
- data/lib/appsignal/hooks/delayed_job.rb +1 -0
- data/lib/appsignal/hooks/mongo_ruby_driver.rb +1 -0
- data/lib/appsignal/hooks/net_http.rb +1 -0
- data/lib/appsignal/hooks/passenger.rb +1 -0
- data/lib/appsignal/hooks/puma.rb +1 -0
- data/lib/appsignal/hooks/rake.rb +1 -0
- data/lib/appsignal/hooks/redis.rb +1 -0
- data/lib/appsignal/hooks/sequel.rb +1 -0
- data/lib/appsignal/hooks/shoryuken.rb +1 -0
- data/lib/appsignal/hooks/sidekiq.rb +1 -0
- data/lib/appsignal/hooks/unicorn.rb +1 -0
- data/lib/appsignal/hooks/webmachine.rb +1 -0
- data/lib/appsignal/integrations/capistrano/appsignal.cap +4 -4
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +2 -0
- data/lib/appsignal/integrations/data_mapper.rb +1 -1
- data/lib/appsignal/integrations/delayed_job_plugin.rb +1 -0
- data/lib/appsignal/integrations/grape.rb +3 -1
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +1 -0
- data/lib/appsignal/integrations/padrino.rb +36 -21
- data/lib/appsignal/integrations/railtie.rb +2 -2
- data/lib/appsignal/integrations/resque.rb +1 -0
- data/lib/appsignal/integrations/resque_active_job.rb +1 -0
- data/lib/appsignal/integrations/webmachine.rb +27 -24
- data/lib/appsignal/js_exception_transaction.rb +8 -8
- data/lib/appsignal/marker.rb +41 -4
- data/lib/appsignal/minutely.rb +1 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +3 -2
- data/lib/appsignal/rack/js_exception_catcher.rb +55 -15
- data/lib/appsignal/rack/rails_instrumentation.rb +2 -1
- data/lib/appsignal/rack/sinatra_instrumentation.rb +4 -2
- data/lib/appsignal/rack/streaming_listener.rb +4 -2
- data/lib/appsignal/system.rb +5 -31
- data/lib/appsignal/transaction.rb +71 -6
- data/lib/appsignal/transmitter.rb +24 -13
- data/lib/appsignal/utils.rb +18 -11
- data/lib/appsignal/utils/params_sanitizer.rb +2 -1
- data/lib/appsignal/utils/query_params_sanitizer.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/resources/appsignal.yml.erb +1 -1
- data/spec/lib/appsignal/auth_check_spec.rb +64 -22
- data/spec/lib/appsignal/cli/diagnose_spec.rb +539 -81
- data/spec/lib/appsignal/cli/helpers_spec.rb +74 -2
- data/spec/lib/appsignal/cli/install_spec.rb +3 -3
- data/spec/lib/appsignal/config_spec.rb +38 -72
- data/spec/lib/appsignal/demo_spec.rb +2 -2
- data/spec/lib/appsignal/event_formatter_spec.rb +2 -2
- data/spec/lib/appsignal/extension_spec.rb +4 -0
- data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +18 -21
- data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +1 -1
- data/spec/lib/appsignal/hooks/redis_spec.rb +34 -44
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +2 -2
- data/spec/lib/appsignal/integrations/grape_spec.rb +6 -6
- data/spec/lib/appsignal/integrations/padrino_spec.rb +241 -122
- data/spec/lib/appsignal/integrations/railtie_spec.rb +34 -16
- data/spec/lib/appsignal/integrations/resque_spec.rb +1 -1
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +38 -10
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +2 -2
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +7 -6
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +95 -58
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +9 -6
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +11 -10
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +20 -13
- data/spec/lib/appsignal/system_spec.rb +2 -32
- data/spec/lib/appsignal/transaction_spec.rb +48 -7
- data/spec/lib/appsignal/transmitter_spec.rb +52 -33
- data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +3 -1
- data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +3 -3
- data/spec/lib/appsignal/utils_spec.rb +49 -6
- data/spec/lib/appsignal_spec.rb +60 -5
- data/spec/spec_helper.rb +4 -3
- data/spec/support/helpers/api_request_helper.rb +1 -4
- data/spec/support/helpers/dependency_helper.rb +4 -0
- data/spec/support/helpers/system_helpers.rb +1 -17
- data/spec/support/helpers/time_helpers.rb +1 -1
- metadata +19 -8
- data/spec/lib/appsignal/system/container_spec.rb +0 -67
- data/spec/lib/appsignal/utils/gzip_spec.rb +0 -10
data/lib/appsignal/minutely.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "rack"
|
2
2
|
|
3
3
|
module Appsignal
|
4
|
+
# @api private
|
4
5
|
module Rack
|
5
6
|
class GenericInstrumentation
|
6
7
|
def initialize(app, options = {})
|
@@ -33,9 +34,9 @@ module Appsignal
|
|
33
34
|
raise error
|
34
35
|
ensure
|
35
36
|
if env["appsignal.route"]
|
36
|
-
transaction.
|
37
|
+
transaction.set_action_if_nil(env["appsignal.route"])
|
37
38
|
else
|
38
|
-
transaction.
|
39
|
+
transaction.set_action_if_nil("unknown")
|
39
40
|
end
|
40
41
|
transaction.set_metadata("path", request.path)
|
41
42
|
transaction.set_metadata("method", request.request_method)
|
@@ -1,29 +1,69 @@
|
|
1
1
|
module Appsignal
|
2
|
+
# @api private
|
2
3
|
module Rack
|
4
|
+
# JavaScript error catching middleware.
|
5
|
+
#
|
6
|
+
# Listens to the endpoint specified in the `frontend_error_catching_path`
|
7
|
+
# configuration option.
|
8
|
+
#
|
9
|
+
# This is automatically included middleware in Rails apps if the
|
10
|
+
# `frontend_error_catching_path` configuration option is active.
|
11
|
+
#
|
12
|
+
# If AppSignal is not active in the current environment, but does have
|
13
|
+
# JavaScript error catching turned on, we assume that a JavaScript script
|
14
|
+
# still sends errors to this endpoint. When AppSignal is not active in this
|
15
|
+
# scenario this middleware still listens to the endpoint, but won't record
|
16
|
+
# the error. It will return HTTP status code 202.
|
17
|
+
#
|
18
|
+
# @example with a Sinatra app
|
19
|
+
# Sinatra::Application.use(Appsignal::Rack::JSExceptionCatcher)
|
20
|
+
#
|
21
|
+
# @see http://docs.appsignal.com/front-end/error-handling.html
|
22
|
+
# @api private
|
3
23
|
class JSExceptionCatcher
|
4
|
-
def initialize(app,
|
5
|
-
Appsignal.logger.debug
|
24
|
+
def initialize(app, _options = nil)
|
25
|
+
Appsignal.logger.debug \
|
26
|
+
"Initializing Appsignal::Rack::JSExceptionCatcher"
|
6
27
|
@app = app
|
7
|
-
@options = options
|
8
28
|
end
|
9
29
|
|
10
30
|
def call(env)
|
11
|
-
|
12
|
-
|
31
|
+
# Ignore other paths than the error catching path.
|
32
|
+
return @app.call(env) unless error_cathing_endpoint?(env)
|
33
|
+
|
34
|
+
# Prevent raising a 404 not found when a non-active environment posts
|
35
|
+
# to this endpoint.
|
36
|
+
unless Appsignal.active?
|
37
|
+
return [
|
38
|
+
202,
|
39
|
+
{},
|
40
|
+
["AppSignal JavaScript error catching endpoint is not active."]
|
41
|
+
]
|
42
|
+
end
|
13
43
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Appsignal.logger.debug "JSExceptionCatcher: Could not send exception, 'name' is empty."
|
20
|
-
code = 422
|
21
|
-
end
|
44
|
+
begin
|
45
|
+
body = JSON.parse(env["rack.input"].read)
|
46
|
+
rescue JSON::ParserError
|
47
|
+
return [400, {}, ["Request payload is not valid JSON."]]
|
48
|
+
end
|
22
49
|
|
23
|
-
|
50
|
+
if body["name"].is_a?(String) && !body["name"].empty?
|
51
|
+
transaction = JSExceptionTransaction.new(body)
|
52
|
+
transaction.complete!
|
53
|
+
code = 200
|
24
54
|
else
|
25
|
-
|
55
|
+
Appsignal.logger.debug \
|
56
|
+
"JSExceptionCatcher: Could not send exception, 'name' is empty."
|
57
|
+
code = 422
|
26
58
|
end
|
59
|
+
|
60
|
+
[code, {}, []]
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def error_cathing_endpoint?(env)
|
66
|
+
env["PATH_INFO"] == Appsignal.config[:frontend_error_catching_path]
|
27
67
|
end
|
28
68
|
end
|
29
69
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "rack"
|
2
2
|
|
3
3
|
module Appsignal
|
4
|
+
# @api private
|
4
5
|
module Rack
|
5
6
|
class RailsInstrumentation
|
6
7
|
def initialize(app, options = {})
|
@@ -33,7 +34,7 @@ module Appsignal
|
|
33
34
|
ensure
|
34
35
|
controller = env["action_controller.instance"]
|
35
36
|
if controller
|
36
|
-
transaction.
|
37
|
+
transaction.set_action_if_nil("#{controller.class}##{controller.action_name}")
|
37
38
|
end
|
38
39
|
transaction.set_http_or_background_queue_start
|
39
40
|
transaction.set_metadata("path", request.path)
|
@@ -7,6 +7,8 @@ module Appsignal
|
|
7
7
|
# `use Appsignal::Rack::SinatraInstrumentation` in their modular Sinatra
|
8
8
|
# applications. This is no longer needed. Instead Appsignal now includes
|
9
9
|
# `use Appsignal::Rack::SinatraBaseInstrumentation` automatically.
|
10
|
+
#
|
11
|
+
# @api private
|
10
12
|
class SinatraInstrumentation
|
11
13
|
def initialize(app, options = {})
|
12
14
|
@app = app
|
@@ -63,10 +65,10 @@ module Appsignal
|
|
63
65
|
ensure
|
64
66
|
# If raise_error is off versions of Sinatra don't raise errors, but store
|
65
67
|
# them in the sinatra.error env var.
|
66
|
-
if
|
68
|
+
if !raise_errors_on && env["sinatra.error"] && !env["sinatra.skip_appsignal_error"]
|
67
69
|
transaction.set_error(env["sinatra.error"])
|
68
70
|
end
|
69
|
-
transaction.
|
71
|
+
transaction.set_action_if_nil(action_name(env))
|
70
72
|
transaction.set_metadata("path", request.path)
|
71
73
|
transaction.set_metadata("method", request.request_method)
|
72
74
|
transaction.set_http_or_background_queue_start
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# Appsignal module that tracks exceptions in Streaming rack responses.
|
2
1
|
module Appsignal
|
3
2
|
module Rack
|
3
|
+
# Appsignal module that tracks exceptions in Streaming rack responses.
|
4
|
+
#
|
5
|
+
# @api private
|
4
6
|
class StreamingListener
|
5
7
|
def initialize(app, options = {})
|
6
8
|
Appsignal.logger.debug "Initializing Appsignal::Rack::StreamingListener"
|
@@ -33,7 +35,7 @@ module Appsignal
|
|
33
35
|
transaction.set_error(e)
|
34
36
|
raise e
|
35
37
|
ensure
|
36
|
-
transaction.
|
38
|
+
transaction.set_action_if_nil(env["appsignal.action"])
|
37
39
|
transaction.set_metadata("path", request.path)
|
38
40
|
transaction.set_metadata("method", request.request_method)
|
39
41
|
transaction.set_http_or_background_queue_start
|
data/lib/appsignal/system.rb
CHANGED
@@ -1,38 +1,12 @@
|
|
1
1
|
module Appsignal
|
2
|
+
# System environment detection module.
|
3
|
+
#
|
4
|
+
# Provides useful methods to find out more about the host system.
|
5
|
+
#
|
6
|
+
# @api private
|
2
7
|
module System
|
3
|
-
def self.container?
|
4
|
-
heroku? || Container.id
|
5
|
-
end
|
6
|
-
|
7
8
|
def self.heroku?
|
8
9
|
ENV.key? "DYNO".freeze
|
9
10
|
end
|
10
|
-
|
11
|
-
module Container
|
12
|
-
CGROUP_FILE = "/proc/self/cgroup".freeze
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def id
|
16
|
-
case cgroups
|
17
|
-
when %r{docker[-|/]([0-9a-f]+)}
|
18
|
-
$1
|
19
|
-
when %r{lxc/([0-9a-f-]+)$} # LXC / Heroku
|
20
|
-
$1
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def cgroups
|
27
|
-
file = CGROUP_FILE
|
28
|
-
return unless File.exist? file
|
29
|
-
|
30
|
-
File.read(file)
|
31
|
-
rescue SystemCallError => e
|
32
|
-
Appsignal.logger.debug "Unable to read '#{file}' to determine cgroup"
|
33
|
-
Appsignal.logger.debug e
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
11
|
end
|
38
12
|
end
|
@@ -20,7 +20,7 @@ module Appsignal
|
|
20
20
|
HTTP_CACHE_CONTROL HTTP_CONNECTION HTTP_USER_AGENT HTTP_FROM
|
21
21
|
HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_X_FORWARDED_FOR
|
22
22
|
HTTP_CLIENT_IP HTTP_RANGE HTTP_X_AUTH_TOKEN
|
23
|
-
)
|
23
|
+
).freeze
|
24
24
|
|
25
25
|
class << self
|
26
26
|
def create(id, namespace, request, options = {})
|
@@ -59,10 +59,11 @@ module Appsignal
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
attr_reader :ext, :transaction_id, :namespace, :request, :paused, :tags, :options, :discarded
|
62
|
+
attr_reader :ext, :transaction_id, :action, :namespace, :request, :paused, :tags, :options, :discarded
|
63
63
|
|
64
64
|
def initialize(transaction_id, namespace, request, options = {})
|
65
65
|
@transaction_id = transaction_id
|
66
|
+
@action = nil
|
66
67
|
@namespace = namespace
|
67
68
|
@request = request
|
68
69
|
@paused = false
|
@@ -122,15 +123,78 @@ module Appsignal
|
|
122
123
|
@store[key]
|
123
124
|
end
|
124
125
|
|
126
|
+
# Set tags on the transaction.
|
127
|
+
#
|
128
|
+
# @param given_tags [Hash] Collection of tags.
|
129
|
+
# @option given_tags [String, Symbol, Integer] :any
|
130
|
+
# The name of the tag as a Symbol.
|
131
|
+
# @option given_tags [String, Symbol, Integer] "any"
|
132
|
+
# The name of the tag as a String.
|
133
|
+
# @return [void]
|
134
|
+
#
|
135
|
+
# @see Appsignal.tag_request
|
136
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/tagging.html
|
137
|
+
# Tagging guide
|
125
138
|
def set_tags(given_tags = {})
|
126
139
|
@tags.merge!(given_tags)
|
127
140
|
end
|
128
141
|
|
142
|
+
# Set an action name for the transaction.
|
143
|
+
#
|
144
|
+
# An action name is used to identify the location of a certain sample;
|
145
|
+
# error and performance issues.
|
146
|
+
#
|
147
|
+
# @param action [String] the action name to set.
|
148
|
+
# @return [void]
|
149
|
+
# @see Appsignal.set_action
|
150
|
+
# @see #set_action_if_nil
|
151
|
+
# @since 2.2.0
|
129
152
|
def set_action(action)
|
130
153
|
return unless action
|
154
|
+
@action = action
|
131
155
|
@ext.set_action(action)
|
132
156
|
end
|
133
157
|
|
158
|
+
# Set an action name only if there is no current action set.
|
159
|
+
#
|
160
|
+
# Commonly used by AppSignal integrations so that they don't override
|
161
|
+
# custom action names.
|
162
|
+
#
|
163
|
+
# @example
|
164
|
+
# Appsignal.set_action("foo")
|
165
|
+
# Appsignal.set_action_if_nil("bar")
|
166
|
+
# # Transaction action will be "foo"
|
167
|
+
#
|
168
|
+
# @param action [String]
|
169
|
+
# @return [void]
|
170
|
+
# @see #set_action
|
171
|
+
# @since 2.2.0
|
172
|
+
def set_action_if_nil(action)
|
173
|
+
return if @action
|
174
|
+
set_action(action)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Set the namespace for this transaction.
|
178
|
+
#
|
179
|
+
# Useful to split up parts of an application into certain namespaces. For
|
180
|
+
# example: http requests, background jobs and administration panel
|
181
|
+
# controllers.
|
182
|
+
#
|
183
|
+
# Note: The "http_request" namespace gets transformed on AppSignal.com to
|
184
|
+
# "Web" and "background_job" gets transformed to "Background".
|
185
|
+
#
|
186
|
+
# @example
|
187
|
+
# transaction.set_action("admin")
|
188
|
+
#
|
189
|
+
# @param namespace [String] namespace name to use for this transaction.
|
190
|
+
# @return [void]
|
191
|
+
# @since 2.2.0
|
192
|
+
def set_namespace(namespace)
|
193
|
+
return unless namespace
|
194
|
+
@namespace = namespace
|
195
|
+
@ext.set_namespace(namespace)
|
196
|
+
end
|
197
|
+
|
134
198
|
def set_http_or_background_action(from = request.params)
|
135
199
|
return unless from
|
136
200
|
group_and_action = [
|
@@ -239,7 +303,7 @@ module Appsignal
|
|
239
303
|
end
|
240
304
|
end
|
241
305
|
|
242
|
-
|
306
|
+
private
|
243
307
|
|
244
308
|
# Returns calculated background queue start time in milliseconds, based on
|
245
309
|
# environment values.
|
@@ -308,7 +372,7 @@ module Appsignal
|
|
308
372
|
# The environment of a transaction can contain a lot of information, not
|
309
373
|
# all of it useful for debugging.
|
310
374
|
#
|
311
|
-
# Only the values from the keys specified in
|
375
|
+
# Only the values from the keys specified in {ENV_METHODS} are returned.
|
312
376
|
#
|
313
377
|
# @return [nil] if no environment is present.
|
314
378
|
# @return [Hash<String, Object>]
|
@@ -380,8 +444,9 @@ module Appsignal
|
|
380
444
|
end
|
381
445
|
end
|
382
446
|
|
383
|
-
# Stub that is returned by
|
384
|
-
# that it's still safe to call methods on it if there is
|
447
|
+
# Stub that is returned by {Transaction.current} if there is no current
|
448
|
+
# transaction, so that it's still safe to call methods on it if there is no
|
449
|
+
# current transaction.
|
385
450
|
class NilTransaction
|
386
451
|
def method_missing(m, *args, &block)
|
387
452
|
end
|
@@ -5,9 +5,9 @@ require "rack/utils"
|
|
5
5
|
require "json"
|
6
6
|
|
7
7
|
module Appsignal
|
8
|
+
# @api private
|
8
9
|
class Transmitter
|
9
10
|
CONTENT_TYPE = "application/json; charset=UTF-8".freeze
|
10
|
-
CONTENT_ENCODING = "gzip".freeze
|
11
11
|
|
12
12
|
HTTP_ERRORS = [
|
13
13
|
EOFError,
|
@@ -19,38 +19,49 @@ module Appsignal
|
|
19
19
|
Net::ProtocolError,
|
20
20
|
Timeout::Error,
|
21
21
|
OpenSSL::SSL::SSLError
|
22
|
-
]
|
22
|
+
].freeze
|
23
23
|
|
24
|
-
attr_reader :config, :
|
24
|
+
attr_reader :config, :base_uri
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
# @param base_uri [String] Base URI for the transmitter to use. If a full
|
27
|
+
# URI is given (including the HTTP protocol) it is used as the full base.
|
28
|
+
# If only a path is given the `config[:endpoint]` is prefixed along with
|
29
|
+
# `/1/` (API v1 endpoint).
|
30
|
+
# @param config [Appsignal::Config] AppSignal configuration to use for this
|
31
|
+
# transmission.
|
32
|
+
def initialize(base_uri, config = Appsignal.config)
|
33
|
+
@base_uri =
|
34
|
+
if base_uri.start_with? "http"
|
35
|
+
base_uri
|
36
|
+
else
|
37
|
+
"#{config[:endpoint]}/1/#{base_uri}"
|
38
|
+
end
|
28
39
|
@config = config
|
29
40
|
end
|
30
41
|
|
31
42
|
def uri
|
32
|
-
@uri ||= URI(
|
33
|
-
uri.query = ::Rack::Utils.build_query(
|
43
|
+
@uri ||= URI(base_uri).tap do |uri|
|
44
|
+
uri.query = ::Rack::Utils.build_query(
|
45
|
+
:api_key => config[:push_api_key],
|
34
46
|
:name => config[:name],
|
35
47
|
:environment => config.env,
|
36
48
|
:hostname => config[:hostname],
|
37
|
-
:gem_version => Appsignal::VERSION
|
49
|
+
:gem_version => Appsignal::VERSION
|
50
|
+
)
|
38
51
|
end
|
39
52
|
end
|
40
53
|
|
41
54
|
def transmit(payload)
|
42
55
|
config.logger.debug "Transmitting payload to #{uri}"
|
43
|
-
http_client.request(http_post(payload))
|
56
|
+
http_client.request(http_post(payload))
|
44
57
|
end
|
45
58
|
|
46
|
-
|
59
|
+
private
|
47
60
|
|
48
61
|
def http_post(payload)
|
49
62
|
Net::HTTP::Post.new(uri.request_uri).tap do |request|
|
50
63
|
request["Content-Type"] = CONTENT_TYPE
|
51
|
-
request
|
52
|
-
request.body = Appsignal::Utils::Gzip.compress \
|
53
|
-
Appsignal::Utils::JSON.generate(payload)
|
64
|
+
request.body = Appsignal::Utils::JSON.generate(payload)
|
54
65
|
end
|
55
66
|
end
|
56
67
|
|
data/lib/appsignal/utils.rb
CHANGED
@@ -2,6 +2,7 @@ require "appsignal/utils/params_sanitizer"
|
|
2
2
|
require "appsignal/utils/query_params_sanitizer"
|
3
3
|
|
4
4
|
module Appsignal
|
5
|
+
# @api private
|
5
6
|
module Utils
|
6
7
|
def self.data_generate(body)
|
7
8
|
Data.generate(body)
|
@@ -15,7 +16,7 @@ module Appsignal
|
|
15
16
|
elsif body.is_a?(Array)
|
16
17
|
map_array(body)
|
17
18
|
else
|
18
|
-
raise TypeError
|
19
|
+
raise TypeError, "Body of type #{body.class} should be a Hash or Array"
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -26,8 +27,14 @@ module Appsignal
|
|
26
27
|
case value
|
27
28
|
when String
|
28
29
|
map.set_string(key, value)
|
29
|
-
when
|
30
|
-
|
30
|
+
when Integer
|
31
|
+
# An Integer too big for C-lang longs to fit
|
32
|
+
bigint = 1 << 63
|
33
|
+
if value >= bigint
|
34
|
+
map.set_string(key, "bigint:#{value}")
|
35
|
+
else
|
36
|
+
map.set_integer(key, value)
|
37
|
+
end
|
31
38
|
when Float
|
32
39
|
map.set_float(key, value)
|
33
40
|
when TrueClass, FalseClass
|
@@ -51,8 +58,14 @@ module Appsignal
|
|
51
58
|
case value
|
52
59
|
when String
|
53
60
|
array.append_string(value)
|
54
|
-
when
|
55
|
-
|
61
|
+
when Integer
|
62
|
+
# An Integer too big for C-lang longs to fit
|
63
|
+
bigint = 1 << 63
|
64
|
+
if value >= bigint
|
65
|
+
array.append_string("bigint:#{value}")
|
66
|
+
else
|
67
|
+
array.append_integer(value)
|
68
|
+
end
|
56
69
|
when Float
|
57
70
|
array.append_float(value)
|
58
71
|
when TrueClass, FalseClass
|
@@ -108,11 +121,5 @@ module Appsignal
|
|
108
121
|
end
|
109
122
|
end
|
110
123
|
end
|
111
|
-
|
112
|
-
class Gzip
|
113
|
-
def self.compress(body)
|
114
|
-
Zlib::Deflate.deflate(body, Zlib::BEST_SPEED)
|
115
|
-
end
|
116
|
-
end
|
117
124
|
end
|
118
125
|
end
|