appsignal 3.12.6 → 4.0.0.beta.1
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 +499 -487
- data/CHANGELOG.md +151 -0
- data/Rakefile +31 -7
- data/benchmark.rake +4 -6
- data/build_matrix.yml +45 -39
- data/ext/agent.rb +27 -27
- data/ext/appsignal_extension.c +25 -0
- data/gemfiles/rails-7.2.gemfile +11 -0
- data/lib/appsignal/check_in/cron.rb +67 -0
- data/lib/appsignal/check_in.rb +46 -0
- data/lib/appsignal/cli/diagnose.rb +37 -28
- data/lib/appsignal/cli/install.rb +5 -1
- data/lib/appsignal/config.rb +57 -119
- data/lib/appsignal/demo.rb +2 -2
- data/lib/appsignal/extension/jruby.rb +14 -0
- data/lib/appsignal/helpers/instrumentation.rb +139 -414
- data/lib/appsignal/helpers/metrics.rb +0 -16
- data/lib/appsignal/hooks/action_cable.rb +8 -8
- data/lib/appsignal/hooks/active_job.rb +2 -2
- data/lib/appsignal/hooks/at_exit.rb +37 -0
- data/lib/appsignal/hooks.rb +1 -16
- data/lib/appsignal/integrations/action_cable.rb +2 -2
- data/lib/appsignal/integrations/capistrano/appsignal.cap +2 -4
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +1 -4
- data/lib/appsignal/integrations/delayed_job_plugin.rb +3 -3
- data/lib/appsignal/integrations/http.rb +2 -7
- data/lib/appsignal/integrations/que.rb +2 -2
- data/lib/appsignal/integrations/railtie.rb +26 -59
- data/lib/appsignal/integrations/rake.rb +2 -2
- data/lib/appsignal/integrations/resque.rb +2 -2
- data/lib/appsignal/integrations/shoryuken.rb +4 -4
- data/lib/appsignal/integrations/sidekiq.rb +3 -3
- data/lib/appsignal/integrations/webmachine.rb +2 -2
- data/lib/appsignal/loaders.rb +1 -1
- data/lib/appsignal/probes.rb +0 -9
- data/lib/appsignal/rack/abstract_middleware.rb +4 -26
- data/lib/appsignal/rack/event_handler.rb +4 -4
- data/lib/appsignal/rack/rails_instrumentation.rb +1 -1
- data/lib/appsignal/rack.rb +0 -25
- data/lib/appsignal/sample_data.rb +95 -0
- data/lib/appsignal/transaction.rb +235 -361
- data/lib/appsignal/utils/rails_helper.rb +4 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +20 -62
- data/spec/lib/appsignal/auth_check_spec.rb +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/capistrano3_spec.rb +53 -13
- data/spec/lib/appsignal/{heartbeat_spec.rb → check_in_spec.rb} +45 -36
- data/spec/lib/appsignal/cli/demo_spec.rb +7 -27
- data/spec/lib/appsignal/cli/diagnose_spec.rb +145 -110
- data/spec/lib/appsignal/config_spec.rb +304 -379
- data/spec/lib/appsignal/extension_install_failure_spec.rb +5 -1
- data/spec/lib/appsignal/extension_spec.rb +5 -1
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +1 -1
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +1 -2
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +1 -0
- data/spec/lib/appsignal/hooks/activejob_spec.rb +7 -12
- data/spec/lib/appsignal/hooks/at_exit_spec.rb +72 -0
- data/spec/lib/appsignal/hooks/gvl_spec.rb +10 -5
- data/spec/lib/appsignal/hooks/http_spec.rb +3 -3
- data/spec/lib/appsignal/hooks/net_http_spec.rb +3 -3
- data/spec/lib/appsignal/hooks/rake_spec.rb +6 -9
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -10
- data/spec/lib/appsignal/hooks/redis_spec.rb +4 -7
- data/spec/lib/appsignal/hooks/resque_spec.rb +3 -5
- data/spec/lib/appsignal/hooks_spec.rb +0 -41
- data/spec/lib/appsignal/integrations/data_mapper_spec.rb +29 -20
- data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +4 -9
- data/spec/lib/appsignal/integrations/http_spec.rb +0 -21
- data/spec/lib/appsignal/integrations/railtie_spec.rb +179 -157
- data/spec/lib/appsignal/integrations/shoryuken_spec.rb +3 -5
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +48 -62
- data/spec/lib/appsignal/loaders/hanami_spec.rb +6 -9
- data/spec/lib/appsignal/loaders/padrino_spec.rb +6 -10
- data/spec/lib/appsignal/loaders/sinatra_spec.rb +6 -9
- data/spec/lib/appsignal/loaders_spec.rb +8 -1
- data/spec/lib/appsignal/marker_spec.rb +1 -1
- data/spec/lib/appsignal/probes_spec.rb +4 -83
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +4 -63
- data/spec/lib/appsignal/rack/event_handler_spec.rb +18 -15
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +3 -11
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +4 -5
- data/spec/lib/appsignal/sample_data_spec.rb +174 -0
- data/spec/lib/appsignal/transaction_spec.rb +791 -1031
- data/spec/lib/appsignal/transmitter_spec.rb +6 -8
- data/spec/lib/appsignal_spec.rb +294 -643
- data/spec/spec_helper.rb +1 -3
- data/spec/support/fixtures/projects/valid/config/appsignal.yml +4 -7
- data/spec/support/fixtures/projects/valid_with_rails_app/config/application.rb +16 -0
- data/spec/support/fixtures/projects/valid_with_rails_app/config/appsignal.yml +56 -0
- data/spec/support/fixtures/projects/valid_with_rails_app/config/environment.rb +5 -0
- data/spec/support/helpers/api_request_helper.rb +3 -2
- data/spec/support/helpers/config_helpers.rb +41 -11
- data/spec/support/helpers/dependency_helper.rb +8 -0
- data/spec/support/helpers/log_helpers.rb +1 -0
- data/spec/support/helpers/rails_helper.rb +6 -6
- data/spec/support/helpers/transaction_helpers.rb +2 -24
- data/spec/support/matchers/transaction.rb +3 -3
- data/spec/support/mocks/appsignal_mock.rb +3 -3
- data/spec/support/mocks/mock_probe.rb +2 -0
- data/spec/support/testing.rb +2 -2
- metadata +14 -23
- data/gemfiles/que_beta.gemfile +0 -5
- data/lib/appsignal/heartbeat.rb +0 -59
- data/lib/appsignal/helpers/heartbeats.rb +0 -44
- data/lib/appsignal/integrations/grape.rb +0 -35
- data/lib/appsignal/integrations/hanami.rb +0 -13
- data/lib/appsignal/integrations/padrino.rb +0 -13
- data/lib/appsignal/integrations/sinatra.rb +0 -13
- data/lib/appsignal/rack/generic_instrumentation.rb +0 -22
- data/lib/appsignal/rack/streaming_listener.rb +0 -28
- data/spec/lib/appsignal/integrations/grape_spec.rb +0 -36
- data/spec/lib/appsignal/integrations/hanami_spec.rb +0 -17
- data/spec/lib/appsignal/integrations/padrino_spec.rb +0 -15
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -15
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +0 -81
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +0 -69
- data/spec/support/fixtures/projects/valid/config/environments/development.rb +0 -0
- data/spec/support/fixtures/projects/valid/config/environments/production.rb +0 -0
- data/spec/support/fixtures/projects/valid/config/environments/test.rb +0 -0
- data/spec/support/rails/my_app.rb +0 -6
- /data/spec/support/fixtures/projects/{valid/config/application.rb → valid_with_rails_app/log/.gitkeep} +0 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module CheckIn
|
5
|
+
class Cron
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def transmitter
|
9
|
+
@transmitter ||= Appsignal::Transmitter.new(
|
10
|
+
"#{Appsignal.config[:logging_endpoint]}/check_ins/json"
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
attr_reader :identifier, :digest
|
17
|
+
|
18
|
+
def initialize(identifier:)
|
19
|
+
@identifier = identifier
|
20
|
+
@digest = SecureRandom.hex(8)
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
transmit_event("start")
|
25
|
+
end
|
26
|
+
|
27
|
+
def finish
|
28
|
+
transmit_event("finish")
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def event(kind)
|
34
|
+
{
|
35
|
+
:identifier => @identifier,
|
36
|
+
:digest => @digest,
|
37
|
+
:kind => kind,
|
38
|
+
:timestamp => Time.now.utc.to_i,
|
39
|
+
:check_in_type => "cron"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def transmit_event(kind)
|
44
|
+
unless Appsignal.active?
|
45
|
+
Appsignal.internal_logger.debug(
|
46
|
+
"AppSignal not active, not transmitting cron check-in event"
|
47
|
+
)
|
48
|
+
return
|
49
|
+
end
|
50
|
+
|
51
|
+
response = self.class.transmitter.transmit(event(kind))
|
52
|
+
|
53
|
+
if response.code.to_i >= 200 && response.code.to_i < 300
|
54
|
+
Appsignal.internal_logger.debug(
|
55
|
+
"Transmitted cron check-in `#{identifier}` (#{digest}) #{kind} event"
|
56
|
+
)
|
57
|
+
else
|
58
|
+
Appsignal.internal_logger.error(
|
59
|
+
"Failed to transmit cron check-in #{kind} event: status code was #{response.code}"
|
60
|
+
)
|
61
|
+
end
|
62
|
+
rescue => e
|
63
|
+
Appsignal.internal_logger.error("Failed to transmit cron check-in #{kind} event: #{e}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module CheckIn
|
5
|
+
class << self
|
6
|
+
# Track cron check-ins.
|
7
|
+
#
|
8
|
+
# Track the execution of certain processes by sending a cron check-in.
|
9
|
+
#
|
10
|
+
# To track the duration of a piece of code, pass a block to {.cron}
|
11
|
+
# to report both when the process starts, and when it finishes.
|
12
|
+
#
|
13
|
+
# If an exception is raised within the block, the finish event will not
|
14
|
+
# be reported, triggering a notification about the missing cron check-in.
|
15
|
+
# The exception will bubble outside of the cron check-in block.
|
16
|
+
#
|
17
|
+
# @example Send a cron check-in
|
18
|
+
# Appsignal::CheckIn.cron("send_invoices")
|
19
|
+
#
|
20
|
+
# @example Send a cron check-in with duration
|
21
|
+
# Appsignal::CheckIn.cron("send_invoices") do
|
22
|
+
# # your code
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @param name [String] name of the cron check-in to report.
|
26
|
+
# @yield the block to monitor.
|
27
|
+
# @return [void]
|
28
|
+
# @since 3.13.0
|
29
|
+
# @see https://docs.appsignal.com/check-ins/cron
|
30
|
+
def cron(identifier)
|
31
|
+
cron = Appsignal::CheckIn::Cron.new(:identifier => identifier)
|
32
|
+
output = nil
|
33
|
+
|
34
|
+
if block_given?
|
35
|
+
cron.start
|
36
|
+
output = yield
|
37
|
+
end
|
38
|
+
|
39
|
+
cron.finish
|
40
|
+
output
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
require "appsignal/check_in/cron"
|
@@ -77,6 +77,10 @@ module Appsignal
|
|
77
77
|
# @return [void]
|
78
78
|
# @api private
|
79
79
|
def run(options = {})
|
80
|
+
# Do not start AppSignal on `Appsignal.start` and run the extension
|
81
|
+
# and agent in diagnose mode.
|
82
|
+
ENV["_APPSIGNAL_DIAGNOSE"] = "true"
|
83
|
+
|
80
84
|
self.coloring = options.delete(:color) { true }
|
81
85
|
$stdout.sync = true
|
82
86
|
header
|
@@ -184,21 +188,13 @@ module Appsignal
|
|
184
188
|
end
|
185
189
|
|
186
190
|
def configure_appsignal(options)
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
current_path = Rails.root
|
192
|
-
initial_config[:name] =
|
193
|
-
Appsignal::Utils::RailsHelper.detected_rails_app_name
|
194
|
-
initial_config[:log_path] = current_path.join("log")
|
195
|
-
end
|
191
|
+
# Try and load the Rails app, if any.
|
192
|
+
# This will configure AppSignal through the config file or an
|
193
|
+
# initializer.
|
194
|
+
require_rails_app_if_present
|
196
195
|
|
197
|
-
|
198
|
-
|
199
|
-
options.fetch(:environment, ENV.fetch("RACK_ENV", ENV.fetch("RAILS_ENV", nil))),
|
200
|
-
initial_config
|
201
|
-
)
|
196
|
+
# If no config was found by loading the app, load with the defaults.
|
197
|
+
Appsignal.configure(options.fetch(:environment, nil))
|
202
198
|
Appsignal.config.write_to_environment
|
203
199
|
Appsignal._start_logger
|
204
200
|
Appsignal.internal_logger.info("Starting AppSignal diagnose")
|
@@ -211,9 +207,9 @@ module Appsignal
|
|
211
207
|
return
|
212
208
|
end
|
213
209
|
|
214
|
-
|
210
|
+
# Requires _APPSIGNAL_DIAGNOSE to be set. This is set at the
|
211
|
+
# beginning of the diagnose CLI.
|
215
212
|
diagnostics_report_string = Appsignal::Extension.diagnose
|
216
|
-
ENV.delete("_APPSIGNAL_DIAGNOSE")
|
217
213
|
|
218
214
|
begin
|
219
215
|
report = JSON.parse(diagnostics_report_string)
|
@@ -473,14 +469,12 @@ module Appsignal
|
|
473
469
|
:sources => {
|
474
470
|
:default => Appsignal::Config::DEFAULT_CONFIG,
|
475
471
|
:system => config.system_config,
|
472
|
+
:loaders => config.loaders_config,
|
476
473
|
:initial => config.initial_config,
|
477
474
|
:file => config.file_config,
|
478
475
|
:env => config.env_config,
|
479
|
-
:override => config.override_config
|
480
|
-
|
481
|
-
:modifiers => {
|
482
|
-
"APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" =>
|
483
|
-
ENV.fetch("APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR", "")
|
476
|
+
:override => config.override_config,
|
477
|
+
:dsl => config.dsl_config
|
484
478
|
}
|
485
479
|
}
|
486
480
|
print_config_options(config)
|
@@ -523,11 +517,6 @@ module Appsignal
|
|
523
517
|
end
|
524
518
|
end
|
525
519
|
|
526
|
-
puts
|
527
|
-
puts "Configuration modifiers"
|
528
|
-
puts " APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR: " \
|
529
|
-
"#{data[:config][:modifiers]["APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR"].inspect}"
|
530
|
-
|
531
520
|
puts "\nRead more about how the diagnose config output is rendered\n" \
|
532
521
|
"https://docs.appsignal.com/ruby/command-line/diagnose.html"
|
533
522
|
end
|
@@ -642,9 +631,29 @@ module Appsignal
|
|
642
631
|
puts "\n"
|
643
632
|
end
|
644
633
|
|
645
|
-
def
|
634
|
+
def require_rails_app_if_present
|
635
|
+
return unless rails_present?
|
636
|
+
|
637
|
+
# Mark app as Rails app
|
638
|
+
data[:app][:rails] = true
|
639
|
+
# Manually require the railtie, because it wasn't loaded when the CLI
|
640
|
+
# started and AppSignal loaded, because the `Rails` constant wasn't
|
641
|
+
# present.
|
642
|
+
require "appsignal/integrations/railtie"
|
643
|
+
# Start the Rails app, including railties and initializers.
|
644
|
+
require Appsignal::Utils::RailsHelper.environment_config_path
|
645
|
+
rescue LoadError, StandardError => error
|
646
|
+
print_empty_line
|
647
|
+
puts "ERROR: Error encountered while loading the Rails app"
|
648
|
+
puts "#{error.class}: #{error.message}"
|
649
|
+
puts error.backtrace
|
650
|
+
data[:app][:load_error] =
|
651
|
+
"#{error.class}: #{error.message}\n#{error.backtrace.join("\n")}"
|
652
|
+
end
|
653
|
+
|
654
|
+
def rails_present?
|
655
|
+
# Try and load the Rails gem
|
646
656
|
require "rails"
|
647
|
-
require File.expand_path(File.join(Dir.pwd, "config", "application.rb"))
|
648
657
|
true
|
649
658
|
rescue LoadError
|
650
659
|
false
|
@@ -237,6 +237,10 @@ module Appsignal
|
|
237
237
|
puts "How do you want to configure AppSignal?"
|
238
238
|
puts " (1) a config file"
|
239
239
|
puts " (2) environment variables"
|
240
|
+
puts
|
241
|
+
puts " See our docs for information on the different configuration methods: "
|
242
|
+
puts " https://docs.appsignal.com/ruby/configuration.html"
|
243
|
+
puts
|
240
244
|
loop do
|
241
245
|
print " Choose (1/2): "
|
242
246
|
case ask_for_input
|
@@ -264,7 +268,7 @@ module Appsignal
|
|
264
268
|
puts " export APPSIGNAL_APP_NAME=#{config[:name]}" if name_overwritten
|
265
269
|
puts
|
266
270
|
puts " See the documentation for more configuration options:"
|
267
|
-
puts " https://docs.appsignal.com/
|
271
|
+
puts " https://docs.appsignal.com/ruby/configuration.html"
|
268
272
|
press_any_key
|
269
273
|
break
|
270
274
|
end
|
data/lib/appsignal/config.rb
CHANGED
@@ -8,16 +8,19 @@ require "tmpdir"
|
|
8
8
|
|
9
9
|
module Appsignal
|
10
10
|
class Config
|
11
|
-
include Appsignal::Utils::StdoutAndLoggerMessage
|
12
|
-
|
13
11
|
# @api private
|
14
12
|
def self.loader_defaults
|
15
13
|
@loader_defaults ||= []
|
16
14
|
end
|
17
15
|
|
18
16
|
# @api private
|
19
|
-
def self.add_loader_defaults(name, options)
|
20
|
-
loader_defaults <<
|
17
|
+
def self.add_loader_defaults(name, env: nil, root_path: nil, **options)
|
18
|
+
loader_defaults << {
|
19
|
+
:name => name,
|
20
|
+
:env => env,
|
21
|
+
:root_path => root_path,
|
22
|
+
:options => options.compact
|
23
|
+
}
|
21
24
|
end
|
22
25
|
|
23
26
|
# Determine which env AppSignal should initialize with.
|
@@ -32,7 +35,7 @@ module Appsignal
|
|
32
35
|
return env if env
|
33
36
|
end
|
34
37
|
|
35
|
-
loader_defaults.reverse.each do |
|
38
|
+
loader_defaults.reverse.each do |loader_defaults|
|
36
39
|
env = loader_defaults[:env]
|
37
40
|
return env if env
|
38
41
|
end
|
@@ -43,7 +46,7 @@ module Appsignal
|
|
43
46
|
# Determine which root path AppSignal should initialize with.
|
44
47
|
# @api private
|
45
48
|
def self.determine_root_path
|
46
|
-
loader_defaults.reverse.each do |
|
49
|
+
loader_defaults.reverse.each do |loader_defaults|
|
47
50
|
root_path = loader_defaults[:root_path]
|
48
51
|
return root_path if root_path
|
49
52
|
end
|
@@ -55,9 +58,9 @@ module Appsignal
|
|
55
58
|
DEFAULT_CONFIG = {
|
56
59
|
:activejob_report_errors => "all",
|
57
60
|
:ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
|
58
|
-
:debug => false,
|
59
61
|
:dns_servers => [],
|
60
62
|
:enable_allocation_tracking => true,
|
63
|
+
:enable_at_exit_reporter => true,
|
61
64
|
:enable_host_metrics => true,
|
62
65
|
:enable_minutely_probes => true,
|
63
66
|
:enable_statsd => true,
|
@@ -90,8 +93,8 @@ module Appsignal
|
|
90
93
|
],
|
91
94
|
:send_environment_metadata => true,
|
92
95
|
:send_params => true,
|
93
|
-
:
|
94
|
-
:
|
96
|
+
:send_session_data => true,
|
97
|
+
:sidekiq_report_errors => "all"
|
95
98
|
}.freeze
|
96
99
|
|
97
100
|
# @api private
|
@@ -127,14 +130,13 @@ module Appsignal
|
|
127
130
|
"APPSIGNAL_SIDEKIQ_REPORT_ERRORS" => :sidekiq_report_errors,
|
128
131
|
"APPSIGNAL_STATSD_PORT" => :statsd_port,
|
129
132
|
"APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
|
130
|
-
"APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
|
131
133
|
"APP_REVISION" => :revision
|
132
134
|
}.freeze
|
133
135
|
# @api private
|
134
136
|
ENV_BOOLEAN_KEYS = {
|
135
137
|
"APPSIGNAL_ACTIVE" => :active,
|
136
|
-
"APPSIGNAL_DEBUG" => :debug,
|
137
138
|
"APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
|
139
|
+
"APPSIGNAL_ENABLE_AT_EXIT_REPORTER" => :enable_at_exit_reporter,
|
138
140
|
"APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
|
139
141
|
"APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
|
140
142
|
"APPSIGNAL_ENABLE_STATSD" => :enable_statsd,
|
@@ -152,9 +154,7 @@ module Appsignal
|
|
152
154
|
"APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
|
153
155
|
"APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
|
154
156
|
"APPSIGNAL_SEND_PARAMS" => :send_params,
|
155
|
-
"APPSIGNAL_SEND_SESSION_DATA" => :send_session_data
|
156
|
-
"APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
|
157
|
-
"APPSIGNAL_TRANSACTION_DEBUG_MODE" => :transaction_debug_mode
|
157
|
+
"APPSIGNAL_SEND_SESSION_DATA" => :send_session_data
|
158
158
|
}.freeze
|
159
159
|
# @api private
|
160
160
|
ENV_ARRAY_KEYS = {
|
@@ -178,11 +178,6 @@ module Appsignal
|
|
178
178
|
# Used in diagnose report.
|
179
179
|
# @api private
|
180
180
|
# @return [Hash]
|
181
|
-
# @!attribute [r] initial_config
|
182
|
-
# Config detected on the system level.
|
183
|
-
# Used in diagnose report.
|
184
|
-
# @api private
|
185
|
-
# @return [Hash]
|
186
181
|
# @!attribute [r] file_config
|
187
182
|
# Config loaded from `config/appsignal.yml` config file.
|
188
183
|
# Used in diagnose report.
|
@@ -195,8 +190,8 @@ module Appsignal
|
|
195
190
|
# @return [Hash]
|
196
191
|
# @!attribute [r] config_hash
|
197
192
|
# Config used by the AppSignal gem.
|
198
|
-
# Combined Hash of the {system_config}, {
|
199
|
-
#
|
193
|
+
# Combined Hash of the {system_config}, {file_config}, {env_config}
|
194
|
+
# attributes.
|
200
195
|
# @see #[]
|
201
196
|
# @see #[]=
|
202
197
|
# @api private
|
@@ -204,8 +199,8 @@ module Appsignal
|
|
204
199
|
|
205
200
|
# @api private
|
206
201
|
attr_accessor :root_path, :env, :config_hash
|
207
|
-
attr_reader :system_config, :
|
208
|
-
:override_config, :dsl_config
|
202
|
+
attr_reader :system_config, :loaders_config, :initial_config, :file_config,
|
203
|
+
:env_config, :override_config, :dsl_config
|
209
204
|
# @api private
|
210
205
|
attr_accessor :logger
|
211
206
|
|
@@ -215,9 +210,6 @@ module Appsignal
|
|
215
210
|
# @param initial_env [String] The environment to load when AppSignal is started. It
|
216
211
|
# will look for an environment with this name in the `config/appsignal.yml`
|
217
212
|
# config file.
|
218
|
-
# @param initial_config [Hash<String, Object>] The initial configuration to
|
219
|
-
# use. This will be overwritten by the file config and environment
|
220
|
-
# variables config.
|
221
213
|
# @param logger [Logger] The logger to use for the AppSignal gem. This is
|
222
214
|
# used by the configuration class only. Default:
|
223
215
|
# {Appsignal.internal_logger}. See also {Appsignal.start}.
|
@@ -231,13 +223,10 @@ module Appsignal
|
|
231
223
|
# Configuration load order
|
232
224
|
# @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
|
233
225
|
# How to integrate AppSignal manually
|
234
|
-
def initialize(
|
226
|
+
def initialize(
|
235
227
|
root_path,
|
236
228
|
initial_env,
|
237
|
-
|
238
|
-
logger = Appsignal.internal_logger,
|
239
|
-
config_file = nil,
|
240
|
-
load_on_new = true # rubocop:disable Style/OptionalBooleanParameter
|
229
|
+
logger = Appsignal.internal_logger
|
241
230
|
)
|
242
231
|
@root_path = root_path
|
243
232
|
@config_file_error = false
|
@@ -249,20 +238,14 @@ module Appsignal
|
|
249
238
|
@env = initial_env.to_s
|
250
239
|
@config_hash = {}
|
251
240
|
@system_config = {}
|
252
|
-
@
|
241
|
+
@loaders_config = {}
|
242
|
+
@initial_config = {}
|
253
243
|
@file_config = {}
|
254
244
|
@env_config = {}
|
255
245
|
@override_config = {}
|
256
246
|
@dsl_config = {} # Can be set using `Appsignal.configure`
|
257
247
|
|
258
|
-
return unless load_on_new
|
259
|
-
|
260
|
-
# Always override environment if set via this env var.
|
261
|
-
# TODO: This is legacy behavior. In the `Appsignal.configure` method the
|
262
|
-
# env argument is leading.
|
263
|
-
@env = ENV["APPSIGNAL_APP_ENV"] if ENV.key?("APPSIGNAL_APP_ENV")
|
264
248
|
load_config
|
265
|
-
validate
|
266
249
|
end
|
267
250
|
|
268
251
|
# @api private
|
@@ -275,8 +258,17 @@ module Appsignal
|
|
275
258
|
@system_config = detect_from_system
|
276
259
|
merge(system_config)
|
277
260
|
|
278
|
-
#
|
279
|
-
|
261
|
+
# Set defaults from loaders in reverse order so the first register
|
262
|
+
# loader's defaults overwrite all others
|
263
|
+
self.class.loader_defaults.reverse.each do |loader_defaults|
|
264
|
+
defaults = loader_defaults[:options]
|
265
|
+
@loaders_config.merge!(defaults.merge(
|
266
|
+
:root_path => loader_defaults[:root_path],
|
267
|
+
:env => loader_defaults[:env]
|
268
|
+
))
|
269
|
+
merge(defaults)
|
270
|
+
end
|
271
|
+
|
280
272
|
# Track origin of env
|
281
273
|
@initial_config[:env] = @initial_env.to_s
|
282
274
|
|
@@ -290,13 +282,6 @@ module Appsignal
|
|
290
282
|
# Track origin of env
|
291
283
|
env_loaded_from_env = ENV.fetch("APPSIGNAL_APP_ENV", nil)
|
292
284
|
@env_config[:env] = env_loaded_from_env if env_loaded_from_env
|
293
|
-
|
294
|
-
# Load config overrides
|
295
|
-
@override_config = determine_overrides
|
296
|
-
merge(override_config)
|
297
|
-
|
298
|
-
# Handle deprecated config options
|
299
|
-
maintain_backwards_compatibility
|
300
285
|
end
|
301
286
|
|
302
287
|
# @api private
|
@@ -326,12 +311,12 @@ module Appsignal
|
|
326
311
|
|
327
312
|
# @api private
|
328
313
|
def log_level
|
329
|
-
level = ::Logger::DEBUG if config_hash[:debug] || config_hash[:transaction_debug_mode]
|
330
314
|
option = config_hash[:log_level]
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
315
|
+
level =
|
316
|
+
if option
|
317
|
+
log_level_option = LOG_LEVEL_MAP[option]
|
318
|
+
log_level_option
|
319
|
+
end
|
335
320
|
level.nil? ? Appsignal::Config::DEFAULT_LOG_LEVEL : level
|
336
321
|
end
|
337
322
|
|
@@ -379,7 +364,6 @@ module Appsignal
|
|
379
364
|
ENV["_APPSIGNAL_BIND_ADDRESS"] = config_hash[:bind_address].to_s
|
380
365
|
ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
|
381
366
|
ENV["_APPSIGNAL_CPU_COUNT"] = config_hash[:cpu_count].to_s
|
382
|
-
ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
|
383
367
|
ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
|
384
368
|
ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
|
385
369
|
ENV["_APPSIGNAL_ENABLE_STATSD"] = config_hash[:enable_statsd].to_s
|
@@ -406,24 +390,24 @@ module Appsignal
|
|
406
390
|
ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"] = config_hash[:running_in_container].to_s
|
407
391
|
ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"] = config_hash[:send_environment_metadata].to_s
|
408
392
|
ENV["_APPSIGNAL_STATSD_PORT"] = config_hash[:statsd_port].to_s
|
409
|
-
ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"] = config_hash[:transaction_debug_mode].to_s
|
410
393
|
if config_hash[:working_directory_path]
|
411
394
|
ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"] = config_hash[:working_directory_path]
|
412
395
|
end
|
413
|
-
if config_hash[:working_dir_path]
|
414
|
-
ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path]
|
415
|
-
end
|
416
396
|
ENV["_APP_REVISION"] = config_hash[:revision].to_s
|
417
397
|
end
|
418
398
|
|
419
399
|
# @api private
|
420
400
|
def merge_dsl_options(options)
|
421
|
-
@
|
401
|
+
@dsl_config = options
|
422
402
|
merge(options)
|
423
403
|
end
|
424
404
|
|
425
405
|
# @api private
|
426
406
|
def validate
|
407
|
+
# Apply any overrides for invalid settings.
|
408
|
+
@override_config = determine_overrides
|
409
|
+
merge(override_config)
|
410
|
+
|
427
411
|
# Strip path from endpoint so we're backwards compatible with
|
428
412
|
# earlier versions of the gem.
|
429
413
|
# TODO: Move to its own method, maybe in `#[]=`?
|
@@ -444,6 +428,17 @@ module Appsignal
|
|
444
428
|
end
|
445
429
|
end
|
446
430
|
|
431
|
+
# Deep freeze the config object so it cannot be modified during the runtime
|
432
|
+
# of the Ruby app.
|
433
|
+
#
|
434
|
+
# @api private
|
435
|
+
# @since 4.0.0
|
436
|
+
def freeze
|
437
|
+
super
|
438
|
+
config_hash.freeze
|
439
|
+
config_hash.transform_values(&:freeze)
|
440
|
+
end
|
441
|
+
|
447
442
|
private
|
448
443
|
|
449
444
|
def config_file
|
@@ -475,20 +470,9 @@ module Appsignal
|
|
475
470
|
nil
|
476
471
|
end
|
477
472
|
rescue => e
|
478
|
-
# TODO: Remove in the next major version
|
479
473
|
@config_file_error = true
|
480
|
-
extra_message =
|
481
|
-
if inactive_on_config_file_error?
|
482
|
-
"Not starting AppSignal because " \
|
483
|
-
"APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR is set."
|
484
|
-
else
|
485
|
-
"Skipping file config. In future versions AppSignal will not start " \
|
486
|
-
"on a config file error. To opt-in to this new behavior set " \
|
487
|
-
"'APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR=1' in your system " \
|
488
|
-
"environment."
|
489
|
-
end
|
490
474
|
message = "An error occurred while loading the AppSignal config file. " \
|
491
|
-
"
|
475
|
+
"Not starting AppSignal.\n" \
|
492
476
|
"File: #{config_file.inspect}\n" \
|
493
477
|
"#{e.class.name}: #{e}"
|
494
478
|
Kernel.warn "appsignal: #{message}"
|
@@ -496,27 +480,6 @@ module Appsignal
|
|
496
480
|
nil
|
497
481
|
end
|
498
482
|
|
499
|
-
# Maintain backwards compatibility with deprecated config options.
|
500
|
-
#
|
501
|
-
# Add warnings for deprecated config options here if they have no
|
502
|
-
# replacement, or should be non-functional.
|
503
|
-
#
|
504
|
-
# Add them to {determine_overrides} if replacement config options should be
|
505
|
-
# set instead.
|
506
|
-
#
|
507
|
-
# Make sure to remove the contents of this method in the next major
|
508
|
-
# version, but the method itself with an empty body can stick around as a
|
509
|
-
# structure for future deprecations.
|
510
|
-
def maintain_backwards_compatibility
|
511
|
-
return unless config_hash.key?(:working_dir_path)
|
512
|
-
|
513
|
-
stdout_and_logger_warning \
|
514
|
-
"The `working_dir_path` option is deprecated, please use " \
|
515
|
-
"`working_directory_path` instead and specify the " \
|
516
|
-
"full path to the working directory",
|
517
|
-
logger
|
518
|
-
end
|
519
|
-
|
520
483
|
def load_from_environment
|
521
484
|
config = {}
|
522
485
|
|
@@ -556,32 +519,13 @@ module Appsignal
|
|
556
519
|
end
|
557
520
|
|
558
521
|
# Set config options based on the final user config. Fix any conflicting
|
559
|
-
# config
|
560
|
-
#
|
561
|
-
# Make sure to remove behavior for deprecated config options in this method
|
562
|
-
# in the next major version, but the method itself with an empty body can
|
563
|
-
# stick around as a structure for future deprecations.
|
522
|
+
# config.
|
564
523
|
def determine_overrides
|
565
524
|
config = {}
|
566
525
|
# If an error was detected during config file reading/parsing and the new
|
567
526
|
# behavior is enabled to not start AppSignal on incomplete config, do not
|
568
527
|
# start AppSignal.
|
569
|
-
|
570
|
-
# `inactive_on_config_file_error?` call.
|
571
|
-
config[:active] = false if @config_file_error && inactive_on_config_file_error?
|
572
|
-
skip_session_data = config_hash[:skip_session_data]
|
573
|
-
send_session_data = config_hash[:send_session_data]
|
574
|
-
if skip_session_data.nil? # Deprecated option is not set
|
575
|
-
if send_session_data.nil? # Not configured by user
|
576
|
-
config[:send_session_data] = true # Set default value
|
577
|
-
end
|
578
|
-
else
|
579
|
-
stdout_and_logger_warning "The `skip_session_data` config option is " \
|
580
|
-
"deprecated. Please use `send_session_data` instead.",
|
581
|
-
logger
|
582
|
-
# Not configured by user
|
583
|
-
config[:send_session_data] = !skip_session_data if send_session_data.nil?
|
584
|
-
end
|
528
|
+
config[:active] = false if @config_file_error
|
585
529
|
|
586
530
|
if config_hash[:activejob_report_errors] == "discard" &&
|
587
531
|
!Appsignal::Hooks::ActiveJobHook.version_7_1_or_higher?
|
@@ -603,12 +547,6 @@ module Appsignal
|
|
603
547
|
end
|
604
548
|
end
|
605
549
|
|
606
|
-
# Does it use the new behavior?
|
607
|
-
def inactive_on_config_file_error?
|
608
|
-
value = ENV.fetch("APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR", false)
|
609
|
-
["1", "true"].include?(value)
|
610
|
-
end
|
611
|
-
|
612
550
|
# @api private
|
613
551
|
class ConfigDSL
|
614
552
|
attr_reader :dsl_options
|
data/lib/appsignal/demo.rb
CHANGED
@@ -70,14 +70,14 @@ module Appsignal
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def add_params_to(transaction)
|
73
|
-
transaction.
|
73
|
+
transaction.add_params(
|
74
74
|
"controller" => "demo",
|
75
75
|
"action" => "hello"
|
76
76
|
)
|
77
77
|
end
|
78
78
|
|
79
79
|
def add_headers_to(transaction)
|
80
|
-
transaction.
|
80
|
+
transaction.add_headers(
|
81
81
|
"REMOTE_ADDR" => "127.0.0.1",
|
82
82
|
"REQUEST_METHOD" => "GET",
|
83
83
|
"SERVER_NAME" => "localhost",
|
@@ -132,6 +132,9 @@ module Appsignal
|
|
132
132
|
attach_function :appsignal_complete_transaction,
|
133
133
|
[:pointer],
|
134
134
|
:void
|
135
|
+
attach_function :appsignal_duplicate_transaction,
|
136
|
+
[:pointer, :appsignal_string],
|
137
|
+
:pointer
|
135
138
|
attach_function :appsignal_transaction_to_json,
|
136
139
|
[:pointer],
|
137
140
|
:appsignal_string
|
@@ -432,6 +435,17 @@ module Appsignal
|
|
432
435
|
Extension.appsignal_finish_transaction(pointer, gc_duration_ms)
|
433
436
|
end
|
434
437
|
|
438
|
+
def duplicate(new_transaction_id)
|
439
|
+
duplicate_transaction = Extension.appsignal_duplicate_transaction(
|
440
|
+
pointer,
|
441
|
+
make_appsignal_string(new_transaction_id)
|
442
|
+
)
|
443
|
+
|
444
|
+
return if !duplicate_transaction || duplicate_transaction.null?
|
445
|
+
|
446
|
+
Transaction.new(duplicate_transaction)
|
447
|
+
end
|
448
|
+
|
435
449
|
def complete
|
436
450
|
Extension.appsignal_complete_transaction(pointer)
|
437
451
|
end
|