appsignal 3.9.2-java → 3.10.0-java

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.
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Appsignal
4
4
  module Helpers
5
- module Instrumentation # rubocop:disable Metrics/ModuleLength
5
+ module Instrumentation
6
6
  include Appsignal::Utils::StdoutAndLoggerMessage
7
7
 
8
8
  # Creates an AppSignal transaction for the given block.
@@ -195,6 +195,7 @@ module Appsignal
195
195
  # used to send the error.
196
196
  # @return [void]
197
197
  #
198
+ # @see Transaction#report_error
198
199
  # @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
199
200
  # Exception handling guide
200
201
  # @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
@@ -294,6 +295,7 @@ module Appsignal
294
295
  # @return [void]
295
296
  #
296
297
  # @see Transaction#set_error
298
+ # @see Transaction#report_error
297
299
  # @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
298
300
  # Exception handling guide
299
301
  # @since 0.6.6
@@ -334,6 +336,74 @@ module Appsignal
334
336
  alias :set_exception :set_error
335
337
  alias :add_exception :set_error
336
338
 
339
+ # Report an error.
340
+ #
341
+ # If a transaction is currently active, it will report the error on the
342
+ # current transaction. If no transaction is active, it will report the
343
+ # error on a new transaction.
344
+ #
345
+ # **Note**: If AppSignal is not active, no error is reported.
346
+ #
347
+ # **Note**: If the given exception argument is not an Exception subclass,
348
+ # it will not be reported.
349
+ #
350
+ # @example
351
+ # class SomeController < ApplicationController
352
+ # def create
353
+ # # Do something that breaks
354
+ # rescue => error
355
+ # Appsignal.report_error(error)
356
+ # end
357
+ # end
358
+ #
359
+ # @example Add more metadata to transaction
360
+ # Appsignal.report_error(error) do |transaction|
361
+ # transaction.set_namespace("my_namespace")
362
+ # transaction.set_action("my_action_name")
363
+ # transaction.set_params(:search_query => params[:search_query])
364
+ # transaction.set_tags(:key => "value")
365
+ # end
366
+ #
367
+ # @param exception [Exception] The error to add to the current
368
+ # transaction.
369
+ # @yield [transaction] yields block to allow modification of the
370
+ # transaction.
371
+ # @yieldparam transaction [Transaction] yields the AppSignal transaction
372
+ # used to report the error.
373
+ # @return [void]
374
+ #
375
+ # @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
376
+ # Exception handling guide
377
+ # @since 3.10.0
378
+ def report_error(exception)
379
+ unless exception.is_a?(Exception)
380
+ internal_logger.error "Appsignal.report_error: Cannot set error. " \
381
+ "The given value is not an exception: #{exception.inspect}"
382
+ return
383
+ end
384
+ return unless active?
385
+
386
+ has_parent_transaction = Appsignal::Transaction.current?
387
+ transaction =
388
+ if has_parent_transaction
389
+ Appsignal::Transaction.current
390
+ else
391
+ Appsignal::Transaction.new(
392
+ SecureRandom.uuid,
393
+ Appsignal::Transaction::HTTP_REQUEST,
394
+ Appsignal::Transaction::GenericRequest.new({})
395
+ )
396
+ end
397
+
398
+ transaction.set_error(exception)
399
+ yield transaction if block_given?
400
+
401
+ return if has_parent_transaction
402
+
403
+ transaction.complete
404
+ end
405
+ alias :report_exception :report_error
406
+
337
407
  # Set a custom action name for the current transaction.
338
408
  #
339
409
  # When using an integration such as the Rails or Sinatra AppSignal will
@@ -404,13 +474,44 @@ module Appsignal
404
474
  Appsignal::Transaction.current.set_namespace(namespace)
405
475
  end
406
476
 
