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.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.rspec +4 -0
  4. data/.rubocop.yml +66 -0
  5. data/.rubocop_todo.yml +124 -0
  6. data/.travis.yml +72 -0
  7. data/.yardopts +8 -0
  8. data/CHANGELOG.md +639 -0
  9. data/Gemfile +3 -0
  10. data/LICENSE +20 -0
  11. data/README.md +264 -0
  12. data/Rakefile +214 -0
  13. data/appsignal.gemspec +42 -0
  14. data/benchmark.rake +77 -0
  15. data/bin/appsignal +13 -0
  16. data/ext/Rakefile +27 -0
  17. data/ext/agent.yml +64 -0
  18. data/ext/appsignal_extension.c +692 -0
  19. data/ext/base.rb +79 -0
  20. data/ext/extconf.rb +35 -0
  21. data/gemfiles/capistrano2.gemfile +7 -0
  22. data/gemfiles/capistrano3.gemfile +7 -0
  23. data/gemfiles/grape.gemfile +7 -0
  24. data/gemfiles/no_dependencies.gemfile +5 -0
  25. data/gemfiles/padrino.gemfile +7 -0
  26. data/gemfiles/que.gemfile +5 -0
  27. data/gemfiles/rails-3.2.gemfile +6 -0
  28. data/gemfiles/rails-4.0.gemfile +6 -0
  29. data/gemfiles/rails-4.1.gemfile +6 -0
  30. data/gemfiles/rails-4.2.gemfile +10 -0
  31. data/gemfiles/rails-5.0.gemfile +5 -0
  32. data/gemfiles/rails-5.1.gemfile +5 -0
  33. data/gemfiles/resque.gemfile +12 -0
  34. data/gemfiles/sequel-435.gemfile +11 -0
  35. data/gemfiles/sequel.gemfile +11 -0
  36. data/gemfiles/sinatra.gemfile +6 -0
  37. data/gemfiles/webmachine.gemfile +5 -0
  38. data/lib/appsignal.rb +804 -0
  39. data/lib/appsignal/auth_check.rb +65 -0
  40. data/lib/appsignal/capistrano.rb +10 -0
  41. data/lib/appsignal/cli.rb +108 -0
  42. data/lib/appsignal/cli/demo.rb +63 -0
  43. data/lib/appsignal/cli/diagnose.rb +500 -0
  44. data/lib/appsignal/cli/helpers.rb +72 -0
  45. data/lib/appsignal/cli/install.rb +277 -0
  46. data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
  47. data/lib/appsignal/config.rb +287 -0
  48. data/lib/appsignal/demo.rb +107 -0
  49. data/lib/appsignal/event_formatter.rb +74 -0
  50. data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
  51. data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
  52. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
  53. data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
  54. data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
  55. data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
  56. data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
  57. data/lib/appsignal/extension.rb +63 -0
  58. data/lib/appsignal/extension/jruby.rb +460 -0
  59. data/lib/appsignal/garbage_collection_profiler.rb +48 -0
  60. data/lib/appsignal/hooks.rb +105 -0
  61. data/lib/appsignal/hooks/action_cable.rb +113 -0
  62. data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
  63. data/lib/appsignal/hooks/celluloid.rb +30 -0
  64. data/lib/appsignal/hooks/data_mapper.rb +18 -0
  65. data/lib/appsignal/hooks/delayed_job.rb +19 -0
  66. data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
  67. data/lib/appsignal/hooks/net_http.rb +29 -0
  68. data/lib/appsignal/hooks/passenger.rb +22 -0
  69. data/lib/appsignal/hooks/puma.rb +35 -0
  70. data/lib/appsignal/hooks/que.rb +21 -0
  71. data/lib/appsignal/hooks/rake.rb +39 -0
  72. data/lib/appsignal/hooks/redis.rb +30 -0
  73. data/lib/appsignal/hooks/sequel.rb +60 -0
  74. data/lib/appsignal/hooks/shoryuken.rb +43 -0
  75. data/lib/appsignal/hooks/sidekiq.rb +144 -0
  76. data/lib/appsignal/hooks/unicorn.rb +40 -0
  77. data/lib/appsignal/hooks/webmachine.rb +23 -0
  78. data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
  79. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
  80. data/lib/appsignal/integrations/data_mapper.rb +33 -0
  81. data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
  82. data/lib/appsignal/integrations/grape.rb +53 -0
  83. data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
  84. data/lib/appsignal/integrations/object.rb +35 -0
  85. data/lib/appsignal/integrations/padrino.rb +84 -0
  86. data/lib/appsignal/integrations/que.rb +43 -0
  87. data/lib/appsignal/integrations/railtie.rb +41 -0
  88. data/lib/appsignal/integrations/rake.rb +2 -0
  89. data/lib/appsignal/integrations/resque.rb +20 -0
  90. data/lib/appsignal/integrations/resque_active_job.rb +30 -0
  91. data/lib/appsignal/integrations/sinatra.rb +17 -0
  92. data/lib/appsignal/integrations/webmachine.rb +38 -0
  93. data/lib/appsignal/js_exception_transaction.rb +54 -0
  94. data/lib/appsignal/marker.rb +63 -0
  95. data/lib/appsignal/minutely.rb +42 -0
  96. data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
  97. data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
  98. data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
  99. data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
  100. data/lib/appsignal/rack/streaming_listener.rb +73 -0
  101. data/lib/appsignal/system.rb +81 -0
  102. data/lib/appsignal/transaction.rb +498 -0
  103. data/lib/appsignal/transmitter.rb +107 -0
  104. data/lib/appsignal/utils.rb +127 -0
  105. data/lib/appsignal/utils/params_sanitizer.rb +59 -0
  106. data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
  107. data/lib/appsignal/version.rb +3 -0
  108. data/lib/sequel/extensions/appsignal_integration.rb +3 -0
  109. data/resources/appsignal.yml.erb +39 -0
  110. data/resources/cacert.pem +3866 -0
  111. data/spec/.rubocop.yml +7 -0
  112. data/spec/lib/appsignal/auth_check_spec.rb +80 -0
  113. data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
  114. data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
  115. data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
  116. data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
  117. data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
  118. data/spec/lib/appsignal/cli/install_spec.rb +632 -0
  119. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
  120. data/spec/lib/appsignal/cli_spec.rb +56 -0
  121. data/spec/lib/appsignal/config_spec.rb +637 -0
  122. data/spec/lib/appsignal/demo_spec.rb +87 -0
  123. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
  124. data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
  125. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
  126. data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
  127. data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
  128. data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
  129. data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
  130. data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
  131. data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
  132. data/spec/lib/appsignal/extension_spec.rb +137 -0
  133. data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
  134. data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
  135. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
  136. data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
  137. data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
  138. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
  139. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
  140. data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
  141. data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
  142. data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
  143. data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
  144. data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
  145. data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
  146. data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
  147. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
  148. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
  149. data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
  150. data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
  151. data/spec/lib/appsignal/hooks_spec.rb +195 -0
  152. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
  153. data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
  154. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
  155. data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
  156. data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
  157. data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
  158. data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
  159. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
  160. data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
  161. data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
  162. data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
  163. data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
  164. data/spec/lib/appsignal/marker_spec.rb +51 -0
  165. data/spec/lib/appsignal/minutely_spec.rb +50 -0
  166. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
  167. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
  168. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
  169. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
  170. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
  171. data/spec/lib/appsignal/system_spec.rb +131 -0
  172. data/spec/lib/appsignal/transaction_spec.rb +1146 -0
  173. data/spec/lib/appsignal/transmitter_spec.rb +152 -0
  174. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
  175. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
  176. data/spec/lib/appsignal/utils_spec.rb +150 -0
  177. data/spec/lib/appsignal_spec.rb +1049 -0
  178. data/spec/spec_helper.rb +116 -0
  179. data/spec/support/fixtures/containers/cgroups/docker +14 -0
  180. data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
  181. data/spec/support/fixtures/containers/cgroups/lxc +10 -0
  182. data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
  183. data/spec/support/fixtures/containers/cgroups/none +1 -0
  184. data/spec/support/fixtures/generated_config.yml +24 -0
  185. data/spec/support/fixtures/uploaded_file.txt +0 -0
  186. data/spec/support/helpers/api_request_helper.rb +19 -0
  187. data/spec/support/helpers/cli_helpers.rb +26 -0
  188. data/spec/support/helpers/config_helpers.rb +21 -0
  189. data/spec/support/helpers/dependency_helper.rb +73 -0
  190. data/spec/support/helpers/directory_helper.rb +27 -0
  191. data/spec/support/helpers/env_helpers.rb +33 -0
  192. data/spec/support/helpers/example_exception.rb +13 -0
  193. data/spec/support/helpers/example_standard_error.rb +13 -0
  194. data/spec/support/helpers/log_helpers.rb +22 -0
  195. data/spec/support/helpers/std_streams_helper.rb +66 -0
  196. data/spec/support/helpers/system_helpers.rb +8 -0
  197. data/spec/support/helpers/time_helpers.rb +11 -0
  198. data/spec/support/helpers/transaction_helpers.rb +37 -0
  199. data/spec/support/matchers/contains_log.rb +7 -0
  200. data/spec/support/mocks/fake_gc_profiler.rb +19 -0
  201. data/spec/support/mocks/mock_extension.rb +6 -0
  202. data/spec/support/project_fixture/config/application.rb +0 -0
  203. data/spec/support/project_fixture/config/appsignal.yml +32 -0
  204. data/spec/support/project_fixture/config/environments/development.rb +0 -0
  205. data/spec/support/project_fixture/config/environments/production.rb +0 -0
  206. data/spec/support/project_fixture/config/environments/test.rb +0 -0
  207. data/spec/support/project_fixture/log/.gitkeep +0 -0
  208. data/spec/support/rails/my_app.rb +6 -0
  209. data/spec/support/shared_examples/instrument.rb +43 -0
  210. data/spec/support/stubs/delayed_job.rb +0 -0
  211. 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