appsignal 3.9.2-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3138 -0
  3. data/.rubocop.yml +28 -20
  4. data/.rubocop_todo.yml +7 -33
  5. data/CHANGELOG.md +130 -0
  6. data/README.md +0 -1
  7. data/Rakefile +80 -65
  8. data/appsignal.gemspec +1 -1
  9. data/build_matrix.yml +112 -184
  10. data/ext/base.rb +1 -1
  11. data/gemfiles/hanami-2.1.gemfile +7 -0
  12. data/gemfiles/webmachine1.gemfile +5 -4
  13. data/lib/appsignal/cli/diagnose.rb +1 -1
  14. data/lib/appsignal/config.rb +5 -1
  15. data/lib/appsignal/demo.rb +0 -1
  16. data/lib/appsignal/environment.rb +11 -2
  17. data/lib/appsignal/extension/jruby.rb +1 -1
  18. data/lib/appsignal/helpers/instrumentation.rb +164 -2
  19. data/lib/appsignal/hooks/active_job.rb +1 -6
  20. data/lib/appsignal/integrations/grape.rb +19 -47
  21. data/lib/appsignal/integrations/hanami.rb +8 -7
  22. data/lib/appsignal/integrations/padrino.rb +51 -52
  23. data/lib/appsignal/integrations/railtie.rb +0 -3
  24. data/lib/appsignal/integrations/rake.rb +46 -12
  25. data/lib/appsignal/integrations/sidekiq.rb +1 -11
  26. data/lib/appsignal/integrations/sinatra.rb +0 -1
  27. data/lib/appsignal/integrations/webmachine.rb +15 -9
  28. data/lib/appsignal/probes/gvl.rb +24 -2
  29. data/lib/appsignal/probes/sidekiq.rb +1 -1
  30. data/lib/appsignal/probes.rb +1 -1
  31. data/lib/appsignal/rack/abstract_middleware.rb +104 -33
  32. data/lib/appsignal/rack/body_wrapper.rb +143 -0
  33. data/lib/appsignal/rack/event_handler.rb +12 -3
  34. data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
  35. data/lib/appsignal/rack/grape_middleware.rb +40 -0
  36. data/lib/appsignal/rack/hanami_middleware.rb +2 -12
  37. data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
  38. data/lib/appsignal/rack/rails_instrumentation.rb +14 -57
  39. data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
  40. data/lib/appsignal/rack/streaming_listener.rb +13 -59
  41. data/lib/appsignal/rack.rb +31 -0
  42. data/lib/appsignal/transaction.rb +50 -8
  43. data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
  44. data/lib/appsignal/utils.rb +1 -0
  45. data/lib/appsignal/version.rb +1 -1
  46. data/lib/appsignal.rb +36 -33
  47. data/spec/.rubocop.yml +1 -1
  48. data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
  49. data/spec/lib/appsignal/cli/install_spec.rb +3 -3
  50. data/spec/lib/appsignal/config_spec.rb +8 -5
  51. data/spec/lib/appsignal/demo_spec.rb +38 -41
  52. data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
  53. data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
  54. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
  55. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
  56. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
  57. data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
  58. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
  59. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
  60. data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
  61. data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
  62. data/spec/lib/appsignal/hooks/rake_spec.rb +107 -34
  63. data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
  64. data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
  65. data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
  66. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
  67. data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
  68. data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
  69. data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
  70. data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
  71. data/spec/lib/appsignal/integrations/padrino_spec.rb +190 -163
  72. data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
  73. data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
  74. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
  75. data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -3
  76. data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -40
  77. data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
  78. data/spec/lib/appsignal/probes_spec.rb +7 -4
  79. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +302 -105
  80. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
  81. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
  82. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -27
  83. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
  84. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
  85. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
  86. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
  87. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
  88. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +44 -139
  89. data/spec/lib/appsignal/transaction_spec.rb +239 -94
  90. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
  91. data/spec/lib/appsignal_spec.rb +556 -344
  92. data/spec/support/helpers/dependency_helper.rb +6 -1
  93. data/spec/support/helpers/std_streams_helper.rb +1 -1
  94. data/spec/support/helpers/transaction_helpers.rb +8 -0
  95. data/spec/support/matchers/transaction.rb +185 -0
  96. data/spec/support/mocks/dummy_app.rb +20 -0
  97. data/spec/support/shared_examples/instrument.rb +17 -12
  98. data/spec/support/testing.rb +18 -9
  99. metadata +20 -11
  100. data/.semaphore/semaphore.yml +0 -2347
  101. data/script/lint_git +0 -22
  102. data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
  103. data/spec/support/matchers/be_completed.rb +0 -5
  104. data/support/check_versions +0 -22
  105. /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