477
+ # Set custom data on the current transaction.
478
+ #
479
+ # Add extra information about the request or background that cannot be
480
+ # expressed in tags, like nested data structures.
481
+ #
482
+ # When this method is called multiple times, it will overwrite the
483
+ # previously set value.
484
+ #
485
+ # @example
486
+ # Appsignal.set_custom_data(:user => { :locale => "en" })
487
+ # Appsignal.set_custom_data([
488
+ # "array with data",
489
+ # :options => { :verbose => true }
490
+ # ])
491
+ #
492
+ # @since 3.10.0
493
+ # @see Transaction#set_custom_data
494
+ # @see https://docs.appsignal.com/guides/custom-data/sample-data.html
495
+ # Sample data guide
496
+ # @param data [Hash/Array]
497
+ # @return [void]
498
+ def set_custom_data(data)
499
+ return unless active?
500
+ return unless Appsignal::Transaction.current?
501
+
502
+ transaction = Appsignal::Transaction.current
503
+ transaction.set_custom_data(data)
504
+ end
505
+
407
506
  # Set tags on the current transaction.
408
507
  #
409
508
  # Tags are extra bits of information that are added to transaction and
410
509
  # appear on sample details pages on AppSignal.com.
411
510
  #
511
+ # When this method is called multiple times, it will merge the tags.
512
+ #
412
513
  # @example
413
- # Appsignal.tag_request(:locale => "en")
514
+ # Appsignal.tag_request(:locale => "en", :user_id => 1)
414
515
  # Appsignal.tag_request("locale" => "en")
415
516
  # Appsignal.tag_request("user_id" => 1)
416
517
  #
@@ -445,6 +546,67 @@ module Appsignal
445
546
  transaction.set_tags(tags)
446
547
  end
447
548
  alias :tag_job :tag_request
549
+ alias :set_tags :tag_request
550
+
551
+ # Set parameters on the current transaction.
552
+ #
553
+ # Parameters are automatically set by most of our integrations. It should
554
+ # not be necessary to call this method unless you want to report
555
+ # different parameters.
556
+ #
557
+ # To filter parameters, see our parameter filtering guide.
558
+ #
559
+ # When this method is called multiple times, it will overwrite the
560
+ # previously set value.
561
+ #
562
+ # When no parameters are set this way, the transaction will look for
563
+ # parameters in its request environment.
564
+ #
565
+ # A block can be given to this method to defer the fetching and parsing
566
+ # of the parameters until and only when the transaction is sampled.
567
+ #
568
+ # When both the `params` and a block is given to this method, the
569
+ # `params` argument is leading and the block will _not_ be called.
570
+ #
571
+ # @example Set parameters
572
+ # Appsignal.set_params("param1" => "value1")
573
+ #
574
+ # @example Calling `set_params` multiple times will only keep the last call
575
+ # Appsignal.set_params("param1" => "value1")
576
+ # Appsignal.set_params("param2" => "value2")
577
+ # # The parameters are: { "param2" => "value2" }
578
+ #
579
+ # @example Calling `set_params` with a block
580
+ # Appsignal.set_params do
581
+ # # Some slow code to parse parameters
582
+ # JSON.parse('{"param1": "value1"}')
583
+ # end
584
+ # # The parameters are: { "param1" => "value1" }
585
+ #
586
+ # @example Calling `set_params` with a parameter and a block
587
+ # Appsignal.set_params("argument" => "argument value") do
588
+ # # Some slow code to parse parameters
589
+ # JSON.parse('{"param1": "value1"}')
590
+ # end
591
+ # # The parameters are: { "argument" => "argument value" }
592
+ #
593
+ # @since 3.10.0
594
+ # @param params [Hash] The parameters to set on the transaction.
595
+ # @yield This block is called when the transaction is sampled. The block's
596
+ # return value will become the new parameters.
597
+ # @see https://docs.appsignal.com/guides/custom-data/sample-data.html
598
+ # Sample data guide
599
+ # @see https://docs.appsignal.com/guides/filter-data/filter-parameters.html
600
+ # Parameter filtering guide
601
+ # @see Transaction#set_params
602
+ # @return [void]
603
+ def set_params(params = nil, &block)
604
+ return unless active?
605
+ return unless Appsignal::Transaction.current?
606
+
607
+ transaction = Appsignal::Transaction.current
608
+ transaction.set_params(params, &block)
609
+ end
448
610
 
449
611
  # Add breadcrumbs to the transaction.
450
612
  #
@@ -62,12 +62,7 @@ module Appsignal
62
62
  end
63
63
 
64
64
  if transaction
65
- transaction.set_params_if_nil(
66
- Appsignal::Utils::HashSanitizer.sanitize(
67
- job["arguments"],
68
- Appsignal.config[:filter_parameters]
69
- )
70
- )
65
+ transaction.set_params_if_nil(job["arguments"])
71
66
 
