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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +14 -0
  3. data/.rubocop_todo.yml +16 -171
  4. data/.travis.yml +14 -1
  5. data/.yardopts +8 -0
  6. data/CHANGELOG.md +21 -3
  7. data/README.md +20 -2
  8. data/Rakefile +60 -62
  9. data/appsignal.gemspec +24 -23
  10. data/ext/agent.yml +11 -11
  11. data/ext/appsignal_extension.c +43 -12
  12. data/ext/extconf.rb +9 -9
  13. data/gemfiles/padrino.gemfile +1 -1
  14. data/lib/appsignal.rb +403 -26
  15. data/lib/appsignal/auth_check.rb +28 -1
  16. data/lib/appsignal/cli.rb +1 -0
  17. data/lib/appsignal/cli/demo.rb +40 -0
  18. data/lib/appsignal/cli/diagnose.rb +345 -89
  19. data/lib/appsignal/cli/helpers.rb +9 -4
  20. data/lib/appsignal/cli/install.rb +6 -6
  21. data/lib/appsignal/cli/notify_of_deploy.rb +58 -0
  22. data/lib/appsignal/config.rb +40 -38
  23. data/lib/appsignal/demo.rb +20 -0
  24. data/lib/appsignal/event_formatter.rb +4 -0
  25. data/lib/appsignal/event_formatter/action_view/render_formatter.rb +1 -0
  26. data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +1 -0
  27. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +1 -0
  28. data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +1 -0
  29. data/lib/appsignal/event_formatter/faraday/request_formatter.rb +1 -0
  30. data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +2 -1
  31. data/lib/appsignal/event_formatter/moped/query_formatter.rb +1 -0
  32. data/lib/appsignal/extension.rb +1 -0
  33. data/lib/appsignal/garbage_collection_profiler.rb +20 -19
  34. data/lib/appsignal/hooks.rb +1 -0
  35. data/lib/appsignal/hooks/active_support_notifications.rb +1 -0
  36. data/lib/appsignal/hooks/celluloid.rb +1 -0
  37. data/lib/appsignal/hooks/data_mapper.rb +1 -0
  38. data/lib/appsignal/hooks/delayed_job.rb +1 -0
  39. data/lib/appsignal/hooks/mongo_ruby_driver.rb +1 -0
  40. data/lib/appsignal/hooks/net_http.rb +1 -0
  41. data/lib/appsignal/hooks/passenger.rb +1 -0
  42. data/lib/appsignal/hooks/puma.rb +1 -0
  43. data/lib/appsignal/hooks/rake.rb +1 -0
  44. data/lib/appsignal/hooks/redis.rb +1 -0
  45. data/lib/appsignal/hooks/sequel.rb +1 -0
  46. data/lib/appsignal/hooks/shoryuken.rb +1 -0
  47. data/lib/appsignal/hooks/sidekiq.rb +1 -0
  48. data/lib/appsignal/hooks/unicorn.rb +1 -0
  49. data/lib/appsignal/hooks/webmachine.rb +1 -0
  50. data/lib/appsignal/integrations/capistrano/appsignal.cap +4 -4
  51. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +2 -0
  52. data/lib/appsignal/integrations/data_mapper.rb +1 -1
  53. data/lib/appsignal/integrations/delayed_job_plugin.rb +1 -0
  54. data/lib/appsignal/integrations/grape.rb +3 -1
  55. data/lib/appsignal/integrations/mongo_ruby_driver.rb +1 -0
  56. data/lib/appsignal/integrations/padrino.rb +36 -21
  57. data/lib/appsignal/integrations/railtie.rb +2 -2
  58. data/lib/appsignal/integrations/resque.rb +1 -0
  59. data/lib/appsignal/integrations/resque_active_job.rb +1 -0
  60. data/lib/appsignal/integrations/webmachine.rb +27 -24
  61. data/lib/appsignal/js_exception_transaction.rb +8 -8
  62. data/lib/appsignal/marker.rb +41 -4
  63. data/lib/appsignal/minutely.rb +1 -0
  64. data/lib/appsignal/rack/generic_instrumentation.rb +3 -2
  65. data/lib/appsignal/rack/js_exception_catcher.rb +55 -15
  66. data/lib/appsignal/rack/rails_instrumentation.rb +2 -1
  67. data/lib/appsignal/rack/sinatra_instrumentation.rb +4 -2
  68. data/lib/appsignal/rack/streaming_listener.rb +4 -2
  69. data/lib/appsignal/system.rb +5 -31
  70. data/lib/appsignal/transaction.rb +71 -6
  71. data/lib/appsignal/transmitter.rb +24 -13
  72. data/lib/appsignal/utils.rb +18 -11
  73. data/lib/appsignal/utils/params_sanitizer.rb +2 -1
  74. data/lib/appsignal/utils/query_params_sanitizer.rb +1 -0
  75. data/lib/appsignal/version.rb +1 -1
  76. data/resources/appsignal.yml.erb +1 -1
  77. data/spec/lib/appsignal/auth_check_spec.rb +64 -22
  78. data/spec/lib/appsignal/cli/diagnose_spec.rb +539 -81
  79. data/spec/lib/appsignal/cli/helpers_spec.rb +74 -2
  80. data/spec/lib/appsignal/cli/install_spec.rb +3 -3
  81. data/spec/lib/appsignal/config_spec.rb +38 -72
  82. data/spec/lib/appsignal/demo_spec.rb +2 -2
  83. data/spec/lib/appsignal/event_formatter_spec.rb +2 -2
  84. data/spec/lib/appsignal/extension_spec.rb +4 -0
  85. data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +18 -21
  86. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +1 -1
  87. data/spec/lib/appsignal/hooks/redis_spec.rb +34 -44
  88. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +2 -2
  89. data/spec/lib/appsignal/integrations/grape_spec.rb +6 -6
  90. data/spec/lib/appsignal/integrations/padrino_spec.rb +241 -122
  91. data/spec/lib/appsignal/integrations/railtie_spec.rb +34 -16
  92. data/spec/lib/appsignal/integrations/resque_spec.rb +1 -1
  93. data/spec/lib/appsignal/integrations/sinatra_spec.rb +38 -10
  94. data/spec/lib/appsignal/integrations/webmachine_spec.rb +2 -2
  95. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +7 -6
  96. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +95 -58
  97. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +9 -6
  98. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +11 -10
  99. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +20 -13
  100. data/spec/lib/appsignal/system_spec.rb +2 -32
  101. data/spec/lib/appsignal/transaction_spec.rb +48 -7
  102. data/spec/lib/appsignal/transmitter_spec.rb +52 -33
  103. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +3 -1
  104. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +3 -3
  105. data/spec/lib/appsignal/utils_spec.rb +49 -6
  106. data/spec/lib/appsignal_spec.rb +60 -5
  107. data/spec/spec_helper.rb +4 -3
  108. data/spec/support/helpers/api_request_helper.rb +1 -4
  109. data/spec/support/helpers/dependency_helper.rb +4 -0
  110. data/spec/support/helpers/system_helpers.rb +1 -17
  111. data/spec/support/helpers/time_helpers.rb +1 -1
  112. metadata +19 -8
  113. data/spec/lib/appsignal/system/container_spec.rb +0 -67
  114. data/spec/lib/appsignal/utils/gzip_spec.rb +0 -10