@@ -1,73 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ Appsignal::Utils::StdoutAndLoggerMessage.warning \
4
+ "The constant Appsignal::Rack::StreamingListener has been deprecated. " \
5
+ "Please update the constant name to " \
6
+ "Appsignal::Rack::InstrumentationMiddleware."
7
+
3
8
  module Appsignal
4
9
  module Rack
5
- # Appsignal module that tracks exceptions in Streaming rack responses.
10
+ # Instrumentation middleware that tracks exceptions in streaming Rack
11
+ # responses.
6
12
  #
7
13
  # @api private
8
- class StreamingListener
14
+ class StreamingListener < AbstractMiddleware
9
15
  def initialize(app, options = {})
10
- Appsignal.internal_logger.debug "Initializing Appsignal::Rack::StreamingListener"
11
- @app = app
12
- @options = options
13
- end
14
-
15
- def call(env)
16
- if Appsignal.active?
17
- call_with_appsignal_monitoring(env)
18
- else
19
- @app.call(env)
20
- end
16
+ options[:instrument_event_name] ||= "process_streaming_request.rack"
17
+ super
21
18
  end
22
19
 
23
- def call_with_appsignal_monitoring(env)
24
- request = ::Rack::Request.new(env)
25
- transaction = Appsignal::Transaction.create(
26
- SecureRandom.uuid,
27
- Appsignal::Transaction::HTTP_REQUEST,
28
- request
29
- )
20
+ def add_transaction_metadata_after(transaction, request)
21
+ transaction.set_action_if_nil(request.env["appsignal.action"])
30
22
 
31
- # Instrument a `process_action`, to set params/action name
32
- status, headers, body =
33
- Appsignal.instrument("process_action.rack") do
34
- @app.call(env)
35
- rescue Exception => e # rubocop:disable Lint/RescueException
36
- transaction.set_error(e)
37
- raise e
38
- ensure
39
- transaction.set_action_if_nil(env["appsignal.action"])
40
- transaction.set_metadata("path", request.path)
41
- transaction.set_metadata("method", request.request_method)
42
- transaction.set_http_or_background_queue_start
43
- end
44
-
45
- # Wrap the result body with our StreamWrapper
46
- [status, headers, StreamWrapper.new(body, transaction)]
23
+ super
47
24
  end
48
25
  end
49
26
  end
50
-
51
- class StreamWrapper
52
- def initialize(stream, transaction)
53
- @stream = stream
54
- @transaction = transaction
55
- end
56
-
57
- def each(&block)
58
- @stream.each(&block)
59
- rescue Exception => e # rubocop:disable Lint/RescueException
60
- @transaction.set_error(e)
61
- raise e
62
- end
63
-
64
- def close
65
- @stream.close if @stream.respond_to?(:close)
66
- rescue Exception => e # rubocop:disable Lint/RescueException
67
- @transaction.set_error(e)
68
- raise e
69
- ensure
70
- Appsignal::Transaction.complete_current!
71
- end
72
- end
73
27
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ # @api private
5
+ module Rack
6
+ # Alias constants that have moved with a warning message that points to the
7
+ # place to update the reference.
8
+ def self.const_missing(name)
9
+ case name
10
+ when :GenericInstrumentation
11
+ require "appsignal/rack/generic_instrumentation"
12
+
13
+ callers = caller
14
+ Appsignal::Utils::StdoutAndLoggerMessage.warning \
15
+ "The constant Appsignal::Rack::GenericInstrumentation has been deprecated. " \
16
+ "Please use the new Appsignal::Rack::InstrumentationMiddleware middleware. " \
17
+ "This new middleware does not default the action name to 'unknown'. " \
18
+ "Set the action name for the endpoint using the Appsignal.set_action helper. " \
19
+ "Read our Rack docs for more information " \
20
+ "https://docs.appsignal.com/ruby/integrations/rack.html " \
21
+ "Update the constant name to " \
22
+ "Appsignal::Rack::InstrumentationMiddleware in the following file to " \
23
+ "remove this message.\n#{callers.first}"
24
+ # Return the alias so it can't ever get stuck in a recursive loop
25
+ Appsignal::Rack::GenericInstrumentationAlias
26
+ else
27
+ super
28
+ end
29
+ end
30
+ end
31
+ end
@@ -74,7 +74,7 @@ module Appsignal
74
74
  end