72
67
  transaction_tags = ActiveJobHelpers.transaction_tags_for(job)
73
68
  transaction_tags["active_job_id"] = job["job_id"]
@@ -1,55 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "appsignal"
4
+ require "appsignal/rack/grape_middleware"
5
+
6
+ Appsignal.internal_logger.debug("Loading Grape integration")
7
+
3
8
  module Appsignal
4
- # @todo Move to sub-namespace
5
9
  # @api private
6
10
  module Grape
7
- class Middleware < ::Grape::Middleware::Base
8
- def call(env)
9
- if Appsignal.active?
10
- call_with_appsignal_monitoring(env)
11
- else
12
- app.call(env)
13
- end
14
- end
15
-
16
- def call_with_appsignal_monitoring(env)
17
- request = ::Rack::Request.new(env)
18
- transaction = Appsignal::Transaction.create(
19
- SecureRandom.uuid,
20
- Appsignal::Transaction::HTTP_REQUEST,
21
- request
22
- )
23
- begin
24
- app.call(env)
25
- rescue Exception => error # rubocop:disable Lint/RescueException
26
- # Do not set error if "grape.skip_appsignal_error" is set to `true`.
27
- transaction.set_error(error) unless env["grape.skip_appsignal_error"]
28
- raise error
29
- ensure
30
- request_method = request.request_method.to_s.upcase
31
- path = request.path # Path without namespaces
32
- endpoint = env["api.endpoint"]
33
-
34
- if endpoint&.options
35
- options = endpoint.options
36
- request_method = options[:method].first.to_s.upcase
37
- klass = options[:for]
38
- namespace = endpoint.namespace
39
- namespace = "" if namespace == "/"
40
-
41
- path = options[:path].first.to_s
42
- path = "/#{path}" if path[0] != "/"
43
- path = "#{namespace}#{path}"
44
-
45
- transaction.set_action_if_nil("#{request_method}::#{klass}##{path}")
46
- end
47
-
48
- transaction.set_http_or_background_queue_start
49
- transaction.set_metadata("path", path)
50
- transaction.set_metadata("method", request_method)
51
- Appsignal::Transaction.complete_current!
52
- end
11
+ # Alias constants that have moved with a warning message that points to the
12
+ # place to update the reference.
13
+ def self.const_missing(name)
14
+ case name
15
+ when :Middleware
16
+ callers = caller
17
+ Appsignal::Utils::StdoutAndLoggerMessage.warning \
18
+ "The constant Appsignal::Grape::Middleware has been deprecated. " \
19
+ "Please update the constant name to " \
20
+ "Appsignal::Rack::GrapeMiddleware in the following file to " \
21
+ "remove this message.\n#{callers.first}"
22
+ Appsignal::Rack::GrapeMiddleware
23
+ else
24
+ super
53
25
  end
54
26
  end
55
27
  end
@@ -11,13 +11,14 @@ module Appsignal
11
11
  Appsignal.internal_logger.debug("Loading Hanami integration")
12
12
 
13
13
  hanami_app_config = ::Hanami.app.config
14
- Appsignal.config = Appsignal::Config.new(
15
- hanami_app_config.root || Dir.pwd,
16
- hanami_app_config.env
17
- )
18
14
 
19
- Appsignal.start_logger
20
- Appsignal.start
15
+ unless Appsignal.active?
16
+ Appsignal.config = Appsignal::Config.new(
17
+ hanami_app_config.root || Dir.pwd,
18
+ hanami_app_config.env
19
+ )
20
+ Appsignal.start
21
+ end
21
22
 
22
23
  return unless Appsignal.active?
23
24
 
@@ -44,4 +45,4 @@ module Appsignal
44
45
  end
45
46
  end
46
47
 
47
- Appsignal::Integrations::HanamiPlugin.init
48
+ Appsignal::Integrations::HanamiPlugin.init unless Appsignal.testing?
@@ -1,79 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "appsignal"
4
+ require "appsignal/rack/sinatra_instrumentation"
4
5
 
5
6
  module Appsignal
6
7
  module Integrations
7
8
  # @api private
8
9
  module PadrinoPlugin
9
10
  def self.init
