appsignal 3.9.2-java → 3.9.3-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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +3135 -0
- data/.rubocop.yml +28 -20
- data/.rubocop_todo.yml +7 -33
- data/CHANGELOG.md +38 -0
- data/Rakefile +79 -64
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +109 -179
- data/ext/base.rb +1 -1
- data/gemfiles/hanami-2.1.gemfile +7 -0
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +1 -1
- data/lib/appsignal/demo.rb +0 -1
- data/lib/appsignal/environment.rb +5 -1
- data/lib/appsignal/extension/jruby.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +1 -1
- data/lib/appsignal/integrations/grape.rb +19 -47
- data/lib/appsignal/integrations/hanami.rb +8 -7
- data/lib/appsignal/integrations/padrino.rb +46 -43
- data/lib/appsignal/integrations/railtie.rb +0 -3
- data/lib/appsignal/integrations/sinatra.rb +0 -1
- data/lib/appsignal/probes/gvl.rb +24 -2
- data/lib/appsignal/probes/sidekiq.rb +1 -1
- data/lib/appsignal/probes.rb +1 -1
- data/lib/appsignal/rack/abstract_middleware.rb +62 -28
- data/lib/appsignal/rack/event_handler.rb +12 -3
- data/lib/appsignal/rack/grape_middleware.rb +40 -0
- data/lib/appsignal/rack/hanami_middleware.rb +1 -11
- data/lib/appsignal/rack/rails_instrumentation.rb +14 -55
- data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +34 -33
- data/spec/.rubocop.yml +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
- data/spec/lib/appsignal/cli/install_spec.rb +3 -3
- data/spec/lib/appsignal/config_spec.rb +7 -5
- data/spec/lib/appsignal/demo_spec.rb +38 -41
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
- data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
- data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
- data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
- data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
- data/spec/lib/appsignal/hooks/rake_spec.rb +9 -19
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
- data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
- data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
- data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
- data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
- data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
- data/spec/lib/appsignal/integrations/padrino_spec.rb +47 -70
- data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
- data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -1
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +28 -39
- data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
- data/spec/lib/appsignal/probes_spec.rb +7 -4
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +215 -106
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +2 -12
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
- data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +68 -86
- data/spec/lib/appsignal/transaction_spec.rb +76 -90
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
- data/spec/lib/appsignal_spec.rb +363 -342
- data/spec/support/helpers/dependency_helper.rb +6 -1
- data/spec/support/helpers/std_streams_helper.rb +1 -1
- data/spec/support/helpers/transaction_helpers.rb +8 -0
- data/spec/support/matchers/transaction.rb +185 -0
- data/spec/support/mocks/dummy_app.rb +20 -0
- data/spec/support/shared_examples/instrument.rb +17 -12
- data/spec/support/testing.rb +18 -9
- metadata +15 -10
- data/.semaphore/semaphore.yml +0 -2347
- data/script/lint_git +0 -22
- data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
- data/spec/support/matchers/be_completed.rb +0 -5
- /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
data/lib/appsignal/probes/gvl.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
data/lib/appsignal/probes.rb
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
require "rack"
|
|
4
4
|
|
|
5
5
|
module Appsignal
|
|
6
|
-
# @api private
|
|
7
6
|
module Rack
|
|
7
|
+
# @api private
|
|
8
8
|
class AbstractMiddleware
|
|
9
|
+
DEFAULT_ERROR_REPORTING = :default
|
|
10
|
+
|
|
9
11
|
def initialize(app, options = {})
|
|
10
12
|
Appsignal.internal_logger.debug "Initializing #{self.class}"
|
|
11
13
|
@app = app
|
|
@@ -13,6 +15,7 @@ module Appsignal
|
|
|
13
15
|
@request_class = options.fetch(:request_class, ::Rack::Request)
|
|
14
16
|
@params_method = options.fetch(:params_method, :params)
|
|
15
17
|
@instrument_span_name = options.fetch(:instrument_span_name, "process.abstract")
|
|
18
|
+
@report_errors = options.fetch(:report_errors, DEFAULT_ERROR_REPORTING)
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
def call(env)
|
|
@@ -32,15 +35,31 @@ module Appsignal
|
|
|
32
35
|
)
|
|
33
36
|
end
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
if wrapped_instrumentation
|
|
37
|
-
instrument_wrapped_request(request, transaction)
|
|
38
|
-
else
|
|
38
|
+
unless wrapped_instrumentation
|
|
39
39
|
# Set transaction on the request environment so other nested
|
|
40
40
|
# middleware can detect if there is parent instrumentation
|
|
41
41
|
# middleware active.
|
|
42
42
|
env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = transaction
|
|
43
|
-
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
add_transaction_metadata_before(transaction, request)
|
|
47
|
+
# Report errors if the :report_errors option is set to true or when
|
|
48
|
+
# there is no parent instrumentation that can rescue and report the error.
|
|
49
|
+
if @report_errors || !wrapped_instrumentation
|
|
50
|
+
instrument_app_call_with_exception_handling(
|
|
51
|
+
request.env,
|
|
52
|
+
transaction,
|
|
53
|
+
wrapped_instrumentation
|
|
54
|
+
)
|
|
55
|
+
else
|
|
56
|
+
instrument_app_call(request.env)
|
|
57
|
+
end
|
|
58
|
+
ensure
|
|
59
|
+
add_transaction_metadata_after(transaction, request)
|
|
60
|
+
|
|
61
|
+
# Complete transaction because this is the top instrumentation middleware.
|
|
62
|
+
Appsignal::Transaction.complete_current! unless wrapped_instrumentation
|
|
44
63
|
end
|
|
45
64
|
else
|
|
46
65
|
@app.call(env)
|
|
@@ -56,35 +75,40 @@ module Appsignal
|
|
|
56
75
|
# Either another {GenericInstrumentation} or {EventHandler} is higher in
|
|
57
76
|
# the stack and will report the exception and complete the transaction.
|
|
58
77
|
#
|
|
59
|
-
# @see {#
|
|
60
|
-
def
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
78
|
+
# @see {#instrument_app_call_with_exception_handling}
|
|
79
|
+
def instrument_app_call(env)
|
|
80
|
+
if @instrument_span_name
|
|
81
|
+
Appsignal.instrument(@instrument_span_name) do
|
|
82
|
+
@app.call(env)
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
@app.call(env)
|
|
86
|
+
end
|
|
64
87
|
end
|
|
65
88
|
|
|
66
89
|
# Instrument the request fully. This is used by the top instrumentation
|
|
67
90
|
# middleware in the middleware stack. Unlike
|
|
68
|
-
# {#
|
|
91
|
+
# {#instrument_app_call} this will report any exceptions being
|
|
69
92
|
# raised.
|
|
70
93
|
#
|
|
71
|
-
# @see {#
|
|
72
|
-
def
|
|
73
|
-
instrument_app_call(
|
|
94
|
+
# @see {#instrument_app_call}
|
|
95
|
+
def instrument_app_call_with_exception_handling(env, transaction, wrapped_instrumentation)
|
|
96
|
+
instrument_app_call(env)
|
|
74
97
|
rescue Exception => error # rubocop:disable Lint/RescueException
|
|
75
|
-
|
|
98
|
+
report_errors =
|
|
99
|
+
if @report_errors == DEFAULT_ERROR_REPORTING
|
|
100
|
+
# If there's no parent transaction, report the error
|
|
101
|
+
!wrapped_instrumentation
|
|
102
|
+
elsif @report_errors.respond_to?(:call)
|
|
103
|
+
# If the @report_errors option is callable, call it with the
|
|
104
|
+
# request environment so it can determine if the error needs to be
|
|
105
|
+
# reported.
|
|
106
|
+
@report_errors.call(env)
|
|
107
|
+
else
|
|
108
|
+
@report_errors
|
|
109
|
+
end
|
|
110
|
+
transaction.set_error(error) if report_errors
|
|
76
111
|
raise error
|
|
77
|
-
ensure
|
|
78
|
-
add_transaction_metadata_after(transaction, request)
|
|
79
|
-
|
|
80
|
-
# Complete transaction because this is the top instrumentation middleware.
|
|
81
|
-
Appsignal::Transaction.complete_current!
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def instrument_app_call(env)
|
|
85
|
-
Appsignal.instrument(@instrument_span_name) do
|
|
86
|
-
@app.call(env)
|
|
87
|
-
end
|
|
88
112
|
end
|
|
89
113
|
|
|
90
114
|
# Add metadata to the transaction based on the request environment.
|
|
@@ -101,7 +125,10 @@ module Appsignal
|
|
|
101
125
|
request.env["appsignal.route"] || request.env["appsignal.action"]
|
|
102
126
|
transaction.set_action_if_nil(default_action)
|
|
103
127
|
transaction.set_metadata("path", request.path)
|
|
104
|
-
|
|
128
|
+
|
|
129
|
+
request_method = request_method_for(request)
|
|
130
|
+
transaction.set_metadata("method", request_method) if request_method
|
|
131
|
+
|
|
105
132
|
transaction.set_params_if_nil(params_for(request))
|
|
106
133
|
transaction.set_http_or_background_queue_start
|
|
107
134
|
end
|
|
@@ -118,6 +145,13 @@ module Appsignal
|
|
|
118
145
|
nil
|
|
119
146
|
end
|
|
120
147
|
|
|
148
|
+
def request_method_for(request)
|
|
149
|
+
request.request_method
|
|
150
|
+
rescue => error
|
|
151
|
+
Appsignal.internal_logger.error("Unable to report HTTP request method: '#{error}'")
|
|
152
|
+
nil
|
|
153
|
+
end
|
|
154
|
+
|
|
121
155
|
def request_for(env)
|
|
122
156
|
@request_class.new(env)
|
|
123
157
|
end
|
|
@@ -4,8 +4,10 @@ module Appsignal
|
|
|
4
4
|
module Rack
|
|
5
5
|
APPSIGNAL_TRANSACTION = "appsignal.transaction"
|
|
6
6
|
APPSIGNAL_EVENT_HANDLER_ID = "appsignal.event_handler_id"
|
|
7
|
+
APPSIGNAL_EVENT_HANDLER_HAS_ERROR = "appsignal.event_handler.error"
|
|
7
8
|
RACK_AFTER_REPLY = "rack.after_reply"
|
|
8
9
|
|
|
10
|
+
# @api private
|
|
9
11
|
class EventHandler
|
|
10
12
|
include ::Rack::Events::Abstract
|
|
11
13
|
|
|
@@ -70,6 +72,7 @@ module Appsignal
|
|
|
70
72
|
transaction = request.env[APPSIGNAL_TRANSACTION]
|
|
71
73
|
return unless transaction
|
|
72
74
|
|
|
75
|
+
request.env[APPSIGNAL_EVENT_HANDLER_HAS_ERROR] = true
|
|
73
76
|
transaction.set_error(error)
|
|
74
77
|
end
|
|
75
78
|
end
|
|
@@ -83,12 +86,18 @@ module Appsignal
|
|
|
83
86
|
self.class.safe_execution("Appsignal::Rack::EventHandler#on_finish") do
|
|
84
87
|
transaction.finish_event("process_request.rack", "", "")
|
|
85
88
|
transaction.set_http_or_background_queue_start
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
response_status =
|
|
90
|
+
if response
|
|
91
|
+
response.status
|
|
92
|
+
elsif request.env[APPSIGNAL_EVENT_HANDLER_HAS_ERROR] == true
|
|
93
|
+
500
|
|
94
|
+
end
|
|
95
|
+
if response_status
|
|
96
|
+
transaction.set_tags(:response_status => response_status)
|
|
88
97
|
Appsignal.increment_counter(
|
|
89
98
|
:response_status,
|
|
90
99
|
1,
|
|
91
|
-
:status =>
|
|
100
|
+
:status => response_status,
|
|
92
101
|
:namespace => format_namespace(transaction.namespace)
|
|
93
102
|
)
|
|
94
103
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appsignal
|
|
4
|
+
module Rack
|
|
5
|
+
# @api private
|
|
6
|
+
class GrapeMiddleware < Appsignal::Rack::AbstractMiddleware
|
|
7
|
+
def initialize(app, options = {})
|
|
8
|
+
options[:instrument_span_name] = "process_request.grape"
|
|
9
|
+
options[:report_errors] = lambda { |env| !env["grape.skip_appsignal_error"] }
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def add_transaction_metadata_after(transaction, request)
|
|
16
|
+
endpoint = request.env["api.endpoint"]
|
|
17
|
+
unless endpoint&.options
|
|
18
|
+
super
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
options = endpoint.options
|
|
23
|
+
request_method = options[:method].first.to_s.upcase
|
|
24
|
+
klass = options[:for]
|
|
25
|
+
namespace = endpoint.namespace
|
|
26
|
+
namespace = "" if namespace == "/"
|
|
27
|
+
|
|
28
|
+
path = options[:path].first.to_s
|
|
29
|
+
path = "/#{path}" if path[0] != "/"
|
|
30
|
+
path = "#{namespace}#{path}"
|
|
31
|
+
|
|
32
|
+
transaction.set_action_if_nil("#{request_method}::#{klass}##{path}")
|
|
33
|
+
|
|
34
|
+
super
|
|
35
|
+
|
|
36
|
+
transaction.set_metadata("path", path)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -5,7 +5,6 @@ module Appsignal
|
|
|
5
5
|
# @api private
|
|
6
6
|
class HanamiMiddleware < AbstractMiddleware
|
|
7
7
|
def initialize(app, options = {})
|
|
8
|
-
options[:request_class] ||= ::Hanami::Action::Request
|
|
9
8
|
options[:params_method] ||= :params
|
|
10
9
|
options[:instrument_span_name] ||= "process_action.hanami"
|
|
11
10
|
super
|
|
@@ -14,16 +13,7 @@ module Appsignal
|
|
|
14
13
|
private
|
|
15
14
|
|
|
16
15
|
def params_for(request)
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def request_for(env)
|
|
21
|
-
params = ::Hanami::Action.params_class.new(env)
|
|
22
|
-
@request_class.new(
|
|
23
|
-
:env => env,
|
|
24
|
-
:params => params,
|
|
25
|
-
:sessions_enabled => true
|
|
26
|
-
)
|
|
16
|
+
::Hanami::Action.params_class.new(request.env).to_h
|
|
27
17
|
end
|
|
28
18
|
end
|
|
29
19
|
end
|
|
@@ -3,68 +3,27 @@
|
|
|
3
3
|
require "rack"
|
|
4
4
|
|
|
5
5
|
module Appsignal
|
|
6
|
-
# @api private
|
|
7
6
|
module Rack
|
|
8
|
-
|
|
7
|
+
# @api private
|
|
8
|
+
class RailsInstrumentation < Appsignal::Rack::AbstractMiddleware
|
|
9
9
|
def initialize(app, options = {})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
options[:request_class] ||= ActionDispatch::Request
|
|
11
|
+
options[:params_method] ||= :filtered_parameters
|
|
12
|
+
options[:instrument_span_name] = nil
|
|
13
|
+
options[:report_errors] = true
|
|
14
|
+
super
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
if Appsignal.active?
|
|
17
|
-
call_with_appsignal_monitoring(env)
|
|
18
|
-
else
|
|
19
|
-
@app.call(env)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def call_with_appsignal_monitoring(env)
|
|
24
|
-
request = ActionDispatch::Request.new(env)
|
|
25
|
-
transaction = env.fetch(
|
|
26
|
-
Appsignal::Rack::APPSIGNAL_TRANSACTION,
|
|
27
|
-
Appsignal::Transaction::NilTransaction.new
|
|
28
|
-
)
|
|
17
|
+
private
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
transaction.set_error(error)
|
|
34
|
-
raise error
|
|
35
|
-
ensure
|
|
36
|
-
controller = env["action_controller.instance"]
|
|
37
|
-
if controller
|
|
38
|
-
transaction.set_action_if_nil("#{controller.class}##{controller.action_name}")
|
|
39
|
-
end
|
|
40
|
-
transaction.set_params_if_nil(fetch_params(request))
|
|
41
|
-
request_id = fetch_request_id(env)
|
|
42
|
-
transaction.set_tags(:request_id => request_id) if request_id
|
|
43
|
-
transaction.set_metadata("path", request.path)
|
|
44
|
-
request_method = fetch_request_method(request)
|
|
45
|
-
transaction.set_metadata("method", request_method) if request_method
|
|
46
|
-
end
|
|
47
|
-
end
|
|
19
|
+
def add_transaction_metadata_after(transaction, request)
|
|
20
|
+
controller = request.env["action_controller.instance"]
|
|
21
|
+
transaction.set_action_if_nil("#{controller.class}##{controller.action_name}") if controller
|
|
48
22
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def fetch_params(request)
|
|
54
|
-
return unless request.respond_to?(:filtered_parameters)
|
|
55
|
-
|
|
56
|
-
request.filtered_parameters
|
|
57
|
-
rescue => error
|
|
58
|
-
# Getting params from the request has been know to fail.
|
|
59
|
-
Appsignal.internal_logger.debug "Exception while getting Rails params: #{error}"
|
|
60
|
-
nil
|
|
61
|
-
end
|
|
23
|
+
request_id = request.env["action_dispatch.request_id"]
|
|
24
|
+
transaction.set_tags(:request_id => request_id) if request_id
|
|
62
25
|
|
|
63
|
-
|
|
64
|
-
request.request_method
|
|
65
|
-
rescue => error
|
|
66
|
-
Appsignal.internal_logger.error("Unable to report HTTP request method: '#{error}'")
|
|
67
|
-
nil
|
|
26
|
+
super
|
|
68
27
|
end
|
|
69
28
|
end
|
|
70
29
|
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
|
data/lib/appsignal/utils.rb
CHANGED
data/lib/appsignal/version.rb
CHANGED
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
|
-
#
|
|
59
|
-
# contents of the "in memory logger" is written to the new
|
|
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
|
|
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.
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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 @
|
|
224
|
+
return unless @in_memory_logger
|
|
225
225
|
|
|
226
|
-
|
|
227
|
-
|
|
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,11 @@ require "appsignal/hooks"
|
|
|
323
324
|
require "appsignal/probes"
|
|
324
325
|
require "appsignal/marker"
|
|
325
326
|
require "appsignal/garbage_collection"
|
|
326
|
-
require "appsignal/integrations/railtie" if defined?(::Rails)
|
|
327
|
-
require "appsignal/transaction"
|
|
328
|
-
require "appsignal/version"
|
|
329
327
|
require "appsignal/rack/abstract_middleware"
|
|
330
328
|
require "appsignal/rack/generic_instrumentation"
|
|
331
329
|
require "appsignal/rack/event_handler"
|
|
330
|
+
require "appsignal/integrations/railtie" if defined?(::Rails)
|
|
331
|
+
require "appsignal/transaction"
|
|
332
|
+
require "appsignal/version"
|
|
332
333
|
require "appsignal/transmitter"
|
|
333
334
|
require "appsignal/heartbeat"
|
data/spec/.rubocop.yml
CHANGED
|
@@ -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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|