appsignal 3.10.0-java → 3.12.0-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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +197 -0
  4. data/Gemfile +1 -0
  5. data/Rakefile +1 -1
  6. data/benchmark.rake +99 -42
  7. data/lib/appsignal/cli/demo.rb +0 -1
  8. data/lib/appsignal/cli/diagnose.rb +1 -1
  9. data/lib/appsignal/config.rb +204 -130
  10. data/lib/appsignal/demo.rb +16 -26
  11. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  12. data/lib/appsignal/event_formatter.rb +3 -2
  13. data/lib/appsignal/helpers/instrumentation.rb +331 -19
  14. data/lib/appsignal/hooks/action_cable.rb +21 -16
  15. data/lib/appsignal/hooks/active_job.rb +14 -8
  16. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  17. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  18. data/lib/appsignal/integrations/action_cable.rb +5 -7
  19. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  20. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  21. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  22. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  23. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  24. data/lib/appsignal/integrations/excon.rb +1 -0
  25. data/lib/appsignal/integrations/grape.rb +7 -0
  26. data/lib/appsignal/integrations/hanami.rb +8 -43
  27. data/lib/appsignal/integrations/http.rb +1 -0
  28. data/lib/appsignal/integrations/net_http.rb +1 -0
  29. data/lib/appsignal/integrations/object.rb +6 -0
  30. data/lib/appsignal/integrations/padrino.rb +8 -73
  31. data/lib/appsignal/integrations/que.rb +13 -20
  32. data/lib/appsignal/integrations/railtie.rb +36 -14
  33. data/lib/appsignal/integrations/rake.rb +1 -5
  34. data/lib/appsignal/integrations/redis.rb +1 -0
  35. data/lib/appsignal/integrations/redis_client.rb +1 -0
  36. data/lib/appsignal/integrations/resque.rb +2 -5
  37. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  38. data/lib/appsignal/integrations/sidekiq.rb +7 -15
  39. data/lib/appsignal/integrations/sinatra.rb +8 -19
  40. data/lib/appsignal/integrations/unicorn.rb +1 -0
  41. data/lib/appsignal/integrations/webmachine.rb +2 -5
  42. data/lib/appsignal/loaders/grape.rb +13 -0
  43. data/lib/appsignal/loaders/hanami.rb +40 -0
  44. data/lib/appsignal/loaders/padrino.rb +68 -0
  45. data/lib/appsignal/loaders/sinatra.rb +24 -0
  46. data/lib/appsignal/loaders.rb +92 -0
  47. data/lib/appsignal/logger.rb +7 -3
  48. data/lib/appsignal/probes/helpers.rb +1 -0
  49. data/lib/appsignal/probes/mri.rb +1 -0
  50. data/lib/appsignal/probes/sidekiq.rb +1 -0
  51. data/lib/appsignal/probes.rb +3 -0
  52. data/lib/appsignal/rack/abstract_middleware.rb +20 -13
  53. data/lib/appsignal/rack/event_handler.rb +44 -13
  54. data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
  55. data/lib/appsignal/rack/grape_middleware.rb +2 -1
  56. data/lib/appsignal/rack/streaming_listener.rb +1 -0
  57. data/lib/appsignal/rack.rb +35 -0
  58. data/lib/appsignal/span.rb +1 -0
  59. data/lib/appsignal/transaction.rb +308 -101
  60. data/lib/appsignal/utils/data.rb +0 -1
  61. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  62. data/lib/appsignal/utils/integration_logger.rb +0 -13
  63. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  64. data/lib/appsignal/utils/json.rb +0 -1
  65. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  66. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  67. data/lib/appsignal/utils.rb +6 -0
  68. data/lib/appsignal/version.rb +1 -1
  69. data/lib/appsignal.rb +169 -14
  70. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  71. data/spec/lib/appsignal/cli/demo_spec.rb +0 -1
  72. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +1 -1
  73. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1
  74. data/spec/lib/appsignal/config_spec.rb +291 -44
  75. data/spec/lib/appsignal/demo_spec.rb +1 -2
  76. data/spec/lib/appsignal/environment_spec.rb +4 -2
  77. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  78. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +3 -6
  79. data/spec/lib/appsignal/hooks/activejob_spec.rb +12 -3
  80. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  81. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +4 -7
  82. data/spec/lib/appsignal/hooks/excon_spec.rb +3 -6
  83. data/spec/lib/appsignal/hooks/gvl_spec.rb +2 -2
  84. data/spec/lib/appsignal/hooks/http_spec.rb +1 -3
  85. data/spec/lib/appsignal/hooks/net_http_spec.rb +1 -1
  86. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -8
  87. data/spec/lib/appsignal/hooks/redis_spec.rb +3 -6
  88. data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
  89. data/spec/lib/appsignal/hooks/sequel_spec.rb +3 -5
  90. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  91. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +1 -1
  92. data/spec/lib/appsignal/hooks/webmachine_spec.rb +1 -1
  93. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  94. data/spec/lib/appsignal/integrations/grape_spec.rb +36 -0
  95. data/spec/lib/appsignal/integrations/hanami_spec.rb +9 -178
  96. data/spec/lib/appsignal/integrations/http_spec.rb +1 -5
  97. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +4 -2
  98. data/spec/lib/appsignal/integrations/net_http_spec.rb +1 -1
  99. data/spec/lib/appsignal/integrations/object_spec.rb +1 -3
  100. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -330
  101. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  102. data/spec/lib/appsignal/integrations/railtie_spec.rb +275 -191
  103. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  104. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +15 -13
  105. data/spec/lib/appsignal/integrations/sinatra_spec.rb +9 -104
  106. data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
  107. data/spec/lib/appsignal/loaders/grape_spec.rb +12 -0
  108. data/spec/lib/appsignal/loaders/hanami_spec.rb +95 -0
  109. data/spec/lib/appsignal/loaders/padrino_spec.rb +277 -0
  110. data/spec/lib/appsignal/loaders/sinatra_spec.rb +47 -0
  111. data/spec/lib/appsignal/loaders_spec.rb +137 -0
  112. data/spec/lib/appsignal/probes/sidekiq_spec.rb +1 -1
  113. data/spec/lib/appsignal/probes_spec.rb +6 -5
  114. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +51 -5
  115. data/spec/lib/appsignal/rack/event_handler_spec.rb +114 -10
  116. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +1 -1
  117. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +2 -35
  118. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +1 -1
  119. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  120. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -3
  121. data/spec/lib/appsignal/rack_spec.rb +63 -0
  122. data/spec/lib/appsignal/span_spec.rb +1 -3
  123. data/spec/lib/appsignal/transaction_spec.rb +1640 -1075
  124. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  125. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  126. data/spec/lib/appsignal_spec.rb +601 -36
  127. data/spec/lib/puma/appsignal_spec.rb +0 -3
  128. data/spec/spec_helper.rb +5 -4
  129. data/spec/support/helpers/config_helpers.rb +2 -1
  130. data/spec/support/helpers/loader_helper.rb +21 -0
  131. data/spec/support/helpers/transaction_helpers.rb +44 -20
  132. data/spec/support/matchers/transaction.rb +15 -1
  133. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +7 -0
  134. data/spec/support/testing.rb +47 -1
  135. metadata +19 -2