@@ -1,4 +1,5 @@
1
1
  module Appsignal
2
+ # @api private
2
3
  class Minutely
3
4
  class << self
4
5
  # List of probes. Probes can be lamdba's or objects that
@@ -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.set_action(env["appsignal.route"])
37
+ transaction.set_action_if_nil(env["appsignal.route"])
37
38
  else
38
- transaction.set_action("unknown")
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, options = {})
5
- Appsignal.logger.debug "Initializing Appsignal::Rack::JSExceptionCatcher"
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
- if env["PATH_INFO"] == Appsignal.config[:frontend_error_catching_path]
12
- body = JSON.parse(env["rack.input"].read)
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
- if body["name"].is_a?(String) && !body["name"].empty?
15
- transaction = JSExceptionTransaction.new(body)
16
- transaction.complete!
17
- code = 200
18
- else
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
- [code, {}, []]
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
- @app.call(env)
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.set_action("#{controller.class}##{controller.action_name}")
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 !@raise_errors_on && env["sinatra.error"] && !env["sinatra.skip_appsignal_error"]
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.set_action(action_name(env))
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.set_action(env["appsignal.action"])
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
@@ -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
- protected
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 `ENV_METHODS` are returned.
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 `Transaction.current` if there is no current transaction, so
384
- # that it's still safe to call methods on it if there is none.
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, :action
24
+ attr_reader :config, :base_uri
25
25
 
26
- def initialize(action, config = Appsignal.config)
27
- @action = action
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("#{config[:endpoint]}/1/#{action}").tap do |uri|
33
- uri.query = ::Rack::Utils.build_query(:api_key => config[:push_api_key],
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)).code
56
+ http_client.request(http_post(payload))
44
57
  end
45
58
 
46
- protected
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["Content-Encoding"] = CONTENT_ENCODING
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
 
@@ -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.new("Body of type #{body.class} should be a Hash or Array")
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 Fixnum
30
- map.set_fixnum(key, value)
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 Fixnum
55
- array.append_fixnum(value)
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