75
75
 
76
76
  attr_reader :ext, :transaction_id, :action, :namespace, :request, :paused, :tags, :options,
77
- :discarded, :breadcrumbs
77
+ :discarded, :breadcrumbs, :custom_data
78
78
 
79
79
  def initialize(transaction_id, namespace, request, options = {})
80
80
  @transaction_id = transaction_id
@@ -84,10 +84,12 @@ module Appsignal
84
84
  @paused = false
85
85
  @discarded = false
86
86
  @tags = {}
87
+ @custom_data = nil
87
88
  @breadcrumbs = []
88
89
  @store = Hash.new({})
89
90
  @options = options
90
91
  @options[:params_method] ||= :params
92
+ @params = nil
91
93
 
92
94
  @ext = Appsignal::Extension.start_transaction(
93
95
  @transaction_id,
@@ -139,9 +141,13 @@ module Appsignal
139
141
  end
140
142
 
141
143
  def params
142
- return @params if defined?(@params)
144
+ parameters = @params || request_params
143
145
 
144
- request_params
146
+ if parameters.respond_to? :call
147
+ parameters.call
148
+ else
149
+ parameters
150
+ end
145
151
  end
146
152
 
147
153
  # Set parameters on the transaction.
@@ -152,9 +158,17 @@ module Appsignal
152
158
  # The parameters set using {#set_params} are leading over those extracted
153
159
  # from a request's environment.
154
160
  #
161
+ # When both the `given_params` and a block is given to this method, the
162
+ # `given_params` argument is leading and the block will _not_ be called.
163
+ #
164
+ # @since 3.9.1
155
165
  # @param given_params [Hash] The parameters to set on the transaction.
166
+ # @yield This block is called when the transaction is sampled. The block's
167
+ # return value will become the new parameters.
156
168
  # @return [void]
157
- def set_params(given_params)
169
+ # @see {Helpers::Instrumentation#set_params}
170
+ def set_params(given_params = nil, &block)
171
+ @params = block if block
158
172
  @params = given_params if given_params
159
173
  end
160
174
 
@@ -172,14 +186,20 @@ module Appsignal
172
186
  # When no parameters are set this way, the transaction will look for
173
187
  # parameters on the {#request} environment.
174
188
  #
189
+ # @since 3.9.1
175
190
  # @param given_params [Hash] The parameters to set on the transaction if none are already set.
191
+ # @yield This block is called when the transaction is sampled. The block's
192
+ # return value will become the new parameters.
176
193
  # @return [void]
177
- def set_params_if_nil(given_params)
178
- set_params(given_params) unless @params
194
+ # @see {Helpers::Instrumentation#set_params_if_nil}
195
+ def set_params_if_nil(given_params = nil, &block)
196
+ set_params(given_params, &block) unless @params
179
197
  end
180
198
 
181
199
  # Set tags on the transaction.
182
200
  #
201
+ # When this method is called multiple times, it will merge the tags.
202
+ #
183
203
  # @param given_tags [Hash] Collection of tags.
184
204
  # @option given_tags [String, Symbol, Integer] :any
185
205
  # The name of the tag as a Symbol.
@@ -187,13 +207,34 @@ module Appsignal
187
207
  # The name of the tag as a String.
188
208
  # @return [void]
189
209
  #
190
- # @see Appsignal.tag_request
210
+ # @see Helpers::Instrumentation#tag_request
191
211
  # @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
192
212
  # Tagging guide
193
213
  def set_tags(given_tags = {})
194
214
  @tags.merge!(given_tags)
195
215
  end
196
216
 
217
+ # Set custom data on the transaction.
218
+ #
219
+ # When this method is called multiple times, it will overwrite the
220
+ # previously set value.
221
+ #
222
+ # @since 3.10.0
223
+ # @see Appsignal.set_custom_data
224
+ # @see https://docs.appsignal.com/guides/custom-data/sample-data.html
225
+ # Sample data guide
226
+ # @param data [Hash/Array]
227
+ # @return [void]
228
+ def set_custom_data(data)
229
+ case data
230
+ when Array, Hash
231
+ @custom_data = data
232
+ else
233
+ Appsignal.internal_logger
234
+ .error("set_custom_data: Unsupported data type #{data.class} received.")
235
+ end
236
+ end
237
+
197
238
  # Add breadcrumbs to the transaction.
198
239
  #
199
240
  # @param category [String] category of breadcrumb
@@ -376,7 +417,8 @@ module Appsignal
376
417
  :session_data => sanitized_session_data,
377
418
  :metadata => sanitized_metadata,
378
419
  :tags => sanitized_tags,
379
- :breadcrumbs => breadcrumbs
420
+ :breadcrumbs => breadcrumbs,
421
+ :custom_data => custom_data
380
422
  }.each do |key, data|