10
- Appsignal.internal_logger.debug("Loading Padrino (#{Padrino::VERSION}) integration")
11
+ Padrino::Application.prepend Appsignal::Integrations::PadrinoIntegration
11
12
 
12
- root = Padrino.mounted_root
13
- Appsignal.config = Appsignal::Config.new(root, Padrino.env)
13
+ Padrino.before_load do
14
+ Appsignal.internal_logger.debug("Loading Padrino (#{Padrino::VERSION}) integration")
14
15
 
15
- Appsignal.start_logger
16
- Appsignal.start
16
+ unless Appsignal.active?
17
+ root = Padrino.mounted_root
18
+ Appsignal.config = Appsignal::Config.new(root, Padrino.env)
19
+ Appsignal.start
20
+ end
21
+
22
+ next unless Appsignal.active?
23
+
24
+ Padrino.use ::Rack::Events, [Appsignal::Rack::EventHandler.new]
25
+ Padrino.use Appsignal::Rack::SinatraBaseInstrumentation,
26
+ :instrument_event_name => "process_action.padrino"
27
+ end
17
28
  end
18
29
  end
19
30
  end
20
31
  end
21
32
 
22
- module Appsignal::Integrations::PadrinoIntegration
23
- def route!(base = settings, pass_block = nil)
24
- return super if !Appsignal.active? || env["sinatra.static_file"]
33
+ module Appsignal
34
+ module Integrations
35
+ # @api private
36
+ module PadrinoIntegration
37
+ def route!(base = settings, pass_block = nil)
38
+ return super if !Appsignal.active? || env["sinatra.static_file"]
25
39
 
26
- transaction = Appsignal::Transaction.create(
27
- SecureRandom.uuid,
28
- Appsignal::Transaction::HTTP_REQUEST,
29
- request
30
- )
31
- begin
32
- Appsignal.instrument("process_action.padrino") do
33
- super
40
+ begin
41
+ super
42
+ ensure
43
+ transaction = Appsignal::Transaction.current
44
+ transaction.set_action_if_nil(get_payload_action(request))
45
+ end
34
46
  end
35
- rescue Exception => error # rubocop:disable Lint/RescueException
36
- transaction.set_error(error)
37
- raise error
38
- ensure
39
- transaction.set_action_if_nil(get_payload_action(request))
40
- transaction.set_metadata("path", request.path)
41
- transaction.set_metadata("method", request.request_method)
42
- transaction.set_http_or_background_queue_start
43
- Appsignal::Transaction.complete_current!
44
- end
45
- end
46
47
 
47
- private
48
+ private
48
49
 
49
- def get_payload_action(request)
50
- # Short-circut is there's no request object to obtain information from
51
- return settings.name.to_s unless request
50
+ def get_payload_action(request)
51
+ # Short-circuit is there's no request object to obtain information from
52
+ return settings.name.to_s unless request
52
53
 
53
- # Newer versions expose the action / controller on the request class.
54
- # Newer versions also still expose a route_obj so we must prioritize the
55
- # action/fullpath methods.
56
- # The `request.action` and `request.controller` values are `nil` when a
57
- # endpoint is not found, `""` if not specified by the user.
58
- controller_name = request.controller if request.respond_to?(:controller)
59
- action_name = request.action if request.respond_to?(:action)
60
- action_name ||= ""
54
+ # Newer versions expose the action / controller on the request class.
55
+ # Newer versions also still expose a route_obj so we must prioritize the
56
+ # action/fullpath methods.
57
+ # The `request.action` and `request.controller` values are `nil` when a
58
+ # endpoint is not found, `""` if not specified by the user.
59
+ controller_name = request.controller if request.respond_to?(:controller)
60
+ action_name = request.action if request.respond_to?(:action)
61
+ action_name ||= ""
61
62
 
62
- return "#{settings.name}:#{controller_name}##{action_name}" unless action_name.empty?
63
+ return "#{settings.name}:#{controller_name}##{action_name}" unless action_name.empty?
63
64
 
64
- # Older versions of Padrino work with a route object
65
- if request.respond_to?(:route_obj) && request.route_obj
66
- return "#{settings.name}:#{request.route_obj.original_path}"
67
- end
65
+ # Older versions of Padrino work with a route object
66
+ if request.respond_to?(:route_obj) && request.route_obj
67
+ return "#{settings.name}:#{request.route_obj.original_path}"
68
+ end
68
69
 
