Class: Appsignal::Config

Inherits:
Object show all
Includes:
Utils::DeprecationMessage
Defined in:
lib/appsignal/config.rb

Constant Summary collapse

DEFAULT_CONFIG =
{
  :debug                          => false,
  :log                            => "file",
  :ignore_actions                 => [],
  :ignore_errors                  => [],
  :ignore_namespaces              => [],
  :filter_parameters              => [],
  :filter_session_data            => [],
  :send_params                    => true,
  :request_headers                => %w[
    HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
    HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_CONNECTION
    CONTENT_LENGTH PATH_INFO HTTP_RANGE
    REQUEST_METHOD REQUEST_URI SERVER_NAME SERVER_PORT
    SERVER_PROTOCOL
  ],
  :endpoint                       => "https://push.appsignal.com",
  :instrument_net_http            => true,
  :instrument_redis               => true,
  :instrument_sequel              => true,
  :skip_session_data              => false,
  :enable_frontend_error_catching => false,
  :frontend_error_catching_path   => "/appsignal_error_catcher",
  :enable_allocation_tracking     => true,
  :enable_gc_instrumentation      => false,
  :enable_host_metrics            => true,
  :enable_minutely_probes         => true,
  :ca_file_path                   => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
  :dns_servers                    => [],
  :files_world_accessible         => true
}.freeze
ENV_TO_KEY_MAPPING =
{
  "APPSIGNAL_ACTIVE"                         => :active,
  "APPSIGNAL_PUSH_API_KEY"                   => :push_api_key,
  "APPSIGNAL_APP_NAME"                       => :name,
  "APPSIGNAL_PUSH_API_ENDPOINT"              => :endpoint,
  "APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH"   => :frontend_error_catching_path,
  "APPSIGNAL_DEBUG"                          => :debug,
  "APPSIGNAL_LOG"                            => :log,
  "APPSIGNAL_LOG_PATH"                       => :log_path,
  "APPSIGNAL_INSTRUMENT_NET_HTTP"            => :instrument_net_http,
  "APPSIGNAL_INSTRUMENT_REDIS"               => :instrument_redis,
  "APPSIGNAL_INSTRUMENT_SEQUEL"              => :instrument_sequel,
  "APPSIGNAL_SKIP_SESSION_DATA"              => :skip_session_data,
  "APPSIGNAL_ENABLE_FRONTEND_ERROR_CATCHING" => :enable_frontend_error_catching,
  "APPSIGNAL_IGNORE_ACTIONS"                 => :ignore_actions,
  "APPSIGNAL_IGNORE_ERRORS"                  => :ignore_errors,
  "APPSIGNAL_IGNORE_NAMESPACES"              => :ignore_namespaces,
  "APPSIGNAL_FILTER_PARAMETERS"              => :filter_parameters,
  "APPSIGNAL_FILTER_SESSION_DATA"            => :filter_session_data,
  "APPSIGNAL_SEND_PARAMS"                    => :send_params,
  "APPSIGNAL_HTTP_PROXY"                     => :http_proxy,
  "APPSIGNAL_ENABLE_ALLOCATION_TRACKING"     => :enable_allocation_tracking,
  "APPSIGNAL_ENABLE_GC_INSTRUMENTATION"      => :enable_gc_instrumentation,
  "APPSIGNAL_RUNNING_IN_CONTAINER"           => :running_in_container,
  "APPSIGNAL_WORKING_DIR_PATH"               => :working_dir_path,
  "APPSIGNAL_WORKING_DIRECTORY_PATH"         => :working_directory_path,
  "APPSIGNAL_ENABLE_HOST_METRICS"            => :enable_host_metrics,
  "APPSIGNAL_ENABLE_MINUTELY_PROBES"         => :enable_minutely_probes,
  "APPSIGNAL_HOSTNAME"                       => :hostname,
  "APPSIGNAL_CA_FILE_PATH"                   => :ca_file_path,
  "APPSIGNAL_DNS_SERVERS"                    => :dns_servers,
  "APPSIGNAL_FILES_WORLD_ACCESSIBLE"         => :files_world_accessible,
  "APPSIGNAL_REQUEST_HEADERS"                => :request_headers,
  "APP_REVISION"                             => :revision
}.freeze
DEPRECATED_CONFIG_KEY_MAPPING =