381
423
  set_sample_data(key, data)
382
424
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Appsignal
6
+ module Utils
7
+ # @api private
8
+ class IntegrationMemoryLogger
9
+ LEVELS = {
10
+ Logger::DEBUG => :DEBUG,
11
+ Logger::INFO => :INFO,
12
+ Logger::WARN => :WARN,
13
+ Logger::ERROR => :ERROR,
14
+ Logger::FATAL => :FATAL,
15
+ Logger::UNKNOWN => :UNKNOWN
16
+ }.freeze
17
+
18
+ attr_accessor :formatter, :level
19
+
20
+ def add(severity, message, _progname = nil)
21
+ message = formatter.call(severity, Time.now, nil, message) if formatter
22
+ messages[severity] << message
23
+ end
24
+ alias log add
25
+
26
+ def debug(message)
27
+ add(:DEBUG, message)
28
+ end
29
+
30
+ def info(message)
31
+ add(:INFO, message)
32
+ end
33
+
34
+ def warn(message)
35
+ add(:WARN, message)
36
+ end
37
+
38
+ def seen_keys
39
+ @seen_keys ||= Set.new
40
+ end
41
+
42
+ def warn_once_then_debug(key, message)
43
+ if seen_keys.add?(key).nil?
44
+ debug message
45
+ else
46
+ warn message
47
+ end
48
+ end
49
+
50
+ def error(message)
51
+ add(:ERROR, message)
52
+ end
53
+
54
+ def fatal(message)
55
+ add(:FATAL, message)
56
+ end
57
+
58
+ def unknown(message)
59
+ add(:UNKNOWN, message)
60
+ end
61
+
62
+ def clear
63
+ messages.clear
64
+ end
65
+
66
+ def messages
67
+ @messages ||= Hash.new { |hash, key| hash[key] = [] }
68
+ end
69
+
70
+ def messages_for_level(level)
71
+ levels = LEVELS.select { |log_level| log_level >= level }.values
72
+ messages
73
+ .select { |log_level| levels.include?(log_level) }
74
+ .flat_map { |_level, message| message }
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "appsignal/utils/integration_memory_logger"
3
4
  require "appsignal/utils/stdout_and_logger_message"
4
5
  require "appsignal/utils/data"
5
6
  require "appsignal/utils/hash_sanitizer"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.9.2"
4
+ VERSION = "3.10.0"
5
5
  end
data/lib/appsignal.rb CHANGED
@@ -55,14 +55,15 @@ module Appsignal
55
55
  # directly.
56
56
  #
57
57
  # If no logger has been set, it will return a "in memory logger", using
58
- # `in_memory_log`. Once AppSignal is started (using {.start}) the
59
- # contents of the "in memory logger" is written to the new logger.
58
+ # {Utils::IntegrationMemoryLogger}. Once AppSignal is started (using
59
+ # {.start}) the contents of the "in memory logger" is written to the new
60
+ # logger.
60
61
  #
61
62
  # @note some classes may have options to set custom loggers. Their
62
63
  # defaults are pointed to this attribute.