69
- # Fall back to the application name if we haven't found an action name in
70
- # any previous methods.
71
- "#{settings.name}#unknown"
70
+ # Fall back to the application name if we haven't found an action name in
71
+ # any previous methods.
72
+ "#{settings.name}#unknown"
73
+ end
74
+ end
72
75
  end
73
76
  end
74
77
 
75
- Padrino::Application.prepend Appsignal::Integrations::PadrinoIntegration
76
-
77
- Padrino.after_load do
78
- Appsignal::Integrations::PadrinoPlugin.init
79
- end
78
+ Appsignal::Integrations::PadrinoPlugin.init
@@ -26,9 +26,6 @@ module Appsignal
26
26
  :log_path => Rails.root.join("log")
27
27
  )
28
28
 
29
- # Start logger
30
- Appsignal.start_logger
31
-
32
29
  app.middleware.insert(
33
30
  0,
34
31
  ::Rack::Events,
@@ -2,26 +2,60 @@
2
2
 
3
3
  module Appsignal
4
4
  module Integrations
5
+ # @api private
5
6
  module RakeIntegration
6
7
  def execute(*args)
7
- super
8
+ transaction =
9
+ if Appsignal.config[:enable_rake_performance_instrumentation]
10
+ Appsignal::Integrations::RakeIntegrationHelper.register_at_exit_hook
11
+ _appsignal_create_transaction
12
+ end
13
+
14
+ Appsignal.instrument "task.rake" do
15
+ super
16
+ end
8
17
  rescue Exception => error # rubocop:disable Lint/RescueException
9
- # Format given arguments and cast to hash if possible
10
- params, _ = args
11
- params = params.to_hash if params.respond_to?(:to_hash)
18
+ Appsignal::Integrations::RakeIntegrationHelper.register_at_exit_hook
19
+ transaction ||= _appsignal_create_transaction
20
+ transaction.set_error(error)
21
+ raise error
22
+ ensure
23
+ if transaction
24
+ # Format given arguments and cast to hash if possible
25
+ params, _ = args
26
+ params = params.to_hash if params.respond_to?(:to_hash)
27
+ transaction.set_params_if_nil(params)
28
+ transaction.set_action(name)
29
+ transaction.complete
30
+ end
31
+ end
12
32
 
13
- transaction = Appsignal::Transaction.create(
33
+ private
34
+
35
+ def _appsignal_create_transaction
36
+ Appsignal::Transaction.create(
14
37
  SecureRandom.uuid,
15
38
  Appsignal::Transaction::BACKGROUND_JOB,
16
- Appsignal::Transaction::GenericRequest.new(
17
- :params => params
18
- )
39
+ Appsignal::Transaction::GenericRequest.new({})
19
40
  )
20
- transaction.set_action(name)
21
- transaction.set_error(error)
22
- transaction.complete
41
+ end
42
+ end
43
+
44
+ # @api private
45
+ module RakeIntegrationHelper
46
+ # Register an `at_exit` hook when a task is executed. This will stop
47
+ # AppSignal when _all_ tasks are executed and Rake exits.
48
+ def self.register_at_exit_hook
49
+ return if @register_at_exit_hook
50
+
51
+ Kernel.at_exit(&method(:at_exit_hook))
52
+
53
+ @register_at_exit_hook = true
54
+ end
55
+
56
+ # The at_exit hook itself
57
+ def self.at_exit_hook
23
58
  Appsignal.stop("rake")
24
- raise error
25
59
  end
26
60
  end
27
61
  end
@@ -83,7 +83,7 @@ module Appsignal
83
83
  raise exception
84
84
  ensure
85
85
  if transaction
86
- transaction.set_params_if_nil(filtered_arguments(item))
86
+ transaction.set_params_if_nil(parse_arguments(item))
87
87
  transaction.set_http_or_background_queue_start
88
88
  Appsignal::Transaction.complete_current! unless exception
89
89
 
@@ -115,16 +115,6 @@ module Appsignal
115
115
  "#{sidekiq_action_name}#perform"
116
116
  end
117
117
 
118
- def filtered_arguments(job)
119
- arguments = parse_arguments(job)
120
- return unless arguments
121
-
122
- Appsignal::Utils::HashSanitizer.sanitize(
123
- arguments,
124
- Appsignal.config[:filter_parameters]
125
- )
126
- end
127
-
128
118
  def formatted_metadata(item)
129
119
  {}.tap do |hash|
130
120
  (item || {}).each do |key, value|
@@ -12,7 +12,6 @@ unless Appsignal.active?
12
12
  app_settings.environment
13
13
  )
14
14
 
15
- Appsignal.start_logger
16
15
  Appsignal.start
17
16
  end
18
17
 
@@ -5,20 +5,26 @@ module Appsignal
5
5
  # @api private
6
6
  module WebmachineIntegration
7
7
  def run
8
- transaction = Appsignal::Transaction.create(
9
- SecureRandom.uuid,
10
- Appsignal::Transaction::HTTP_REQUEST,
11
- request,
12
- :params_method => :query
13
- )
14
-
15
- transaction.set_action_if_nil("#{resource.class.name}##{request.method}")
8
+ has_parent_transaction = Appsignal::Transaction.current?
9
+ transaction =
10
+ if has_parent_transaction
11
+ Appsignal::Transaction.current
12
+ else
13
+ Appsignal::Transaction.create(
14
+ SecureRandom.uuid,
15
+ Appsignal::Transaction::HTTP_REQUEST,
16
+ request
17
+ )
18
+ end
16
19
 
17
20
  Appsignal.instrument("process_action.webmachine") do
18
21
  super
19
22
  end
23
+ ensure
24
+ transaction.set_action_if_nil("#{resource.class.name}##{request.method}")
25
+ transaction.set_params_if_nil(request.query)
20
26
 
21
- Appsignal::Transaction.complete_current!
27
+ Appsignal::Transaction.complete_current! unless has_parent_transaction
22
28
  end
23
29
 
24
30
  private
@@ -25,6 +25,11 @@ module Appsignal
25
25
  Appsignal.internal_logger.debug("Initializing GVL probe")
26
26
  @appsignal = appsignal
27
27
  @gvl_tools = gvl_tools
28
+
29
+ # Store the process name and ID at initialization time
30
+ # to avoid picking up changes to the process name at runtime
31
+ @process_name = File.basename($PROGRAM_NAME).split.first || "[unknown process]"
32
+ @process_id = Process.pid
28
33
  end
29
34
 
30
35
  def call
@@ -39,13 +44,30 @@ module Appsignal
39
44
  gauge_delta :gvl_global_timer, monotonic_time_ns do |time_delta_ns|
40
45
  if time_delta_ns > 0
41
46
  time_delta_ms = time_delta_ns / 1_000_000
42
- set_gauge_with_hostname("gvl_global_timer", time_delta_ms)
47
+ set_gauges_with_hostname_and_process(
48
+ "gvl_global_timer",
49
+ time_delta_ms
50
+ )
43
51
  end
44
52
  end
45
53
  end
46
54
 
47
55
  def probe_waiting_threads
48
- set_gauge_with_hostname("gvl_waiting_threads", @gvl_tools::WaitingThreads.count)
56
+ set_gauges_with_hostname_and_process(
57
+ "gvl_waiting_threads",
58
+ @gvl_tools::WaitingThreads.count
59
+ )
60
+ end
61
+
62
+ def set_gauges_with_hostname_and_process(name, value)
63
+ set_gauge_with_hostname(name, value, {
64
+ :process_name => @process_name,
65
+ :process_id => @process_id
66
+ })
67
+
68
+ # Also set the gauge without the process name and ID for
69
+ # compatibility with existing automated dashboards
70
+ set_gauge_with_hostname(name, value)
49
71
  end
50
72
  end
51
73
  end
@@ -47,7 +47,7 @@ module Appsignal
47
47
  # @api private
48
48
  def self.dependencies_present?
49
49
  return true if sidekiq7_and_greater?
50
- return unless defined?(::Redis::VERSION) # Sidekiq <= 6
50
+ return false unless defined?(::Redis::VERSION) # Sidekiq <= 6
51
51
 
52
52
  Gem::Version.new(::Redis::VERSION) >= Gem::Version.new("3.3.5")
53
53
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- module Probes # rubocop:disable Metrics/ModuleLength
4
+ module Probes
5
5
  ITERATION_IN_SECONDS = 60
6
6
 
7
7
  class ProbeCollection