Mapping of old and deprecated AppSignal configuration keys

{
  :api_key => :push_api_key,
  :ignore_exceptions => :ignore_errors
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::DeprecationMessage

#deprecation_message

Constructor Details

#initialize(root_path, env, initial_config = {}, logger = Appsignal.logger) ⇒ Config

Returns a new instance of Config.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/appsignal/config.rb', line 120

def initialize(root_path, env, initial_config = {}, logger = Appsignal.logger)
  @root_path      = root_path
  @logger         = logger
  @valid          = false
  @config_hash    = Hash[DEFAULT_CONFIG]
  env_loaded_from_initial = env.to_s
  @env =
    if ENV.key?("APPSIGNAL_APP_ENV".freeze)
      env_loaded_from_env = ENV["APPSIGNAL_APP_ENV".freeze]
    else
      env_loaded_from_initial
    end

  # Set config based on the system
  @system_config = detect_from_system
  merge(system_config)
  # Initial config
  @initial_config = initial_config
  merge(initial_config)
  # Load the config file if it exists
  @file_config = load_from_disk || {}
  merge(file_config)
  # Load config from environment variables
  @env_config = load_from_environment
  merge(env_config)
  # Validate that we have a correct config
  validate
  # Track origin of env
  @initial_config[:env] = env_loaded_from_initial if env_loaded_from_initial
  @env_config[:env] = env_loaded_from_env if env_loaded_from_env
end

Instance Attribute Details

#config_hashHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Config used by the AppSignal gem. Combined Hash of the #system_config, #initial_config, #file_config, #env_config attributes.

Returns:

  • (Hash)

See Also:



116
117
# File 'lib/appsignal/config.rb', line 116

attr_reader :root_path, :env, :config_hash, :system_config,
:initial_config, :file_config, :env_config

#envObject (readonly)

Returns the value of attribute env.



116
117
118
# File 'lib/appsignal/config.rb', line 116

def env
  @env
end

#env_configObject (readonly)

Returns the value of attribute env_config.



116
117
# File 'lib/appsignal/config.rb', line 116

attr_reader :root_path, :env, :config_hash, :system_config,
:initial_config, :file_config, :env_config

#file_configHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Config loaded from config/appsignal.yml config file. Used in diagnose report.

Returns:

  • (Hash)


116
117
# File 'lib/appsignal/config.rb', line 116

attr_reader :root_path, :env, :config_hash, :system_config,
:initial_config, :file_config, :env_config

#initial_configHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Config detected on the system level. Used in diagnose report.

Returns:

  • (Hash)


116
117
# File 'lib/appsignal/config.rb', line 116

attr_reader :root_path, :env, :config_hash, :system_config,
:initial_config, :file_config, :env_config

#loggerObject

Returns the value of attribute logger.



118
119
120
# File 'lib/appsignal/config.rb', line 118

def logger
  @logger
end

#root_pathObject (readonly)

Returns the value of attribute root_path.



116
117
118
# File 'lib/appsignal/config.rb', line 116

def root_path
  @root_path
end

#system_configHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Config detected on the system level. Used in diagnose report.

Returns:

  • (Hash)


116
117
# File 'lib/appsignal/config.rb', line 116

attr_reader :root_path, :env, :config_hash, :system_config,
:initial_config, :file_config, :env_config

Class Method Details

.system_tmp_dirString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns System's tmp directory.

Returns:

  • (String)

    System's tmp directory.



154
155
156
157
158
159
160
# File 'lib/appsignal/config.rb', line 154

def self.system_tmp_dir
  if Gem.win_platform?
    Dir.tmpdir
  else
    File.realpath("/tmp")
  end
end

Instance Method Details

#[](key) ⇒ Object



162
163
164
# File 'lib/appsignal/config.rb', line 162

def [](key)
  config_hash[key]
end

#[]=(key, value) ⇒ Object



166
167
168
# File 'lib/appsignal/config.rb', line 166

def []=(key, value)
  config_hash[key] = value
end

#active?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/appsignal/config.rb', line 193

def active?
  @valid && config_hash[:active]
end

#log_file_pathObject



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/appsignal/config.rb', line 170

def log_file_path
  path = config_hash[:log_path] || root_path && File.join(root_path, "log")
  if path && File.writable?(path)
    return File.join(File.realpath(path), "appsignal.log")
  end

  system_tmp_dir = self.class.system_tmp_dir
  if File.writable? system_tmp_dir
    $stdout.puts "appsignal: Unable to log to '#{path}'. Logging to "\
      "'#{system_tmp_dir}' instead. Please check the "\
      "permissions for the application's (log) directory."
    File.join(system_tmp_dir, "appsignal.log")
  else
    $stdout.puts "appsignal: Unable to log to '#{path}' or the "\
      "'#{system_tmp_dir}' fallback. Please check the permissions "\
      "for the application's (log) directory."
  end
end

#valid?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'lib/appsignal/config.rb', line 189

def valid?
  @valid
end

#validateObject



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/appsignal/config.rb', line 225

def validate
  # Strip path from endpoint so we're backwards compatible with
  # earlier versions of the gem.
  # TODO: Move to its own method, maybe in `#[]=`?
  endpoint_uri = URI(config_hash[:endpoint])
  config_hash[:endpoint] =
    if endpoint_uri.port == 443
      "#{endpoint_uri.scheme}://#{endpoint_uri.host}"
    else
      "#{endpoint_uri.scheme}://#{endpoint_uri.host}:#{endpoint_uri.port}"
    end

  if config_hash[:push_api_key]
    @valid = true
  else
    @valid = false
    @logger.error "Push api key not set after loading config"
  end
end

#write_to_environmentObject

rubocop:disable Metrics/AbcSize



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/appsignal/config.rb', line 197

def write_to_environment # rubocop:disable Metrics/AbcSize
  ENV["_APPSIGNAL_ACTIVE"]                       = active?.to_s
  ENV["_APPSIGNAL_APP_PATH"]                     = root_path.to_s
  ENV["_APPSIGNAL_AGENT_PATH"]                   = File.expand_path("../../../ext", __FILE__).to_s
  ENV["_APPSIGNAL_ENVIRONMENT"]                  = env
  ENV["_APPSIGNAL_LANGUAGE_INTEGRATION_VERSION"] = "ruby-#{Appsignal::VERSION}"
  ENV["_APPSIGNAL_DEBUG_LOGGING"]                = config_hash[:debug].to_s
  ENV["_APPSIGNAL_LOG"]                          = config_hash[:log]
  ENV["_APPSIGNAL_LOG_FILE_PATH"]                = log_file_path.to_s if log_file_path
  ENV["_APPSIGNAL_PUSH_API_ENDPOINT"]            = config_hash[:endpoint]
  ENV["_APPSIGNAL_PUSH_API_KEY"]                 = config_hash[:push_api_key]
  ENV["_APPSIGNAL_APP_NAME"]                     = config_hash[:name]
  ENV["_APPSIGNAL_HTTP_PROXY"]                   = config_hash[:http_proxy]
  ENV["_APPSIGNAL_IGNORE_ACTIONS"]               = config_hash[:ignore_actions].join(",")
  ENV["_APPSIGNAL_IGNORE_ERRORS"]                = config_hash[:ignore_errors].join(",")
  ENV["_APPSIGNAL_IGNORE_NAMESPACES"]            = config_hash[:ignore_namespaces].join(",")
  ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"]         = config_hash[:running_in_container].to_s
  ENV["_APPSIGNAL_WORKING_DIR_PATH"]             = config_hash[:working_dir_path] if config_hash[:working_dir_path]
  ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"]       = config_hash[:working_directory_path] if config_hash[:working_directory_path]
  ENV["_APPSIGNAL_ENABLE_HOST_METRICS"]          = config_hash[:enable_host_metrics].to_s
  ENV["_APPSIGNAL_HOSTNAME"]                     = config_hash[:hostname].to_s
  ENV["_APPSIGNAL_PROCESS_NAME"]                 = $PROGRAM_NAME
  ENV["_APPSIGNAL_CA_FILE_PATH"]                 = config_hash[:ca_file_path].to_s
  ENV["_APPSIGNAL_DNS_SERVERS"]                  = config_hash[:dns_servers].join(",")
  ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"]       = config_hash[:files_world_accessible].to_s
  ENV["_APP_REVISION"]                           = config_hash[:revision].to_s
end