63
64
  # @api private
64
65
  # @return [Logger]
65
- # @see start_logger
66
+ # @see start
66
67
  attr_writer :internal_logger
67
68
 
68
69
  # @api private
@@ -84,8 +85,6 @@ module Appsignal
84
85
  # AppSignal](https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html)
85
86
  # guide.
86
87
  #
87
- # To start the logger see {.start_logger}.
88
- #
89
88
  # @example
90
89
  # Appsignal.start
91
90
  #
@@ -108,8 +107,9 @@ module Appsignal
108
107
  ENV["APPSIGNAL_APP_ENV"] || ENV["RAILS_ENV"] || ENV.fetch("RACK_ENV", nil)
109
108
  )
110
109
 
110
+ _start_logger
111
+
111
112
  if config.valid?
112
- internal_logger.level = config.log_level
113
113
  if config.active?
114
114
  internal_logger.info "Starting AppSignal #{Appsignal::VERSION} " \
115
115
  "(#{$PROGRAM_NAME}, Ruby #{RUBY_VERSION}, #{RUBY_PLATFORM})"
@@ -160,7 +160,7 @@ module Appsignal
160
160
  def forked
161
161
  return unless active?
162
162
 
163
- Appsignal.start_logger
163
+ Appsignal._start_logger
164
164
  internal_logger.debug("Forked process, resubscribing and restarting extension")
165
165
  Appsignal::Extension.start
166
166
  end
@@ -169,27 +169,15 @@ module Appsignal
169
169
  Appsignal::Extension.get_server_state(key)
170
170
  end
171
171
 
172
- # In memory internal logger used before any internal logger is started with
173
- # {.start_logger}.
174
- #
175
- # The contents of this logger are flushed to the logger in {.start_logger}.
176
- #
177
- # @api private
178
- # @return [StringIO]
179
- def in_memory_log
180
- if defined?(@in_memory_log) && @in_memory_log
181
- @in_memory_log
182
- else
183
- @in_memory_log = StringIO.new
184
- end
172
+ def in_memory_logger
173
+ @in_memory_logger ||=
174
+ Appsignal::Utils::IntegrationMemoryLogger.new.tap do |l|
175
+ l.formatter = log_formatter("appsignal")
176
+ end
185
177
  end
186
178
 
187
179
  def internal_logger
188
- @internal_logger ||=
189
- Appsignal::Utils::IntegrationLogger.new(in_memory_log).tap do |l|
190
- l.level = ::Logger::INFO
191
- l.formatter = log_formatter("appsignal")
192
- end
180
+ @internal_logger ||= in_memory_logger
193
181
  end
194
182
 
195
183
  # @api private
@@ -201,14 +189,26 @@ module Appsignal
201
189
  end
202
190
  end
203
191
 
192
+ # @deprecated Only {.start} has to be called.
193
+ # @return [void]
194
+ # @since 0.7.0
195
+ def start_logger
196
+ callers = caller
197
+ Appsignal::Utils::StdoutAndLoggerMessage.warning \
198
+ "Callng 'Appsignal.start_logger' is deprecated. " \
199
+ "The logger will be started when calling 'Appsignal.start'. " \
200
+ "Remove the 'Appsignal.start_logger' call in the following file to " \
201
+ "remove this message.\n#{callers.first}"
202
+ end
203
+
204
204
  # Start the AppSignal internal logger.
205
205
  #
206
206
  # Sets the log level and sets the logger. Uses a file-based logger or the
207
207
  # STDOUT-based logger. See the `:log` configuration option.
208
208
  #
209
+ # @api private
209
210
  # @return [void]
210
- # @since 0.7.0
211
- def start_logger
211
+ def _start_logger
212
212
  if config && config[:log] == "file" && config.log_file_path
213
213
  start_internal_file_logger(config.log_file_path)
214
214
  else
@@ -221,10 +221,11 @@ module Appsignal
221
221
  else
222
222
  Appsignal::Config::DEFAULT_LOG_LEVEL
223
223
  end
224
- return unless @in_memory_log
224
+ return unless @in_memory_logger
225
225
 
226
- internal_logger << @in_memory_log.string
227
- @in_memory_log = nil
226
+ messages = @in_memory_logger.messages_for_level(internal_logger.level)
227
+ internal_logger << messages.join
228
+ @in_memory_logger = nil
228
229
  end
