appsignal 2.5.0.alpha.1-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 +7 -0
- data/.gitignore +33 -0
- data/.rspec +4 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +124 -0
- data/.travis.yml +72 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +639 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +264 -0
- data/Rakefile +214 -0
- data/appsignal.gemspec +42 -0
- data/benchmark.rake +77 -0
- data/bin/appsignal +13 -0
- data/ext/Rakefile +27 -0
- data/ext/agent.yml +64 -0
- data/ext/appsignal_extension.c +692 -0
- data/ext/base.rb +79 -0
- data/ext/extconf.rb +35 -0
- data/gemfiles/capistrano2.gemfile +7 -0
- data/gemfiles/capistrano3.gemfile +7 -0
- data/gemfiles/grape.gemfile +7 -0
- data/gemfiles/no_dependencies.gemfile +5 -0
- data/gemfiles/padrino.gemfile +7 -0
- data/gemfiles/que.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +6 -0
- data/gemfiles/rails-4.0.gemfile +6 -0
- data/gemfiles/rails-4.1.gemfile +6 -0
- data/gemfiles/rails-4.2.gemfile +10 -0
- data/gemfiles/rails-5.0.gemfile +5 -0
- data/gemfiles/rails-5.1.gemfile +5 -0
- data/gemfiles/resque.gemfile +12 -0
- data/gemfiles/sequel-435.gemfile +11 -0
- data/gemfiles/sequel.gemfile +11 -0
- data/gemfiles/sinatra.gemfile +6 -0
- data/gemfiles/webmachine.gemfile +5 -0
- data/lib/appsignal.rb +804 -0
- data/lib/appsignal/auth_check.rb +65 -0
- data/lib/appsignal/capistrano.rb +10 -0
- data/lib/appsignal/cli.rb +108 -0
- data/lib/appsignal/cli/demo.rb +63 -0
- data/lib/appsignal/cli/diagnose.rb +500 -0
- data/lib/appsignal/cli/helpers.rb +72 -0
- data/lib/appsignal/cli/install.rb +277 -0
- data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
- data/lib/appsignal/config.rb +287 -0
- data/lib/appsignal/demo.rb +107 -0
- data/lib/appsignal/event_formatter.rb +74 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
- data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
- data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
- data/lib/appsignal/extension.rb +63 -0
- data/lib/appsignal/extension/jruby.rb +460 -0
- data/lib/appsignal/garbage_collection_profiler.rb +48 -0
- data/lib/appsignal/hooks.rb +105 -0
- data/lib/appsignal/hooks/action_cable.rb +113 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
- data/lib/appsignal/hooks/celluloid.rb +30 -0
- data/lib/appsignal/hooks/data_mapper.rb +18 -0
- data/lib/appsignal/hooks/delayed_job.rb +19 -0
- data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
- data/lib/appsignal/hooks/net_http.rb +29 -0
- data/lib/appsignal/hooks/passenger.rb +22 -0
- data/lib/appsignal/hooks/puma.rb +35 -0
- data/lib/appsignal/hooks/que.rb +21 -0
- data/lib/appsignal/hooks/rake.rb +39 -0
- data/lib/appsignal/hooks/redis.rb +30 -0
- data/lib/appsignal/hooks/sequel.rb +60 -0
- data/lib/appsignal/hooks/shoryuken.rb +43 -0
- data/lib/appsignal/hooks/sidekiq.rb +144 -0
- data/lib/appsignal/hooks/unicorn.rb +40 -0
- data/lib/appsignal/hooks/webmachine.rb +23 -0
- data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
- data/lib/appsignal/integrations/data_mapper.rb +33 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
- data/lib/appsignal/integrations/grape.rb +53 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
- data/lib/appsignal/integrations/object.rb +35 -0
- data/lib/appsignal/integrations/padrino.rb +84 -0
- data/lib/appsignal/integrations/que.rb +43 -0
- data/lib/appsignal/integrations/railtie.rb +41 -0
- data/lib/appsignal/integrations/rake.rb +2 -0
- data/lib/appsignal/integrations/resque.rb +20 -0
- data/lib/appsignal/integrations/resque_active_job.rb +30 -0
- data/lib/appsignal/integrations/sinatra.rb +17 -0
- data/lib/appsignal/integrations/webmachine.rb +38 -0
- data/lib/appsignal/js_exception_transaction.rb +54 -0
- data/lib/appsignal/marker.rb +63 -0
- data/lib/appsignal/minutely.rb +42 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
- data/lib/appsignal/rack/streaming_listener.rb +73 -0
- data/lib/appsignal/system.rb +81 -0
- data/lib/appsignal/transaction.rb +498 -0
- data/lib/appsignal/transmitter.rb +107 -0
- data/lib/appsignal/utils.rb +127 -0
- data/lib/appsignal/utils/params_sanitizer.rb +59 -0
- data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
- data/lib/appsignal/version.rb +3 -0
- data/lib/sequel/extensions/appsignal_integration.rb +3 -0
- data/resources/appsignal.yml.erb +39 -0
- data/resources/cacert.pem +3866 -0
- data/spec/.rubocop.yml +7 -0
- data/spec/lib/appsignal/auth_check_spec.rb +80 -0
- data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
- data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
- data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
- data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
- data/spec/lib/appsignal/cli/install_spec.rb +632 -0
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
- data/spec/lib/appsignal/cli_spec.rb +56 -0
- data/spec/lib/appsignal/config_spec.rb +637 -0
- data/spec/lib/appsignal/demo_spec.rb +87 -0
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
- data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
- data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
- data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
- data/spec/lib/appsignal/extension_spec.rb +137 -0
- data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
- data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
- data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
- data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
- data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
- data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
- data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
- data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
- data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
- data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
- data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
- data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
- data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
- data/spec/lib/appsignal/hooks_spec.rb +195 -0
- data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
- data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
- data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
- data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
- data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
- data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
- data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
- data/spec/lib/appsignal/marker_spec.rb +51 -0
- data/spec/lib/appsignal/minutely_spec.rb +50 -0
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
- data/spec/lib/appsignal/system_spec.rb +131 -0
- data/spec/lib/appsignal/transaction_spec.rb +1146 -0
- data/spec/lib/appsignal/transmitter_spec.rb +152 -0
- data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
- data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
- data/spec/lib/appsignal/utils_spec.rb +150 -0
- data/spec/lib/appsignal_spec.rb +1049 -0
- data/spec/spec_helper.rb +116 -0
- data/spec/support/fixtures/containers/cgroups/docker +14 -0
- data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
- data/spec/support/fixtures/containers/cgroups/lxc +10 -0
- data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
- data/spec/support/fixtures/containers/cgroups/none +1 -0
- data/spec/support/fixtures/generated_config.yml +24 -0
- data/spec/support/fixtures/uploaded_file.txt +0 -0
- data/spec/support/helpers/api_request_helper.rb +19 -0
- data/spec/support/helpers/cli_helpers.rb +26 -0
- data/spec/support/helpers/config_helpers.rb +21 -0
- data/spec/support/helpers/dependency_helper.rb +73 -0
- data/spec/support/helpers/directory_helper.rb +27 -0
- data/spec/support/helpers/env_helpers.rb +33 -0
- data/spec/support/helpers/example_exception.rb +13 -0
- data/spec/support/helpers/example_standard_error.rb +13 -0
- data/spec/support/helpers/log_helpers.rb +22 -0
- data/spec/support/helpers/std_streams_helper.rb +66 -0
- data/spec/support/helpers/system_helpers.rb +8 -0
- data/spec/support/helpers/time_helpers.rb +11 -0
- data/spec/support/helpers/transaction_helpers.rb +37 -0
- data/spec/support/matchers/contains_log.rb +7 -0
- data/spec/support/mocks/fake_gc_profiler.rb +19 -0
- data/spec/support/mocks/mock_extension.rb +6 -0
- data/spec/support/project_fixture/config/application.rb +0 -0
- data/spec/support/project_fixture/config/appsignal.yml +32 -0
- data/spec/support/project_fixture/config/environments/development.rb +0 -0
- data/spec/support/project_fixture/config/environments/production.rb +0 -0
- data/spec/support/project_fixture/config/environments/test.rb +0 -0
- data/spec/support/project_fixture/log/.gitkeep +0 -0
- data/spec/support/rails/my_app.rb +6 -0
- data/spec/support/shared_examples/instrument.rb +43 -0
- data/spec/support/stubs/delayed_job.rb +0 -0
- metadata +483 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
# Class used to perform a Push API validation / authentication check against
|
|
3
|
+
# the AppSignal Push API.
|
|
4
|
+
#
|
|
5
|
+
# @example
|
|
6
|
+
# config = Appsignal::Config.new(Dir.pwd, "production")
|
|
7
|
+
# auth_check = Appsignal::AuthCheck.new(config)
|
|
8
|
+
# # Valid push_api_key
|
|
9
|
+
# auth_check.perform # => "200"
|
|
10
|
+
# # Invalid push_api_key
|
|
11
|
+
# auth_check.perform # => "401"
|
|
12
|
+
#
|
|
13
|
+
# @!attribute [r] config
|
|
14
|
+
# @return [Appsignal::Config] config to use in the authentication request.
|
|
15
|
+
# @api private
|
|
16
|
+
class AuthCheck
|
|
17
|
+
# Path used on the AppSignal Push API
|
|
18
|
+
# https://push.appsignal.com/1/auth
|
|
19
|
+
ACTION = "auth".freeze
|
|
20
|
+
|
|
21
|
+
attr_reader :config, :logger
|
|
22
|
+
|
|
23
|
+
def initialize(config, logger = nil)
|
|
24
|
+
@config = config
|
|
25
|
+
if logger # rubocop:disable Style/GuardClause
|
|
26
|
+
warn "Deprecated: `logger` argument will be removed in the next " \
|
|
27
|
+
"major version."
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Perform push api validation request and return response status code.
|
|
32
|
+
#
|
|
33
|
+
# @return [String] response status code.
|
|
34
|
+
# @raise [StandardError] see {Appsignal::Transmitter#transmit}.
|
|
35
|
+
def perform
|
|
36
|
+
Appsignal::Transmitter.new(ACTION, config).transmit({}).code
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Perform push api validation request and return a descriptive response
|
|
40
|
+
# tuple.
|
|
41
|
+
#
|
|
42
|
+
# @return [Array<String/nil, String>] response tuple.
|
|
43
|
+
# - First value is the response status code.
|
|
44
|
+
# - Second value is a description of the response and the exception error
|
|
45
|
+
# message if an exception occured.
|
|
46
|
+
def perform_with_result
|
|
47
|
+
status = perform
|
|
48
|
+
result =
|
|
49
|
+
case status
|
|
50
|
+
when "200"
|
|
51
|
+
"AppSignal has confirmed authorization!"
|
|
52
|
+
when "401"
|
|
53
|
+
"API key not valid with AppSignal..."
|
|
54
|
+
else
|
|
55
|
+
"Could not confirm authorization: " \
|
|
56
|
+
"#{status.nil? ? "nil" : status}"
|
|
57
|
+
end
|
|
58
|
+
[status, result]
|
|
59
|
+
rescue => e
|
|
60
|
+
result = "Something went wrong while trying to "\
|
|
61
|
+
"authenticate with AppSignal: #{e}"
|
|
62
|
+
[nil, result]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require "appsignal"
|
|
2
|
+
require "capistrano/version"
|
|
3
|
+
|
|
4
|
+
if defined?(Capistrano::VERSION) && Gem::Version.new(Capistrano::VERSION) >= Gem::Version.new(3)
|
|
5
|
+
# Capistrano 3+
|
|
6
|
+
load File.expand_path("../integrations/capistrano/appsignal.cap", __FILE__)
|
|
7
|
+
else
|
|
8
|
+
# Capistrano 2
|
|
9
|
+
require "appsignal/integrations/capistrano/capistrano_2_tasks"
|
|
10
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
require "logger"
|
|
3
|
+
require "appsignal"
|
|
4
|
+
require "appsignal/cli/helpers"
|
|
5
|
+
require "appsignal/cli/demo"
|
|
6
|
+
require "appsignal/cli/diagnose"
|
|
7
|
+
require "appsignal/cli/install"
|
|
8
|
+
require "appsignal/cli/notify_of_deploy"
|
|
9
|
+
|
|
10
|
+
module Appsignal
|
|
11
|
+
# @api private
|
|
12
|
+
class CLI
|
|
13
|
+
AVAILABLE_COMMANDS = %w[demo diagnose install notify_of_deploy].freeze
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
attr_accessor :options
|
|
17
|
+
|
|
18
|
+
def run(argv = ARGV)
|
|
19
|
+
@options = {}
|
|
20
|
+
global = global_option_parser
|
|
21
|
+
commands = command_option_parser
|
|
22
|
+
global.order!(argv)
|
|
23
|
+
command = argv.shift
|
|
24
|
+
if command
|
|
25
|
+
if AVAILABLE_COMMANDS.include?(command)
|
|
26
|
+
commands[command].parse!(argv)
|
|
27
|
+
case command.to_sym
|
|
28
|
+
when :demo
|
|
29
|
+
Appsignal::CLI::Demo.run(options)
|
|
30
|
+
when :diagnose
|
|
31
|
+
Appsignal::CLI::Diagnose.run(options)
|
|
32
|
+
when :install
|
|
33
|
+
Appsignal::CLI::Install.run(argv.shift)
|
|
34
|
+
when :notify_of_deploy
|
|
35
|
+
Appsignal::CLI::NotifyOfDeploy.run(options)
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
puts "Command '#{command}' does not exist, run appsignal -h to "\
|
|
39
|
+
"see the help"
|
|
40
|
+
exit(1)
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
# Print help
|
|
44
|
+
puts global
|
|
45
|
+
exit(0)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def global_option_parser
|
|
50
|
+
OptionParser.new do |o|
|
|
51
|
+
o.banner = "Usage: appsignal <command> [options]"
|
|
52
|
+
|
|
53
|
+
o.on "-v", "--version", "Print version and exit" do |_arg|
|
|
54
|
+
puts "AppSignal #{Appsignal::VERSION}"
|
|
55
|
+
exit(0)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
o.on "-h", "--help", "Show help and exit" do
|
|
59
|
+
puts o
|
|
60
|
+
exit(0)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
o.separator ""
|
|
64
|
+
o.separator "Available commands: #{AVAILABLE_COMMANDS.join(", ")}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def command_option_parser
|
|
69
|
+
{
|
|
70
|
+
"demo" => OptionParser.new do |o|
|
|
71
|
+
o.banner = "Usage: appsignal demo [options]"
|
|
72
|
+
|
|
73
|
+
o.on "--environment=<app_env>", "The environment to demo" do |arg|
|
|
74
|
+
options[:environment] = arg
|
|
75
|
+
end
|
|
76
|
+
end,
|
|
77
|
+
"diagnose" => OptionParser.new do |o|
|
|
78
|
+
o.banner = "Usage: appsignal diagnose [options]"
|
|
79
|
+
|
|
80
|
+
o.on "--environment=<app_env>", "The environment to diagnose" do |arg|
|
|
81
|
+
options[:environment] = arg
|
|
82
|
+
end
|
|
83
|
+
end,
|
|
84
|
+
"install" => OptionParser.new,
|
|
85
|
+
"notify_of_deploy" => OptionParser.new do |o|
|
|
86
|
+
o.banner = "Usage: appsignal notify_of_deploy [options]"
|
|
87
|
+
|
|
88
|
+
o.on "--revision=<revision>", "The revision you're deploying" do |arg|
|
|
89
|
+
options[:revision] = arg
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
o.on "--user=<user>", "The name of the user that's deploying" do |arg|
|
|
93
|
+
options[:user] = arg
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
o.on "--environment=<app_env>", "The environment you're deploying to" do |arg|
|
|
97
|
+
options[:environment] = arg
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
o.on "--name=<name>", "The name of the app (optional)" do |arg|
|
|
101
|
+
options[:name] = arg
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
}
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require "appsignal/demo"
|
|
2
|
+
|
|
3
|
+
module Appsignal
|
|
4
|
+
class CLI
|
|
5
|
+
# Command line tool for sending demonstration samples to AppSignal.com
|
|
6
|
+
#
|
|
7
|
+
# This command line tool is useful when testing AppSignal on a system and
|
|
8
|
+
# validating the local configuration. It tests if the installation of
|
|
9
|
+
# AppSignal has succeeded and if the AppSignal agent is able to run on the
|
|
10
|
+
# machine's architecture and communicate with the AppSignal servers.
|
|
11
|
+
#
|
|
12
|
+
# The same test is also run during installation with
|
|
13
|
+
# {Appsignal::CLI::Install}.
|
|
14
|
+
#
|
|
15
|
+
# ## Exit codes
|
|
16
|
+
#
|
|
17
|
+
# - Exits with status code `0` if the demo command has finished.
|
|
18
|
+
# - Exits with status code `1` if the demo command failed to finished.
|
|
19
|
+
#
|
|
20
|
+
# @example On the command line in your project
|
|
21
|
+
# appsignal demo
|
|
22
|
+
#
|
|
23
|
+
# @example With a specific environment
|
|
24
|
+
# appsignal demo --environment=production
|
|
25
|
+
#
|
|
26
|
+
# @example Standalone run
|
|
27
|
+
# gem install appsignal
|
|
28
|
+
# export APPSIGNAL_APP_NAME="My test app"
|
|
29
|
+
# export APPSIGNAL_APP_ENV="test"
|
|
30
|
+
# export APPSIGNAL_PUSH_API_KEY="xxxx-xxxx-xxxx-xxxx"
|
|
31
|
+
# appsignal demo
|
|
32
|
+
#
|
|
33
|
+
# @since 2.0.0
|
|
34
|
+
# @see Appsignal::Demo
|
|
35
|
+
# @see Appsignal::CLI::Install
|
|
36
|
+
# @see http://docs.appsignal.com/ruby/command-line/demo.html
|
|
37
|
+
# AppSignal demo documentation
|
|
38
|
+
# @see http://docs.appsignal.com/support/debugging.html
|
|
39
|
+
# Debugging AppSignal guide
|
|
40
|
+
# @api private
|
|
41
|
+
class Demo
|
|
42
|
+
class << self
|
|
43
|
+
# @param options [Hash]
|
|
44
|
+
# @option options :environment [String] environment to load
|
|
45
|
+
# configuration for.
|
|
46
|
+
# @return [void]
|
|
47
|
+
def run(options = {})
|
|
48
|
+
ENV["APPSIGNAL_APP_ENV"] = options[:environment] if options[:environment]
|
|
49
|
+
|
|
50
|
+
puts "Sending demonstration sample data..."
|
|
51
|
+
if Appsignal::Demo.transmit
|
|
52
|
+
puts "Demonstration sample data sent!"
|
|
53
|
+
puts "It may take about a minute for the data to appear on https://appsignal.com/accounts"
|
|
54
|
+
else
|
|
55
|
+
puts "Error: Unable to start the AppSignal agent and send data to AppSignal.com"
|
|
56
|
+
puts "Please use `appsignal diagnose` to debug your configuration."
|
|
57
|
+
exit 1
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
require "rbconfig"
|
|
2
|
+
require "bundler/cli"
|
|
3
|
+
require "bundler/cli/common"
|
|
4
|
+
require "etc"
|
|
5
|
+
|
|
6
|
+
module Appsignal
|
|
7
|
+
class CLI
|
|
8
|
+
# Command line tool to run diagnostics on your project.
|
|
9
|
+
#
|
|
10
|
+
# This command line tool is useful when testing AppSignal on a system and
|
|
11
|
+
# validating the local configuration. It outputs useful information to
|
|
12
|
+
# debug issues and it checks if AppSignal agent is able to run on the
|
|
13
|
+
# machine's architecture and communicate with the AppSignal servers.
|
|
14
|
+
#
|
|
15
|
+
# This diagnostic tool outputs the following:
|
|
16
|
+
# - if AppSignal can run on the host system.
|
|
17
|
+
# - if the configuration is valid and active.
|
|
18
|
+
# - if the Push API key is present and valid (internet connection required).
|
|
19
|
+
# - if the required system paths exist and are writable.
|
|
20
|
+
# - outputs AppSignal version information.
|
|
21
|
+
# - outputs information about the host system and Ruby.
|
|
22
|
+
# - outputs last lines from the available log files.
|
|
23
|
+
#
|
|
24
|
+
# ## Exit codes
|
|
25
|
+
#
|
|
26
|
+
# - Exits with status code `0` if the diagnose command has finished.
|
|
27
|
+
# - Exits with status code `1` if the diagnose command failed to finished.
|
|
28
|
+
#
|
|
29
|
+
# @example On the command line in your project
|
|
30
|
+
# appsignal diagnose
|
|
31
|
+
#
|
|
32
|
+
# @example With a specific environment
|
|
33
|
+
# appsignal diagnose --environment=production
|
|
34
|
+
#
|
|
35
|
+
# @see http://docs.appsignal.com/support/debugging.html Debugging AppSignal
|
|
36
|
+
# @see http://docs.appsignal.com/ruby/command-line/diagnose.html
|
|
37
|
+
# AppSignal diagnose documentation
|
|
38
|
+
# @since 1.1.0
|
|
39
|
+
class Diagnose
|
|
40
|
+
extend CLI::Helpers
|
|
41
|
+
|
|
42
|
+
DIAGNOSE_ENDPOINT = "https://appsignal.com/diag".freeze
|
|
43
|
+
|
|
44
|
+
module Data
|
|
45
|
+
def data
|
|
46
|
+
@data ||= Hash.new { |hash, key| hash[key] = {} }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def data_section(key)
|
|
50
|
+
@section = key
|
|
51
|
+
yield
|
|
52
|
+
@section = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def current_section
|
|
56
|
+
@section
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def save(key, value)
|
|
60
|
+
data[current_section][key] = value
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
extend Data
|
|
64
|
+
|
|
65
|
+
class << self
|
|
66
|
+
# @param options [Hash]
|
|
67
|
+
# @option options :environment [String] environment to load
|
|
68
|
+
# configuration for.
|
|
69
|
+
# @return [void]
|
|
70
|
+
# @api private
|
|
71
|
+
def run(options = {})
|
|
72
|
+
$stdout.sync = true
|
|
73
|
+
header
|
|
74
|
+
empty_line
|
|
75
|
+
|
|
76
|
+
library_information
|
|
77
|
+
empty_line
|
|
78
|
+
|
|
79
|
+
host_information
|
|
80
|
+
empty_line
|
|
81
|
+
|
|
82
|
+
configure_appsignal(options)
|
|
83
|
+
run_agent_diagnose_mode
|
|
84
|
+
empty_line
|
|
85
|
+
|
|
86
|
+
config
|
|
87
|
+
empty_line
|
|
88
|
+
|
|
89
|
+
check_api_key
|
|
90
|
+
empty_line
|
|
91
|
+
|
|
92
|
+
paths_section
|
|
93
|
+
empty_line
|
|
94
|
+
|
|
95
|
+
log_files
|
|
96
|
+
|
|
97
|
+
transmit_report_to_appsignal if send_report_to_appsignal?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def send_report_to_appsignal?
|
|
103
|
+
puts "\nDiagnostics report"
|
|
104
|
+
puts " Do you want to send this diagnostics report to AppSignal?"
|
|
105
|
+
puts " If you share this diagnostics report you will be given\n" \
|
|
106
|
+
" a support token you can use to refer to your diagnotics \n" \
|
|
107
|
+
" report when you contact us at support@appsignal.com\n\n"
|
|
108
|
+
send_diagnostics = yes_or_no(
|
|
109
|
+
" Send diagnostics report to AppSignal? (Y/n): ",
|
|
110
|
+
:default => "y"
|
|
111
|
+
)
|
|
112
|
+
unless send_diagnostics
|
|
113
|
+
puts " Not sending diagnostics information to AppSignal."
|
|
114
|
+
return false
|
|
115
|
+
end
|
|
116
|
+
true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def transmit_report_to_appsignal
|
|
120
|
+
puts "\n Transmitting diagnostics report"
|
|
121
|
+
transmitter = Transmitter.new(
|
|
122
|
+
DIAGNOSE_ENDPOINT,
|
|
123
|
+
Appsignal.config
|
|
124
|
+
)
|
|
125
|
+
response = transmitter.transmit(:diagnose => data)
|
|
126
|
+
|
|
127
|
+
unless response.code == "200"
|
|
128
|
+
puts " Error: Something went wrong while submitting the report "\
|
|
129
|
+
"to AppSignal."
|
|
130
|
+
puts " Response code: #{response.code}"
|
|
131
|
+
puts " Response body:\n#{response.body}"
|
|
132
|
+
return
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
puts " Please email us at support@appsignal.com with the following"
|
|
136
|
+
puts " support token."
|
|
137
|
+
begin
|
|
138
|
+
response_data = JSON.parse(response.body)
|
|
139
|
+
puts " Your support token: #{response_data["token"]}"
|
|
140
|
+
rescue JSON::ParserError
|
|
141
|
+
puts " Error: Couldn't decode server response."
|
|
142
|
+
puts " #{response.body}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def puts_and_save(key, label, value)
|
|
147
|
+
save key, value
|
|
148
|
+
puts_value label, value
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def puts_value(label, value, options = {})
|
|
152
|
+
options[:level] ||= 1
|
|
153
|
+
puts "#{" " * options[:level]}#{label}: #{value}"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def configure_appsignal(options)
|
|
157
|
+
current_path = Dir.pwd
|
|
158
|
+
initial_config = {}
|
|
159
|
+
if rails_app?
|
|
160
|
+
data[:app][:rails] = true
|
|
161
|
+
current_path = Rails.root
|
|
162
|
+
initial_config[:name] = Rails.application.class.parent_name
|
|
163
|
+
initial_config[:log_path] = current_path.join("log")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
Appsignal.config = Appsignal::Config.new(
|
|
167
|
+
current_path,
|
|
168
|
+
options[:environment],
|
|
169
|
+
initial_config
|
|
170
|
+
)
|
|
171
|
+
Appsignal.config.write_to_environment
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def run_agent_diagnose_mode
|
|
175
|
+
puts "Agent diagnostics"
|
|
176
|
+
unless Appsignal.extension_loaded?
|
|
177
|
+
puts " Extension is not loaded. No agent report created."
|
|
178
|
+
return
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
ENV["_APPSIGNAL_DIAGNOSE"] = "true"
|
|
182
|
+
diagnostics_report_string = Appsignal::Extension.diagnose
|
|
183
|
+
ENV.delete("_APPSIGNAL_DIAGNOSE")
|
|
184
|
+
|
|
185
|
+
begin
|
|
186
|
+
report = JSON.parse(diagnostics_report_string)
|
|
187
|
+
data[:agent] = report
|
|
188
|
+
print_agent_report(report)
|
|
189
|
+
rescue JSON::ParserError => error
|
|
190
|
+
puts " Error while parsing agent diagnostics report:"
|
|
191
|
+
puts " Error: #{error}"
|
|
192
|
+
puts " Output: #{diagnostics_report_string}"
|
|
193
|
+
data[:agent] = {
|
|
194
|
+
:error => error,
|
|
195
|
+
:output => diagnostics_report_string.split("\n")
|
|
196
|
+
}
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def print_agent_report(report)
|
|
201
|
+
if report["error"]
|
|
202
|
+
puts " Error: #{report["error"]}"
|
|
203
|
+
return
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
agent_diagnostic_test_definition.each do |part, categories|
|
|
207
|
+
categories.each do |category, tests|
|
|
208
|
+
tests.each do |test_name, test_definition|
|
|
209
|
+
test_report = report
|
|
210
|
+
.fetch(part, {})
|
|
211
|
+
.fetch(category, {})
|
|
212
|
+
.fetch(test_name, {})
|
|
213
|
+
|
|
214
|
+
print_agent_test(test_definition, test_report)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def print_agent_test(definition, test)
|
|
221
|
+
value = test["result"]
|
|
222
|
+
error = test["error"]
|
|
223
|
+
output = test["output"]
|
|
224
|
+
|
|
225
|
+
print " #{definition[:label]}: "
|
|
226
|
+
display_value = definition[:values][value]
|
|
227
|
+
print display_value.nil? ? "-" : display_value
|
|
228
|
+
print "\n Error: #{error}" if error
|
|
229
|
+
print "\n Output: #{output}" if output
|
|
230
|
+
print "\n"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def agent_diagnostic_test_definition
|
|
234
|
+
{
|
|
235
|
+
"extension" => {
|
|
236
|
+
"config" => {
|
|
237
|
+
"valid" => {
|
|
238
|
+
:label => "Extension config",
|
|
239
|
+
:values => { true => "valid", false => "invalid" }
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
"agent" => {
|
|
244
|
+
"boot" => {
|
|
245
|
+
"started" => {
|
|
246
|
+
:label => "Agent started",
|
|
247
|
+
:values => { true => "started", false => "not started" }
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"config" => {
|
|
251
|
+
"valid" => {
|
|
252
|
+
:label => "Agent config",
|
|
253
|
+
:values => { true => "valid", false => "invalid" }
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"logger" => {
|
|
257
|
+
"started" => {
|
|
258
|
+
:label => "Agent logger",
|
|
259
|
+
:values => { true => "started", false => "not started" }
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"lock_path" => {
|
|
263
|
+
"created" => {
|
|
264
|
+
:label => "Agent lock path",
|
|
265
|
+
:values => { true => "writable", false => "not writable" }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def header
|
|
273
|
+
puts "AppSignal diagnose"
|
|
274
|
+
puts "=" * 80
|
|
275
|
+
puts "Use this information to debug your configuration."
|
|
276
|
+
puts "More information is available on the documentation site."
|
|
277
|
+
puts "http://docs.appsignal.com/"
|
|
278
|
+
puts "Send this output to support@appsignal.com if you need help."
|
|
279
|
+
puts "=" * 80
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def library_information
|
|
283
|
+
puts "AppSignal library"
|
|
284
|
+
data_section :library do
|
|
285
|
+
save :language, "ruby"
|
|
286
|
+
puts_and_save :package_version, "Gem version", Appsignal::VERSION
|
|
287
|
+
puts_and_save :agent_version, "Agent version", Appsignal::Extension.agent_version
|
|
288
|
+
puts_and_save :agent_architecture, "Agent architecture",
|
|
289
|
+
Appsignal::System.installed_agent_architecture
|
|
290
|
+
puts_and_save :package_install_path, "Gem install path", gem_path
|
|
291
|
+
puts_and_save :extension_loaded, "Extension loaded", Appsignal.extension_loaded
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def host_information
|
|
296
|
+
rbconfig = RbConfig::CONFIG
|
|
297
|
+
puts "Host information"
|
|
298
|
+
data_section :host do
|
|
299
|
+
puts_and_save :architecture, "Architecture", rbconfig["host_cpu"]
|
|
300
|
+
|
|
301
|
+
os_label = os = rbconfig["host_os"]
|
|
302
|
+
os_label = "#{os} (Microsoft Windows is not supported.)" if Gem.win_platform?
|
|
303
|
+
save :os, os
|
|
304
|
+
puts_value "Operating System", os_label
|
|
305
|
+
|
|
306
|
+
puts_and_save :language_version, "Ruby version",
|
|
307
|
+
"#{rbconfig["ruby_version"]}-p#{rbconfig["PATCHLEVEL"]}"
|
|
308
|
+
|
|
309
|
+
puts_value "Heroku", "true" if Appsignal::System.heroku?
|
|
310
|
+
save :heroku, Appsignal::System.heroku?
|
|
311
|
+
|
|
312
|
+
save :root, Process.uid.zero?
|
|
313
|
+
puts_value "root user",
|
|
314
|
+
Process.uid.zero? ? "true (not recommended)" : "false"
|
|
315
|
+
puts_and_save :running_in_container, "Running in container",
|
|
316
|
+
Appsignal::Extension.running_in_container?
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def config
|
|
321
|
+
puts "Configuration"
|
|
322
|
+
data_section :config do
|
|
323
|
+
puts_environment
|
|
324
|
+
|
|
325
|
+
Appsignal.config.config_hash.each do |key, value|
|
|
326
|
+
puts_and_save key, key, value
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def puts_environment
|
|
332
|
+
env = Appsignal.config.env
|
|
333
|
+
puts_and_save :env, "Environment", env
|
|
334
|
+
|
|
335
|
+
return unless env == ""
|
|
336
|
+
puts " Warning: No environment set, no config loaded!"
|
|
337
|
+
puts " Please make sure appsignal diagnose is run within your "
|
|
338
|
+
puts " project directory with an environment."
|
|
339
|
+
puts " appsignal diagnose --environment=production"
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def paths_section
|
|
343
|
+
puts "Paths"
|
|
344
|
+
data[:process] = process_user
|
|
345
|
+
data_section :paths do
|
|
346
|
+
appsignal_paths.each do |name, path|
|
|
347
|
+
path_info = {
|
|
348
|
+
:path => path,
|
|
349
|
+
:configured => !path.nil?,
|
|
350
|
+
:exists => false,
|
|
351
|
+
:writable => false
|
|
352
|
+
}
|
|
353
|
+
save name, path_info
|
|
354
|
+
|
|
355
|
+
puts_value name, path.to_s.inspect
|
|
356
|
+
|
|
357
|
+
unless path_info[:configured]
|
|
358
|
+
puts_value "Configured?", "false", :level => 2
|
|
359
|
+
next
|
|
360
|
+
end
|
|
361
|
+
unless File.exist?(path)
|
|
362
|
+
puts_value "Exists?", "false", :level => 2
|
|
363
|
+
next
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
path_info[:exists] = true
|
|
367
|
+
path_info[:writable] = File.writable?(path)
|
|
368
|
+
puts_value "Writable?", path_info[:writable], :level => 2
|
|
369
|
+
|
|
370
|
+
file_owner = path_ownership(path)
|
|
371
|
+
path_info[:ownership] = file_owner
|
|
372
|
+
save name, path_info
|
|
373
|
+
|
|
374
|
+
owned = process_user[:uid] == file_owner[:uid]
|
|
375
|
+
owner = "#{owned} " \
|
|
376
|
+
"(file: #{file_owner[:user]}:#{file_owner[:uid]}, " \
|
|
377
|
+
"process: #{process_user[:user]}:#{process_user[:uid]})"
|
|
378
|
+
puts_value "Ownership?", owner, :level => 2
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def path_ownership(path)
|
|
384
|
+
file_uid = File.stat(path).uid
|
|
385
|
+
{
|
|
386
|
+
:uid => file_uid,
|
|
387
|
+
:user => username_for_uid(file_uid)
|
|
388
|
+
}
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def process_user
|
|
392
|
+
return @process_user if defined?(@process_user)
|
|
393
|
+
|
|
394
|
+
process_uid = Process.uid
|
|
395
|
+
@process_user = {
|
|
396
|
+
:uid => process_uid,
|
|
397
|
+
:user => username_for_uid(process_uid)
|
|
398
|
+
}
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def appsignal_paths
|
|
402
|
+
config = Appsignal.config
|
|
403
|
+
log_file_path = config.log_file_path
|
|
404
|
+
{
|
|
405
|
+
:working_dir => Dir.pwd,
|
|
406
|
+
:root_path => config.root_path,
|
|
407
|
+
:log_dir_path => log_file_path ? File.dirname(log_file_path) : "",
|
|
408
|
+
:log_file_path => log_file_path
|
|
409
|
+
}
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def check_api_key
|
|
413
|
+
puts "Validation"
|
|
414
|
+
data_section :validation do
|
|
415
|
+
auth_check = ::Appsignal::AuthCheck.new(Appsignal.config)
|
|
416
|
+
status, error = auth_check.perform_with_result
|
|
417
|
+
result =
|
|
418
|
+
case status
|
|
419
|
+
when "200"
|
|
420
|
+
"valid"
|
|
421
|
+
when "401"
|
|
422
|
+
"invalid"
|
|
423
|
+
else
|
|
424
|
+
"Failed with status #{status}\n#{error.inspect}"
|
|
425
|
+
end
|
|
426
|
+
puts_and_save :push_api_key, "Validating Push API key", result
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def log_files
|
|
431
|
+
puts "Log files"
|
|
432
|
+
data_section :logs do
|
|
433
|
+
install_log
|
|
434
|
+
empty_line
|
|
435
|
+
mkmf_log
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def install_log
|
|
440
|
+
puts " Extension install log"
|
|
441
|
+
filename = File.join("ext", "install.log")
|
|
442
|
+
log_info = log_file_info(File.join(gem_path, filename))
|
|
443
|
+
save filename, log_info
|
|
444
|
+
puts_log_file log_info
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def mkmf_log
|
|
448
|
+
puts " Makefile install log"
|
|
449
|
+
filename = File.join("ext", "mkmf.log")
|
|
450
|
+
log_info = log_file_info(File.join(gem_path, filename))
|
|
451
|
+
save filename, log_info
|
|
452
|
+
puts_log_file log_info
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def log_file_info(log_file)
|
|
456
|
+
{
|
|
457
|
+
:path => log_file,
|
|
458
|
+
:exists => File.exist?(log_file)
|
|
459
|
+
}.tap do |info|
|
|
460
|
+
next unless info[:exists]
|
|
461
|
+
info[:content] = File.read(log_file).split("\n")
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def puts_log_file(log_info)
|
|
466
|
+
puts_value "Path", log_info[:path].to_s.inspect, :level => 2
|
|
467
|
+
if log_info[:exists]
|
|
468
|
+
puts " Contents:"
|
|
469
|
+
puts log_info[:content].join("\n")
|
|
470
|
+
else
|
|
471
|
+
puts " File not found."
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def username_for_uid(uid)
|
|
476
|
+
passwd_struct = Etc.getpwuid(uid)
|
|
477
|
+
return unless passwd_struct
|
|
478
|
+
passwd_struct.name
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def empty_line
|
|
482
|
+
puts "\n"
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def rails_app?
|
|
486
|
+
require "rails"
|
|
487
|
+
require File.expand_path(File.join(Dir.pwd, "config", "application.rb"))
|
|
488
|
+
true
|
|
489
|
+
rescue LoadError
|
|
490
|
+
false
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def gem_path
|
|
494
|
+
@gem_path ||= \
|
|
495
|
+
Bundler::CLI::Common.select_spec("appsignal").full_gem_path.strip
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
end
|