@@ -10,6 +10,17 @@ module Appsignal
10
10
  class Config
11
11
  include Appsignal::Utils::StdoutAndLoggerMessage
12
12
 
13
+ # @api private
14
+ def self.loader_defaults
15
+ @loader_defaults ||= []
16
+ end
17
+
18
+ # @api private
19
+ def self.add_loader_defaults(name, options)
20
+ loader_defaults << [name, options]
21
+ end
22
+
23
+ # @api private
13
24
  DEFAULT_CONFIG = {
14
25
  :activejob_report_errors => "all",
15
26
  :ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
@@ -67,15 +78,31 @@ module Appsignal
67
78
  "trace" => ::Logger::DEBUG
68
79
  }.freeze
69
80
 
70
- ENV_TO_KEY_MAPPING = {
71
- "APPSIGNAL_ACTIVE" => :active,
81
+ # @api private
82
+ ENV_STRING_KEYS = {
72
83
  "APPSIGNAL_ACTIVEJOB_REPORT_ERRORS" => :activejob_report_errors,
73
84
  "APPSIGNAL_APP_NAME" => :name,
74
85
  "APPSIGNAL_BIND_ADDRESS" => :bind_address,
75
86
  "APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
76
- "APPSIGNAL_CPU_COUNT" => :cpu_count,
87
+ "APPSIGNAL_HOSTNAME" => :hostname,
88
+ "APPSIGNAL_HOST_ROLE" => :host_role,
89
+ "APPSIGNAL_HTTP_PROXY" => :http_proxy,
90
+ "APPSIGNAL_LOG" => :log,
91
+ "APPSIGNAL_LOG_LEVEL" => :log_level,
92
+ "APPSIGNAL_LOG_PATH" => :log_path,
93
+ "APPSIGNAL_LOGGING_ENDPOINT" => :logging_endpoint,
94
+ "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
95
+ "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
96
+ "APPSIGNAL_SIDEKIQ_REPORT_ERRORS" => :sidekiq_report_errors,
97
+ "APPSIGNAL_STATSD_PORT" => :statsd_port,
98
+ "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
99
+ "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
100
+ "APP_REVISION" => :revision
101
+ }.freeze
102
+ # @api private
103
+ ENV_BOOLEAN_KEYS = {
104
+ "APPSIGNAL_ACTIVE" => :active,
77
105
  "APPSIGNAL_DEBUG" => :debug,
78
- "APPSIGNAL_DNS_SERVERS" => :dns_servers,
79
106
  "APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
80
107
  "APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
81
108
  "APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
@@ -87,100 +114,33 @@ module Appsignal
87
114
  "APPSIGNAL_ENABLE_RAKE_PERFORMANCE_INSTRUMENTATION" =>
88
115
  :enable_rake_performance_instrumentation,
89
116
  "APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible,
90
- "APPSIGNAL_FILTER_METADATA" => :filter_metadata,
91
- "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
92
- "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
93
- "APPSIGNAL_HOSTNAME" => :hostname,
94
- "APPSIGNAL_HOST_ROLE" => :host_role,
95
- "APPSIGNAL_HTTP_PROXY" => :http_proxy,
96
- "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
97
- "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
98
- "APPSIGNAL_IGNORE_LOGS" => :ignore_logs,
99
- "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
100
117
  "APPSIGNAL_INSTRUMENT_HTTP_RB" => :instrument_http_rb,
101
118
  "APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
102
119
  "APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
103
120
  "APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
104
- "APPSIGNAL_LOG" => :log,
105
- "APPSIGNAL_LOG_LEVEL" => :log_level,
106
- "APPSIGNAL_LOG_PATH" => :log_path,
107
- "APPSIGNAL_LOGGING_ENDPOINT" => :logging_endpoint,
108
- "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
109
- "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
110
- "APPSIGNAL_REQUEST_HEADERS" => :request_headers,
111
121
  "APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
112
122
  "APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
113
123
  "APPSIGNAL_SEND_PARAMS" => :send_params,
114
124
  "APPSIGNAL_SEND_SESSION_DATA" => :send_session_data,
115
- "APPSIGNAL_SIDEKIQ_REPORT_ERRORS" => :sidekiq_report_errors,
116
125
  "APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
117
- "APPSIGNAL_STATSD_PORT" => :statsd_port,
118
- "APPSIGNAL_TRANSACTION_DEBUG_MODE" => :transaction_debug_mode,
119
- "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
120
- "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
121
- "APP_REVISION" => :revision
126
+ "APPSIGNAL_TRANSACTION_DEBUG_MODE" => :transaction_debug_mode
122
127
  }.freeze
123
128
  # @api private
124
- ENV_STRING_KEYS = %w[
125
- APPSIGNAL_ACTIVEJOB_REPORT_ERRORS
126
- APPSIGNAL_APP_NAME
127
- APPSIGNAL_BIND_ADDRESS
128
- APPSIGNAL_CA_FILE_PATH
129
- APPSIGNAL_HOSTNAME
130
- APPSIGNAL_HOST_ROLE
131
- APPSIGNAL_HTTP_PROXY
132
- APPSIGNAL_LOG
133
- APPSIGNAL_LOG_LEVEL
134
- APPSIGNAL_LOG_PATH
135
- APPSIGNAL_LOGGING_ENDPOINT
136
- APPSIGNAL_PUSH_API_ENDPOINT
137
- APPSIGNAL_PUSH_API_KEY
138
- APPSIGNAL_SIDEKIQ_REPORT_ERRORS
139
- APPSIGNAL_STATSD_PORT
140
- APPSIGNAL_WORKING_DIRECTORY_PATH
141
- APPSIGNAL_WORKING_DIR_PATH
142
- APP_REVISION
143
- ].freeze
144
- # @api private
145
- ENV_BOOLEAN_KEYS = %w[
146
- APPSIGNAL_ACTIVE
147
- APPSIGNAL_DEBUG
148
- APPSIGNAL_ENABLE_ALLOCATION_TRACKING
149
- APPSIGNAL_ENABLE_HOST_METRICS
150
- APPSIGNAL_ENABLE_MINUTELY_PROBES
151
- APPSIGNAL_ENABLE_STATSD
152
- APPSIGNAL_ENABLE_NGINX_METRICS
153
- APPSIGNAL_ENABLE_GVL_GLOBAL_TIMER
154
- APPSIGNAL_ENABLE_GVL_WAITING_THREADS
155
- APPSIGNAL_ENABLE_RAILS_ERROR_REPORTER
156
- APPSIGNAL_ENABLE_RAKE_PERFORMANCE_INSTRUMENTATION
157
- APPSIGNAL_FILES_WORLD_ACCESSIBLE
158
- APPSIGNAL_INSTRUMENT_HTTP_RB
159
- APPSIGNAL_INSTRUMENT_NET_HTTP
160
- APPSIGNAL_INSTRUMENT_REDIS
161
- APPSIGNAL_INSTRUMENT_SEQUEL
162
- APPSIGNAL_RUNNING_IN_CONTAINER
163
- APPSIGNAL_SEND_ENVIRONMENT_METADATA
164
- APPSIGNAL_SEND_PARAMS
165
- APPSIGNAL_SEND_SESSION_DATA
166
- APPSIGNAL_SKIP_SESSION_DATA
167
- APPSIGNAL_TRANSACTION_DEBUG_MODE
168
- ].freeze
129
+ ENV_ARRAY_KEYS = {
130
+ "APPSIGNAL_DNS_SERVERS" => :dns_servers,
131
+ "APPSIGNAL_FILTER_METADATA" => :filter_metadata,
132
+ "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
133
+ "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
134
+ "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
135
+ "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
136
+ "APPSIGNAL_IGNORE_LOGS" => :ignore_logs,
137
+ "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
138
+ "APPSIGNAL_REQUEST_HEADERS" => :request_headers
139
+ }.freeze
169
140
  # @api private
170
- ENV_ARRAY_KEYS = %w[
171
- APPSIGNAL_DNS_SERVERS
172
- APPSIGNAL_FILTER_METADATA
173
- APPSIGNAL_FILTER_PARAMETERS
174
- APPSIGNAL_FILTER_SESSION_DATA
175
- APPSIGNAL_IGNORE_ACTIONS
176
- APPSIGNAL_IGNORE_ERRORS
177
- APPSIGNAL_IGNORE_LOGS
178
- APPSIGNAL_IGNORE_NAMESPACES
179
- APPSIGNAL_REQUEST_HEADERS
180
- ].freeze
181
- ENV_FLOAT_KEYS = %w[
182
- APPSIGNAL_CPU_COUNT
183
- ].freeze
141
+ ENV_FLOAT_KEYS = {
142
+ "APPSIGNAL_CPU_COUNT" => :cpu_count
143
+ }.freeze
184
144
 
185
145
  # @attribute [r] system_config
186
146
  # Config detected on the system level.
@@ -211,23 +171,15 @@ module Appsignal
211
171
  # @api private
212
172
  # @return [Hash]
213
173
 
214
- attr_reader :root_path, :env, :config_hash, :system_config,
215
- :initial_config, :file_config, :env_config, :override_config
174
+ # @api private
175
+ attr_accessor :root_path, :env, :config_hash
176
+ attr_reader :system_config, :initial_config, :file_config, :env_config,
177
+ :override_config, :dsl_config
178
+ # @api private
216
179
  attr_accessor :logger
217
180
 
218
181
  # Initialize a new configuration object for AppSignal.
219
182
  #
220
- # If this is manually initialized, and not by {Appsignal.start}, it needs
221
- # to be assigned to the {Appsignal.config} attribute.
222
- #
223
- # @example
224
- # require "appsignal"
225
- # Appsignal.config = Appsignal::Config.new(
226
- # app_path,
227
- # "production"
228
- # )
229
- # Appsignal.start
230
- #
231
183
  # @param root_path [String] Root path of the app.
232
184
  # @param env [String] The environment to load when AppSignal is started. It
233
185
  # will look for an environment with this name in the `config/appsignal.yml`
@@ -241,55 +193,90 @@ module Appsignal
241
193
  # @param config_file [String] Custom config file location. Default
242
194
  # `config/appsignal.yml`.
243
195
  #
196
+ # @api private
244
197
  # @see https://docs.appsignal.com/ruby/configuration/
245
198
  # Configuration documentation
246
199
  # @see https://docs.appsignal.com/ruby/configuration/load-order.html
247
200
  # Configuration load order
248
201
  # @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
249
202
  # How to integrate AppSignal manually
250
- def initialize(
203
+ def initialize( # rubocop:disable Metrics/ParameterLists
251
204
  root_path,
252
- env,
205
+ initial_env,
253
206
  initial_config = {},
254
207
  logger = Appsignal.internal_logger,
255
- config_file = nil
208
+ config_file = nil,
209
+ load_on_new = true # rubocop:disable Style/OptionalBooleanParameter
256
210
  )
257
- @config_file_error = false
258
211
  @root_path = root_path
212
+ @config_file_error = false
259
213
  @config_file = config_file
260
214
  @logger = logger
261
215
  @valid = false
262
- @config_hash = DEFAULT_CONFIG.dup
263
- env_loaded_from_initial = env.to_s
264
- @env =
265
- if ENV.key?("APPSIGNAL_APP_ENV")
266
- env_loaded_from_env = ENV["APPSIGNAL_APP_ENV"]
267
- else
268
- env_loaded_from_initial
269
- end
216
+
217
+ @initial_env = initial_env
218
+ @env = initial_env.to_s
219
+ @config_hash = {}
220
+ @system_config = {}
221
+ @initial_config = initial_config
222
+ @file_config = {}
223
+ @env_config = {}
224
+ @override_config = {}
225
+ @dsl_config = {} # Can be set using `Appsignal.configure`
226
+
227
+ return unless load_on_new
228
+
229
+ # Determine starting environment
230
+ @env = ENV["APPSIGNAL_APP_ENV"] if ENV.key?("APPSIGNAL_APP_ENV")
231
+ load_config
232
+ validate
233
+ end
234
+
235
+ # @api private
236
+ def load_config
237
+ # Set defaults
238
+ # Deep duplicate each frozen default value
239
+ merge(DEFAULT_CONFIG.transform_values(&:dup))
270
240
 
271
241
  # Set config based on the system
272
242
  @system_config = detect_from_system
273
243
  merge(system_config)
274
- # Initial config
275
- @initial_config = initial_config
244
+
245
+ # Set defaults from loaders in reverse order so the first register
246
+ # loader's defaults overwrite all others
247
+ self.class.loader_defaults.reverse.each do |(_loader_name, loader_defaults)|
248
+ defaults = loader_defaults.compact.dup
249
+ # Overwrite root path
250
+ loader_path = defaults.delete(:root_path)
251
+ @root_path = loader_path if loader_path
252
+ # Overwrite env
253
+ loader_env = defaults.delete(:env)
254
+ @env = loader_env.to_s if loader_env
255
+ # Merge with the config loaded so far
256
+ merge(defaults)
257
+ end
258
+
276
259
  merge(initial_config)
260
+ # Track origin of env
261
+ @initial_config[:env] = @initial_env.to_s
262
+
277
263
  # Load the config file if it exists
278
264
  @file_config = load_from_disk || {}
279
265
  merge(file_config)
266
+
280
267
  # Load config from environment variables
281
268
  @env_config = load_from_environment
282
269
  merge(env_config)
270
+ # Track origin of env
271
+ env_loaded_from_env = ENV.fetch("APPSIGNAL_APP_ENV", nil)
272
+ @env_config[:env] = env_loaded_from_env if env_loaded_from_env
273
+
283
274
  # Load config overrides
284
275
  @override_config = determine_overrides
285
276
  merge(override_config)
277
+
286
278
  # Handle deprecated config options
287
279
  maintain_backwards_compatibility
288
- # Validate that we have a correct config
289
- validate
290
- # Track origin of env
291
- @initial_config[:env] = env_loaded_from_initial if env_loaded_from_initial
292
- @env_config[:env] = env_loaded_from_env if env_loaded_from_env
293
280
  end
294
281
 
295
282
  # @api private
@@ -302,6 +289,7 @@ module Appsignal
302
289
  end
303
290
  end
304
291
 
292
+ # @api private
305
293
  def [](key)
306
294
  config_hash[key]
307
295
  end
@@ -316,6 +304,7 @@ module Appsignal
316
304
  config_hash[key] = value
317
305
  end
318
306
 
307
+ # @api private
319
308
  def log_level
320
309
  level = ::Logger::DEBUG if config_hash[:debug] || config_hash[:transaction_debug_mode]
321
310
  option = config_hash[:log_level]
@@ -326,6 +315,7 @@ module Appsignal
326
315
  level.nil? ? Appsignal::Config::DEFAULT_LOG_LEVEL : level
327
316
  end
328
317
 
318
+ # @api private
329
319
  def log_file_path
330
320
  return @log_file_path if defined? @log_file_path
331
321
 
@@ -360,6 +350,7 @@ module Appsignal
360
350
  @valid && config_hash[:active]
361
351
  end
362
352
 
353
+ # @api private
363
354
  def write_to_environment # rubocop:disable Metrics/AbcSize
364
355
  ENV["_APPSIGNAL_ACTIVE"] = active?.to_s
365
356
  ENV["_APPSIGNAL_AGENT_PATH"] = File.expand_path("../../ext", __dir__).to_s
@@ -405,6 +396,13 @@ module Appsignal
405
396
  ENV["_APP_REVISION"] = config_hash[:revision].to_s
406
397
  end
407
398
 
399
+ # @api private
400
+ def merge_dsl_options(options)
401
+ @dsl_options = options
402
+ merge(options)
403
+ end
404
+
405
+ # @api private
408
406
  def validate
409
407
  # Strip path from endpoint so we're backwards compatible with
410
408
  # earlier versions of the gem.
@@ -503,35 +501,35 @@ module Appsignal
503
501
  config = {}
504
502
 
505
503
  # Configuration with string type
506
- ENV_STRING_KEYS.each do |var|
507
- env_var = ENV.fetch(var, nil)
504
+ ENV_STRING_KEYS.each do |env_key, option|
505
+ env_var = ENV.fetch(env_key, nil)
508
506
  next unless env_var
509
507
 
510
- config[ENV_TO_KEY_MAPPING[var]] = env_var
508
+ config[option] = env_var
511
509
  end
512
510
 
513
511
  # Configuration with boolean type
514
- ENV_BOOLEAN_KEYS.each do |var|
515
- env_var = ENV.fetch(var, nil)
512
+ ENV_BOOLEAN_KEYS.each do |env_key, option|
513
+ env_var = ENV.fetch(env_key, nil)
516
514
  next unless env_var
517
515
 
518
- config[ENV_TO_KEY_MAPPING[var]] = env_var.casecmp("true").zero?
516
+ config[option] = env_var.casecmp("true").zero?
519
517
  end
520
518
 
521
519
  # Configuration with array of strings type
522
- ENV_ARRAY_KEYS.each do |var|
523
- env_var = ENV.fetch(var, nil)
520
+ ENV_ARRAY_KEYS.each do |env_key, option|
521
+ env_var = ENV.fetch(env_key, nil)
524
522
  next unless env_var
525
523
 
526
- config[ENV_TO_KEY_MAPPING[var]] = env_var.split(",")
524
+ config[option] = env_var.split(",")
527
525
  end
528
526
 
529
527
  # Configuration with float type
530
- ENV_FLOAT_KEYS.each do |var|
531
- env_var = ENV.fetch(var, nil)
528
+ ENV_FLOAT_KEYS.each do |env_key, option|
529
+ env_var = ENV.fetch(env_key, nil)
532
530
  next unless env_var
533
531
 
534
- config[ENV_TO_KEY_MAPPING[var]] = env_var.to_f
532
+ config[option] = env_var.to_f
535
533
  end
536
534
 
537
535
  config
@@ -590,5 +588,81 @@ module Appsignal
590
588
  value = ENV.fetch("APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR", false)
591
589
  ["1", "true"].include?(value)
592
590
  end
591
+
592
+ # @api private
593
+ class ConfigDSL
594
+ attr_reader :dsl_options
595
+
596
+ def initialize(config)
597
+ @config = config
598
+ @dsl_options = {}
599
+ end
600
+
601
+ def app_path
602
+ @config.root_path
603
+ end
604
+
605
+ def app_path=(path)
606
+ @config.root_path = path
607
+ end
608
+
609
+ def env
610
+ @config.env
611
+ end
612
+
613
+ Appsignal::Config::ENV_STRING_KEYS.each_value do |option|
614
+ define_method(option) do
615
+ fetch_option(option)
616
+ end
617
+
618
+ define_method("#{option}=") do |value|
619
+ update_option(option, value.to_s)
620
+ end
621
+ end
622
+
623
+ Appsignal::Config::ENV_BOOLEAN_KEYS.each_value do |option|
624
+ define_method(option) do
625
+ fetch_option(option)
626
+ end
627
+
628
+ define_method("#{option}=") do |value|
629
+ update_option(option, !!value)
630
+ end
631
+ end
632
+
633
+ Appsignal::Config::ENV_ARRAY_KEYS.each_value do |option|
634
+ define_method(option) do
635
+ fetch_option(option)
636
+ end
637
+
638
+ define_method("#{option}=") do |value|
639
+ update_option(option, value.to_a)
640
+ end
641
+ end
642
+
643
+ Appsignal::Config::ENV_FLOAT_KEYS.each_value do |option|
644
+ define_method(option) do
645
+ fetch_option(option)
646
+ end
647
+
648
+ define_method("#{option}=") do |value|
649
+ update_option(option, value.to_f)
650
+ end
651
+ end
652
+
653
+ private
654
+
655
+ def fetch_option(key)
656
+ if @dsl_options.key?(key)
657
+ @dsl_options[key]
658
+ else
659
+ @dsl_options[key] = @config[key].dup
660
+ end
661
+ end
662
+
663
+ def update_option(key, value)
664
+ @dsl_options[key] = value
665
+ end
666
+ end
593
667
  end
594
668
  end
@@ -6,12 +6,7 @@ module Appsignal
6
6
  # {Appsignal::Demo} is a way to send demonstration / test samples for a
7
7
  # exception and a performance issue.
8
8
  #
9
- # @example Loading config automatically
10
- # Appsignal::Demo.transmit
11
- #
12
- # @example With custom config
13
- # # If another configuration should be used, set it beforehand.
14
- # Appsignal.config = Appsignal::Config.new(Dir.pwd, "production")
9
+ # @example Send example transactions
15
10
  # Appsignal::Demo.transmit
16
11
  #
17
12
  # @since 2.0.0
@@ -39,18 +34,15 @@ module Appsignal
39
34
  private
40
35
 
41
36
  def create_example_error_request
42
- transaction = Appsignal::Transaction.create(
43
- SecureRandom.uuid,
44
- Appsignal::Transaction::HTTP_REQUEST,
45
- rack_request
46
- )
37
+ transaction = Appsignal::Transaction.create(Appsignal::Transaction::HTTP_REQUEST)
47
38
  begin
48
39
  raise TestError,
49
40
  "Hello world! This is an error used for demonstration purposes."
50
41
  rescue => error
51
42
  Appsignal.set_error(error)
52
43
  end
53
- transaction.set_http_or_background_queue_start
44
+ add_params_to(transaction)
45
+ add_headers_to(transaction)
54
46
  transaction.set_metadata("path", "/hello")
55
47
  transaction.set_metadata("method", "GET")
56
48
  transaction.set_action("DemoController#hello")
@@ -59,16 +51,13 @@ module Appsignal
59
51
  end
60
52
 
61
53
  def create_example_performance_request
62
- transaction = Appsignal::Transaction.create(
63
- SecureRandom.uuid,
64
- Appsignal::Transaction::HTTP_REQUEST,
65
- rack_request
66
- )
54
+ transaction = Appsignal::Transaction.create(Appsignal::Transaction::HTTP_REQUEST)
67
55
  Appsignal.instrument "action_view.render", "Render hello.html.erb",
68
56
  "<h1>Hello world!</h1>" do
69
57
  sleep 2
70
58
  end
71
- transaction.set_http_or_background_queue_start
59
+ add_params_to(transaction)
60
+ add_headers_to(transaction)
72
61
  transaction.set_metadata("path", "/hello")
73
62
  transaction.set_metadata("method", "GET")
74
63
  transaction.set_action("DemoController#hello")
@@ -80,13 +69,15 @@ module Appsignal
80
69
  transaction.set_metadata("demo_sample", "true")
81
70
  end
82
71
 
83
- def rack_request
84
- env = ::Rack::MockRequest.env_for(
85
- "/demo",
86
- :params => {
87
- "controller" => "demo",
88
- "action" => "hello"
89
- },
72
+ def add_params_to(transaction)
73
+ transaction.set_params(
74
+ "controller" => "demo",
75
+ "action" => "hello"
76
+ )
77
+ end
78
+
79
+ def add_headers_to(transaction)
80
+ transaction.set_headers(
90
81
  "REMOTE_ADDR" => "127.0.0.1",
91
82
  "REQUEST_METHOD" => "GET",
92
83
  "SERVER_NAME" => "localhost",
@@ -102,7 +93,6 @@ module Appsignal
102
93
  "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0)",
103
94
  "HTTP_REFERER" => "http://appsignal.com/accounts"
104
95
  )
105
- ::Rack::Request.new(env)
106
96
  end
107
97
  end
108
98
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Appsignal
4
4
  class EventFormatter
5
+ # @api private
5
6
  module Rom
6
7
  class SqlFormatter
7
8
  def format(payload)
@@ -10,14 +10,14 @@ module Appsignal
10
10
  # event, the same object will be called intermittently in a threaded environment.
11
11
  # So only keep global configuration as state and pass the payload around as an
12
12
  # argument if you need to use helper methods.
13
- #
14
- # @api private
15
13
  class EventFormatter
16
14
  class << self
15
+ # @api private
17
16
  def formatters
18
17
  @formatters ||= {}
19
18
  end
20
19
 
20
+ # @api private
21
21
  def formatter_classes
22
22
  @formatter_classes ||= {}
23
23
  end
@@ -49,6 +49,7 @@ module Appsignal
49
49
  end
50
50
  end
51
51
 
52
+ # @api private
52
53
  def format(name, payload)
53
54
  formatter = formatters[name]
54
55
  formatter&.format(payload)