229
230
 
230
231
  # Returns if the C-extension was loaded properly.
@@ -323,11 +324,13 @@ require "appsignal/hooks"
323
324
  require "appsignal/probes"
324
325
  require "appsignal/marker"
325
326
  require "appsignal/garbage_collection"
327
+ require "appsignal/rack"
328
+ require "appsignal/rack/body_wrapper"
329
+ require "appsignal/rack/abstract_middleware"
330
+ require "appsignal/rack/instrumentation_middleware"
331
+ require "appsignal/rack/event_handler"
326
332
  require "appsignal/integrations/railtie" if defined?(::Rails)
327
333
  require "appsignal/transaction"
328
334
  require "appsignal/version"
329
- require "appsignal/rack/abstract_middleware"
330
- require "appsignal/rack/generic_instrumentation"
331
- require "appsignal/rack/event_handler"
332
335
  require "appsignal/transmitter"
333
336
  require "appsignal/heartbeat"
data/spec/.rubocop.yml CHANGED
@@ -3,5 +3,5 @@ inherit_from: ../.rubocop.yml
3
3
  Metrics/BlockLength:
4
4
  Enabled: false
5
5
 
6
- # Metrics/LineLength:
6
+ # Layout/LineLength:
7
7
  # Max: 100
@@ -1320,7 +1320,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
1320
1320
  end
1321
1321
 
1322
1322
  it "transmits path data in report" do
