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,287 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "yaml"
|
3
|
+
require "uri"
|
4
|
+
require "socket"
|
5
|
+
require "tmpdir"
|
6
|
+
|
7
|
+
module Appsignal
|
8
|
+
class Config
|
9
|
+
DEFAULT_CONFIG = {
|
10
|
+
:debug => false,
|
11
|
+
:log => "file",
|
12
|
+
:ignore_actions => [],
|
13
|
+
:ignore_errors => [],
|
14
|
+
:ignore_namespaces => [],
|
15
|
+
:filter_parameters => [],
|
16
|
+
:send_params => true,
|
17
|
+
:endpoint => "https://push.appsignal.com",
|
18
|
+
:instrument_net_http => true,
|
19
|
+
:instrument_redis => true,
|
20
|
+
:instrument_sequel => true,
|
21
|
+
:skip_session_data => false,
|
22
|
+
:enable_frontend_error_catching => false,
|
23
|
+
:frontend_error_catching_path => "/appsignal_error_catcher",
|
24
|
+
:enable_allocation_tracking => true,
|
25
|
+
:enable_gc_instrumentation => false,
|
26
|
+
:enable_host_metrics => true,
|
27
|
+
:enable_minutely_probes => false,
|
28
|
+
:hostname => ::Socket.gethostname,
|
29
|
+
:ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
|
30
|
+
:dns_servers => [],
|
31
|
+
:files_world_accessible => true
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
ENV_TO_KEY_MAPPING = {
|
35
|
+
"APPSIGNAL_ACTIVE" => :active,
|
36
|
+
"APPSIGNAL_PUSH_API_KEY" => :push_api_key,
|
37
|
+
"APPSIGNAL_APP_NAME" => :name,
|
38
|
+
"APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
|
39
|
+
"APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH" => :frontend_error_catching_path,
|
40
|
+
"APPSIGNAL_DEBUG" => :debug,
|
41
|
+
"APPSIGNAL_LOG" => :log,
|
42
|
+
"APPSIGNAL_LOG_PATH" => :log_path,
|
43
|
+
"APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
|
44
|
+
"APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
|
45
|
+
"APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
|
46
|
+
"APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
|
47
|
+
"APPSIGNAL_ENABLE_FRONTEND_ERROR_CATCHING" => :enable_frontend_error_catching,
|
48
|
+
"APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
|
49
|
+
"APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
|
50
|
+
"APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
|
51
|
+
"APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
|
52
|
+
"APPSIGNAL_SEND_PARAMS" => :send_params,
|
53
|
+
"APPSIGNAL_HTTP_PROXY" => :http_proxy,
|
54
|
+
"APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
|
55
|
+
"APPSIGNAL_ENABLE_GC_INSTRUMENTATION" => :enable_gc_instrumentation,
|
56
|
+
"APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
|
57
|
+
"APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
|
58
|
+
"APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
|
59
|
+
"APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
|
60
|
+
"APPSIGNAL_HOSTNAME" => :hostname,
|
61
|
+
"APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
|
62
|
+
"APPSIGNAL_DNS_SERVERS" => :dns_servers,
|
63
|
+
"APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible
|
64
|
+
}.freeze
|
65
|
+
|
66
|
+
# Mapping of old and deprecated AppSignal configuration keys
|
67
|
+
DEPRECATED_CONFIG_KEY_MAPPING = {
|
68
|
+
:api_key => :push_api_key,
|
69
|
+
:ignore_exceptions => :ignore_errors
|
70
|
+
}.freeze
|
71
|
+
|
72
|
+
attr_reader :root_path, :env, :initial_config, :config_hash
|
73
|
+
attr_accessor :logger
|
74
|
+
|
75
|
+
def initialize(root_path, env, initial_config = {}, logger = Appsignal.logger)
|
76
|
+
@root_path = root_path
|
77
|
+
@env = ENV.fetch("APPSIGNAL_APP_ENV".freeze, env.to_s)
|
78
|
+
@initial_config = initial_config
|
79
|
+
@logger = logger
|
80
|
+
@valid = false
|
81
|
+
@config_hash = Hash[DEFAULT_CONFIG]
|
82
|
+
|
83
|
+
# Set config based on the system
|
84
|
+
detect_from_system
|
85
|
+
# Initial config
|
86
|
+
merge(@config_hash, initial_config)
|
87
|
+
# Load the config file if it exists
|
88
|
+
load_from_disk
|
89
|
+
# Load config from environment variables
|
90
|
+
load_from_environment
|
91
|
+
# Validate that we have a correct config
|
92
|
+
validate
|
93
|
+
end
|
94
|
+
|
95
|
+
# @api private
|
96
|
+
# @return [String] System's tmp directory.
|
97
|
+
def self.system_tmp_dir
|
98
|
+
if Gem.win_platform?
|
99
|
+
Dir.tmpdir
|
100
|
+
else
|
101
|
+
File.realpath("/tmp")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def [](key)
|
106
|
+
config_hash[key]
|
107
|
+
end
|
108
|
+
|
109
|
+
def []=(key, value)
|
110
|
+
config_hash[key] = value
|
111
|
+
end
|
112
|
+
|
113
|
+
def log_file_path
|
114
|
+
path = config_hash[:log_path] || root_path && File.join(root_path, "log")
|
115
|
+
if path && File.writable?(path)
|
116
|
+
return File.join(File.realpath(path), "appsignal.log")
|
117
|
+
end
|
118
|
+
|
119
|
+
system_tmp_dir = self.class.system_tmp_dir
|
120
|
+
if File.writable? system_tmp_dir
|
121
|
+
$stdout.puts "appsignal: Unable to log to '#{path}'. Logging to "\
|
122
|
+
"'#{system_tmp_dir}' instead. Please check the "\
|
123
|
+
"permissions for the application's (log) directory."
|
124
|
+
File.join(system_tmp_dir, "appsignal.log")
|
125
|
+
else
|
126
|
+
$stdout.puts "appsignal: Unable to log to '#{path}' or the "\
|
127
|
+
"'#{system_tmp_dir}' fallback. Please check the permissions "\
|
128
|
+
"for the application's (log) directory."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def valid?
|
133
|
+
@valid
|
134
|
+
end
|
135
|
+
|
136
|
+
def active?
|
137
|
+
@valid && config_hash[:active]
|
138
|
+
end
|
139
|
+
|
140
|
+
def write_to_environment # rubocop:disable Metrics/AbcSize
|
141
|
+
ENV["_APPSIGNAL_ACTIVE"] = active?.to_s
|
142
|
+
ENV["_APPSIGNAL_APP_PATH"] = root_path.to_s
|
143
|
+
ENV["_APPSIGNAL_AGENT_PATH"] = File.expand_path("../../../ext", __FILE__).to_s
|
144
|
+
ENV["_APPSIGNAL_ENVIRONMENT"] = env
|
145
|
+
ENV["_APPSIGNAL_AGENT_VERSION"] = Appsignal::Extension.agent_version
|
146
|
+
ENV["_APPSIGNAL_LANGUAGE_INTEGRATION_VERSION"] = "ruby-#{Appsignal::VERSION}"
|
147
|
+
ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
|
148
|
+
ENV["_APPSIGNAL_LOG"] = config_hash[:log]
|
149
|
+
ENV["_APPSIGNAL_LOG_FILE_PATH"] = log_file_path.to_s if log_file_path
|
150
|
+
ENV["_APPSIGNAL_PUSH_API_ENDPOINT"] = config_hash[:endpoint]
|
151
|
+
ENV["_APPSIGNAL_PUSH_API_KEY"] = config_hash[:push_api_key]
|
152
|
+
ENV["_APPSIGNAL_APP_NAME"] = config_hash[:name]
|
153
|
+
ENV["_APPSIGNAL_HTTP_PROXY"] = config_hash[:http_proxy]
|
154
|
+
ENV["_APPSIGNAL_IGNORE_ACTIONS"] = config_hash[:ignore_actions].join(",")
|
155
|
+
ENV["_APPSIGNAL_IGNORE_ERRORS"] = config_hash[:ignore_errors].join(",")
|
156
|
+
ENV["_APPSIGNAL_IGNORE_NAMESPACES"] = config_hash[:ignore_namespaces].join(",")
|
157
|
+
ENV["_APPSIGNAL_FILTER_PARAMETERS"] = config_hash[:filter_parameters].join(",")
|
158
|
+
ENV["_APPSIGNAL_SEND_PARAMS"] = config_hash[:send_params].to_s
|
159
|
+
ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"] = config_hash[:running_in_container].to_s
|
160
|
+
ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path] if config_hash[:working_dir_path]
|
161
|
+
ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
|
162
|
+
ENV["_APPSIGNAL_ENABLE_MINUTELY_PROBES"] = config_hash[:enable_minutely_probes].to_s
|
163
|
+
ENV["_APPSIGNAL_HOSTNAME"] = config_hash[:hostname].to_s
|
164
|
+
ENV["_APPSIGNAL_PROCESS_NAME"] = $PROGRAM_NAME
|
165
|
+
ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
|
166
|
+
ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
|
167
|
+
ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = config_hash[:files_world_accessible].to_s
|
168
|
+
end
|
169
|
+
|
170
|
+
def validate
|
171
|
+
# Strip path from endpoint so we're backwards compatible with
|
172
|
+
# earlier versions of the gem.
|
173
|
+
# TODO: Move to its own method, maybe in `#[]=`?
|
174
|
+
endpoint_uri = URI(config_hash[:endpoint])
|
175
|
+
config_hash[:endpoint] =
|
176
|
+
if endpoint_uri.port == 443
|
177
|
+
"#{endpoint_uri.scheme}://#{endpoint_uri.host}"
|
178
|
+
else
|
179
|
+
"#{endpoint_uri.scheme}://#{endpoint_uri.host}:#{endpoint_uri.port}"
|
180
|
+
end
|
181
|
+
|
182
|
+
if config_hash[:push_api_key]
|
183
|
+
@valid = true
|
184
|
+
else
|
185
|
+
@valid = false
|
186
|
+
@logger.error "Push api key not set after loading config"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def config_file
|
193
|
+
@config_file ||=
|
194
|
+
root_path.nil? ? nil : File.join(root_path, "config", "appsignal.yml")
|
195
|
+
end
|
196
|
+
|
197
|
+
def detect_from_system
|
198
|
+
config_hash[:log] = "stdout" if Appsignal::System.heroku?
|
199
|
+
|
200
|
+
# Make active by default if APPSIGNAL_PUSH_API_KEY is present
|
201
|
+
config_hash[:active] = true if ENV["APPSIGNAL_PUSH_API_KEY"]
|
202
|
+
end
|
203
|
+
|
204
|
+
def load_from_disk
|
205
|
+
return if !config_file || !File.exist?(config_file)
|
206
|
+
|
207
|
+
configurations = YAML.load(ERB.new(IO.read(config_file)).result)
|
208
|
+
config_for_this_env = configurations[env]
|
209
|
+
if config_for_this_env
|
210
|
+
config_for_this_env =
|
211
|
+
config_for_this_env.each_with_object({}) do |(key, value), hash|
|
212
|
+
hash[key.to_sym] = value # convert keys to symbols
|
213
|
+
end
|
214
|
+
|
215
|
+
config_for_this_env = maintain_backwards_compatibility(config_for_this_env)
|
216
|
+
|
217
|
+
merge(@config_hash, config_for_this_env)
|
218
|
+
else
|
219
|
+
@logger.error "Not loading from config file: config for '#{env}' not found"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Maintain backwards compatibility with config files generated by earlier
|
224
|
+
# versions of the gem
|
225
|
+
#
|
226
|
+
# Used by {#load_from_disk}. No compatibility for env variables or initial config currently.
|
227
|
+
def maintain_backwards_compatibility(configuration)
|
228
|
+
configuration.tap do |config|
|
229
|
+
DEPRECATED_CONFIG_KEY_MAPPING.each do |old_key, new_key|
|
230
|
+
old_config_value = config.delete(old_key)
|
231
|
+
next unless old_config_value
|
232
|
+
logger.warn "Old configuration key found. Please update the "\
|
233
|
+
"'#{old_key}' to '#{new_key}'."
|
234
|
+
|
235
|
+
next if config[new_key] # Skip if new key is already in use
|
236
|
+
config[new_key] = old_config_value
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def load_from_environment
|
242
|
+
config = {}
|
243
|
+
|
244
|
+
# Configuration with string type
|
245
|
+
%w[APPSIGNAL_PUSH_API_KEY APPSIGNAL_APP_NAME APPSIGNAL_PUSH_API_ENDPOINT
|
246
|
+
APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH APPSIGNAL_HTTP_PROXY
|
247
|
+
APPSIGNAL_LOG APPSIGNAL_LOG_PATH APPSIGNAL_WORKING_DIR_PATH
|
248
|
+
APPSIGNAL_HOSTNAME APPSIGNAL_CA_FILE_PATH].each do |var|
|
249
|
+
env_var = ENV[var]
|
250
|
+
next unless env_var
|
251
|
+
config[ENV_TO_KEY_MAPPING[var]] = env_var
|
252
|
+
end
|
253
|
+
|
254
|
+
# Configuration with boolean type
|
255
|
+
%w[APPSIGNAL_ACTIVE APPSIGNAL_DEBUG APPSIGNAL_INSTRUMENT_NET_HTTP
|
256
|
+
APPSIGNAL_INSTRUMENT_REDIS APPSIGNAL_INSTRUMENT_SEQUEL
|
257
|
+
APPSIGNAL_SKIP_SESSION_DATA APPSIGNAL_ENABLE_FRONTEND_ERROR_CATCHING
|
258
|
+
APPSIGNAL_ENABLE_ALLOCATION_TRACKING APPSIGNAL_ENABLE_GC_INSTRUMENTATION
|
259
|
+
APPSIGNAL_RUNNING_IN_CONTAINER APPSIGNAL_ENABLE_HOST_METRICS
|
260
|
+
APPSIGNAL_SEND_PARAMS APPSIGNAL_ENABLE_MINUTELY_PROBES
|
261
|
+
APPSIGNAL_FILES_WORLD_ACCESSIBLE].each do |var|
|
262
|
+
env_var = ENV[var]
|
263
|
+
next unless env_var
|
264
|
+
config[ENV_TO_KEY_MAPPING[var]] = env_var.casecmp("true").zero?
|
265
|
+
end
|
266
|
+
|
267
|
+
# Configuration with array of strings type
|
268
|
+
%w[APPSIGNAL_IGNORE_ACTIONS APPSIGNAL_IGNORE_ERRORS
|
269
|
+
APPSIGNAL_IGNORE_NAMESPACES APPSIGNAL_FILTER_PARAMETERS].each do |var|
|
270
|
+
env_var = ENV[var]
|
271
|
+
next unless env_var
|
272
|
+
config[ENV_TO_KEY_MAPPING[var]] = env_var.split(",")
|
273
|
+
end
|
274
|
+
|
275
|
+
merge(@config_hash, config)
|
276
|
+
end
|
277
|
+
|
278
|
+
def merge(original_config, new_config)
|
279
|
+
new_config.each do |key, value|
|
280
|
+
unless original_config[key].nil?
|
281
|
+
@logger.debug("Config key '#{key}' is being overwritten")
|
282
|
+
end
|
283
|
+
original_config[key] = value
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "rack/mock"
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
# {Appsignal::Demo} is a way to send demonstration / test samples for a
|
5
|
+
# exception and a performance issue.
|
6
|
+
#
|
7
|
+
# @example Loading config automatically
|
8
|
+
# Appsignal::Demo.transmit
|
9
|
+
#
|
10
|
+
# @example With custom config
|
11
|
+
# # If another configuration should be used, set it beforehand.
|
12
|
+
# Appsignal.config = Appsignal::Config.new(Dir.pwd, "production")
|
13
|
+
# Appsignal::Demo.transmit
|
14
|
+
#
|
15
|
+
# @since 2.0.0
|
16
|
+
# @see Appsignal::CLI::Demo
|
17
|
+
# @api private
|
18
|
+
class Demo
|
19
|
+
# Error type used to create demonstration exception.
|
20
|
+
class TestError < StandardError; end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# Starts AppSignal and transmits the demonstration samples to AppSignal
|
24
|
+
# using the loaded configuration.
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
# - returns `false` if Appsignal is not active.
|
28
|
+
def transmit
|
29
|
+
Appsignal.start
|
30
|
+
Appsignal.start_logger
|
31
|
+
return false unless Appsignal.active?
|
32
|
+
|
33
|
+
create_example_error_request
|
34
|
+
create_example_performance_request
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def create_example_error_request
|
41
|
+
transaction = Appsignal::Transaction.create(
|
42
|
+
SecureRandom.uuid,
|
43
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
44
|
+
rack_request
|
45
|
+
)
|
46
|
+
begin
|
47
|
+
raise TestError,
|
48
|
+
"Hello world! This is an error used for demonstration purposes."
|
49
|
+
rescue => error
|
50
|
+
Appsignal.set_error(error)
|
51
|
+
end
|
52
|
+
transaction.set_http_or_background_queue_start
|
53
|
+
transaction.set_metadata("path", "/hello")
|
54
|
+
transaction.set_metadata("method", "GET")
|
55
|
+
transaction.set_action("DemoController#hello")
|
56
|
+
add_demo_metadata_to transaction
|
57
|
+
Appsignal::Transaction.complete_current!
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_example_performance_request
|
61
|
+
transaction = Appsignal::Transaction.create(
|
62
|
+
SecureRandom.uuid,
|
63
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
64
|
+
rack_request
|
65
|
+
)
|
66
|
+
Appsignal.instrument "action_view.render", "Render hello.html.erb", "<h1>Hello world!</h1>" do
|
67
|
+
sleep 2
|
68
|
+
end
|
69
|
+
transaction.set_http_or_background_queue_start
|
70
|
+
transaction.set_metadata("path", "/hello")
|
71
|
+
transaction.set_metadata("method", "GET")
|
72
|
+
transaction.set_action("DemoController#hello")
|
73
|
+
add_demo_metadata_to transaction
|
74
|
+
Appsignal::Transaction.complete_current!
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_demo_metadata_to(transaction)
|
78
|
+
transaction.set_metadata("demo_sample", "true")
|
79
|
+
end
|
80
|
+
|
81
|
+
def rack_request
|
82
|
+
env = ::Rack::MockRequest.env_for(
|
83
|
+
"/demo",
|
84
|
+
:params => {
|
85
|
+
"controller" => "demo",
|
86
|
+
"action" => "hello"
|
87
|
+
},
|
88
|
+
"REMOTE_ADDR" => "127.0.0.1",
|
89
|
+
"REQUEST_METHOD" => "GET",
|
90
|
+
"SERVER_NAME" => "localhost",
|
91
|
+
"SERVER_PORT" => "80",
|
92
|
+
"SERVER_PROTOCOL" => "HTTP/1.1",
|
93
|
+
"REQUEST_URI" => "/hello",
|
94
|
+
"PATH_INFO" => "/hello",
|
95
|
+
"HTTP_ACCEPT" => "text/html,application/xhtml+xml",
|
96
|
+
"HTTP_ACCEPT_ENCODING" => "gzip, deflate, sdch",
|
97
|
+
"HTTP_ACCEPT_LANGUAGE" => "en-US,en;q=0.8,nl;q=0.6",
|
98
|
+
"HTTP_CACHE_CONTROL" => "max-age=0",
|
99
|
+
"HTTP_CONNECTION" => "keep-alive",
|
100
|
+
"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0)",
|
101
|
+
"HTTP_REFERER" => "http://appsignal.com/accounts"
|
102
|
+
)
|
103
|
+
::Rack::Request.new(env)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Appsignal
|
2
|
+
# Keeps track of formatters for types event that we can use to get
|
3
|
+
# the title and body of an event. Formatters should inherit from this class
|
4
|
+
# and implement a format(payload) method which returns an array with the title
|
5
|
+
# and body.
|
6
|
+
#
|
7
|
+
# When implementing a formatter remember that it cannot keep separate state per
|
8
|
+
# event, the same object will be called intermittently in a threaded environment.
|
9
|
+
# So only keep global configuration as state and pass the payload around as an
|
10
|
+
# argument if you need to use helper methods.
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
class EventFormatter
|
14
|
+
class << self
|
15
|
+
def formatters
|
16
|
+
@@formatters ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def formatter_classes
|
20
|
+
@@formatter_classes ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def register(name, formatter = self)
|
24
|
+
formatter_classes[name] = formatter
|
25
|
+
end
|
26
|
+
|
27
|
+
def unregister(name, formatter = self)
|
28
|
+
return unless formatter_classes[name] == formatter
|
29
|
+
|
30
|
+
formatter_classes.delete(name)
|
31
|
+
formatters.delete(name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def registered?(name, klass = nil)
|
35
|
+
if klass
|
36
|
+
formatter_classes[name] == klass
|
37
|
+
else
|
38
|
+
formatter_classes.include?(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize_formatters
|
43
|
+
formatter_classes.each do |name, formatter|
|
44
|
+
begin
|
45
|
+
format_method = formatter.instance_method(:format)
|
46
|
+
if format_method && format_method.arity == 1
|
47
|
+
formatters[name] = formatter.new
|
48
|
+
else
|
49
|
+
raise "#{f} does not have a format(payload) method"
|
50
|
+
end
|
51
|
+
rescue => ex
|
52
|
+
formatter_classes.delete(name)
|
53
|
+
formatters.delete(name)
|
54
|
+
Appsignal.logger.debug("'#{ex.message}' when initializing #{name} event formatter")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def format(name, payload)
|
60
|
+
formatter = formatters[name]
|
61
|
+
formatter.format(payload) unless formatter.nil?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @api public
|
66
|
+
DEFAULT = 0
|
67
|
+
# @api public
|
68
|
+
SQL_BODY_FORMAT = 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Dir.glob(File.expand_path("../event_formatter/**/*.rb", __FILE__)).each do |file|
|
73
|
+
require file
|
74
|
+
end
|