1323
- mode = ENV["RUNNING_IN_CI"] ? "40775" : "40755"
1323
+ mode = "40755"
1324
1324
  expect(received_report["paths"]["root_path"]).to eq(
1325
1325
  "path" => root_path,
1326
1326
  "exists" => true,
@@ -155,7 +155,7 @@ describe Appsignal::CLI::Install do
155
155
  end
156
156
 
157
157
  it "requires an application name" do
158
- expect(output.scan(/Enter application name:/).length).to eq(2)
158
+ expect(output.scan("Enter application name:").length).to eq(2)
159
159
  end
160
160
  end
161
161
 
@@ -184,7 +184,7 @@ describe Appsignal::CLI::Install do
184
184
  run
185
185
 
186
186
  expect(output).to_not include "Adding AppSignal integration to Capfile"
187
- expect(File.read(capfile).scan(/appsignal/).count).to eq(1)
187
+ expect(File.read(capfile).scan("appsignal").count).to eq(1)
188
188
  end
189
189
  end
190
190
 
@@ -351,7 +351,7 @@ describe Appsignal::CLI::Install do
351
351
  choose_environment_config
352
352
  run
353
353
 
354
- expect(output.scan(/Choose app's display name:/).length).to eq(2)
354
+ expect(output.scan("Choose app's display name:").length).to eq(2)
355
355
  end
356
356
 
357
357
  context "with configuration using environment variables" do
@@ -165,6 +165,7 @@ describe Appsignal::Config do
165
165
  :enable_statsd => true,
166
166
  :enable_nginx_metrics => false,
167
167
  :enable_rails_error_reporter => true,
168
+ :enable_rake_performance_instrumentation => false,
168
169
  :endpoint => "https://push.appsignal.com",
169
170
  :files_world_accessible => true,
170
171
  :filter_metadata => [],
@@ -385,6 +386,8 @@ describe Appsignal::Config do
385
386
 
386
387
  context "without the selected env" do
387
388
  let(:config) { project_fixture_config("nonsense") }
389
+ let(:log_stream) { std_stream }
390
+ let(:log) { log_contents(log_stream) }
388
391
 
389
392
  it "is not valid or active" do
390
393
  expect(config.valid?).to be_falsy
@@ -392,11 +395,11 @@ describe Appsignal::Config do
392
395
  end
393
396
 
394
397
  it "logs an error" do
395
- expect_any_instance_of(Logger).to receive(:error).once
396
- .with("Not loading from config file: config for 'nonsense' not found")
397
- expect_any_instance_of(Logger).to receive(:error).once
398
- .with("Push API key not set after loading config")
399
- config
398
+ use_logger_with(log_stream) { config }
399
+ expect(log)
400
+ .to contains_log(:error, "Not loading from config file: config for 'nonsense' not found")
401
+ expect(log)
402
+ .to contains_log(:error, "Push API key not set after loading config")
400
403
  end
401
404
  end
402
405
  end
@@ -32,56 +32,53 @@ describe Appsignal::Demo do
32
32
  end
33
33
 
34
34
  describe ".create_example_error_request" do
35
- let!(:error_transaction) { http_request_transaction }
36
- let(:config) { project_fixture_config("production") }
37
- before do
38
- Appsignal.config = config
39
- expect(Appsignal::Transaction).to receive(:new).with(
40
- kind_of(String),
41
- Appsignal::Transaction::HTTP_REQUEST,
42
- kind_of(::Rack::Request),
43
- kind_of(Hash)
44
- ).and_return(error_transaction)
45
- end
46
- subject { described_class.send(:create_example_error_request) }
35
+ before { start_agent }
36
+ around { |example| keep_transactions { example.run } }
47
37
 
48
38
  it "sets an error" do
49
- expect(error_transaction).to receive(:set_error).with(kind_of(described_class::TestError))
50
- expect(error_transaction).to receive(:set_metadata).with("path", "/hello")
51
- expect(error_transaction).to receive(:set_metadata).with("method", "GET")
52
- expect(error_transaction).to receive(:set_metadata).with("demo_sample", "true")
53
- expect(error_transaction).to receive(:complete)
54
- subject
39
+ described_class.send(:create_example_error_request)
40
+
41
+ transaction = last_transaction
42
+ expect(transaction).to have_id
43
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
44
+ expect(transaction).to have_action("DemoController#hello")
45
+ expect(transaction).to have_error(
46
+ "Appsignal::Demo::TestError",
47
+ "Hello world! This is an error used for demonstration purposes."
48
+ )
49
+ expect(transaction).to include_metadata(
50
+ "path" => "/hello",
51
+ "method" => "GET",
52
+ "demo_sample" => "true"
53
+ )
54
+ expect(transaction).to be_completed
55
55
  end
56
56
  end
57
57
 
58
58
  describe ".create_example_performance_request" do
59
- let!(:performance_transaction) { http_request_transaction }
60
- let(:config) { project_fixture_config("production") }
61
- before do
62
- Appsignal.config = config
63
- expect(Appsignal::Transaction).to receive(:new).with(
64
- kind_of(String),
65
- Appsignal::Transaction::HTTP_REQUEST,
66
- kind_of(::Rack::Request),
67
- kind_of(Hash)
68
- ).and_return(performance_transaction)
69
- end
70
- subject { described_class.send(:create_example_performance_request) }
59
+ before { start_agent }
60
+ around { |example| keep_transactions { example.run } }
71
61
 
72
62
  it "sends a performance sample" do
73
- expect(performance_transaction).to receive(:start_event)
74
- expect(performance_transaction).to receive(:finish_event).with(
75
- "action_view.render",
76
- "Render hello.html.erb",
77
- "<h1>Hello world!</h1>",
78
- Appsignal::EventFormatter::DEFAULT
63
+ described_class.send(:create_example_performance_request)
64
+
65
+ transaction = last_transaction
66
+ expect(transaction).to have_id
67
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
68
+ expect(transaction).to have_action("DemoController#hello")
69
+ expect(transaction).to_not have_error
70
+ expect(transaction).to include_metadata(
71
+ "path" => "/hello",
72
+ "method" => "GET",
73
+ "demo_sample" => "true"
74
+ )
75
+ expect(transaction).to include_event(
76
+ "name" => "action_view.render",
77
+ "title" => "Render hello.html.erb",
78
+ "body" => "<h1>Hello world!</h1>",
79
+ "body_format" => Appsignal::EventFormatter::DEFAULT
79
80
  )
80
- expect(performance_transaction).to receive(:set_metadata).with("path", "/hello")
81
- expect(performance_transaction).to receive(:set_metadata).with("method", "GET")
82
- expect(performance_transaction).to receive(:set_metadata).with("demo_sample", "true")
83
- expect(performance_transaction).to receive(:complete)
84
- subject
81
+ expect(transaction).to be_completed
85
82
  end
86
83
  end
87
84
  end