<commit_before># frozen_string_literal: true

require "erb"
require "yaml"
require "uri"
require "socket"
require "tmpdir"

module Appsignal
  class Config
    include Appsignal::Utils::DeprecationMessage

    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,
      :transaction_debug_mode         => false
    }.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,
      "APPSIGNAL_TRANSACTION_DEBUG_MODE"         => :transaction_debug_mode,
      "APP_REVISION"                             => :revision
    }.freeze

    # Mapping of old and deprecated AppSignal configuration keys
    DEPRECATED_CONFIG_KEY_MAPPING = {
      :api_key => :push_api_key,
      :ignore_exceptions => :ignore_errors
    }.freeze

    # @attribute [r] system_config
    #   Config detected on the system level.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] initial_config
    #   Config detected on the system level.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] file_config
    #   Config loaded from `config/appsignal.yml` config file.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] env_config
    #   Config loaded from the system environment.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] config_hash
    #   Config used by the AppSignal gem.
    #   Combined Hash of the {system_config}, {initial_config}, {file_config},
    #   {env_config} attributes.
    #   @see #[]
    #   @see #[]=
    #   @api private
    #   @return [Hash]

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

    def initialize(root_path, env, initial_config = {}, logger = Appsignal.logger, config_file = nil)
      @root_path      = root_path
      @config_file    = config_file
      @logger         = logger
      @valid          = false
      @config_hash    = Hash[DEFAULT_CONFIG]
      env_loaded_from_initial = env.to_s
      @env =
        if ENV.key?("APPSIGNAL_APP_ENV".freeze)<commit_msg>Document Appsignal::Config object<commit_after># frozen_string_literal: true

require "erb"
require "yaml"
require "uri"
require "socket"
require "tmpdir"

module Appsignal
  class Config
    include Appsignal::Utils::DeprecationMessage

    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,
      :transaction_debug_mode         => false
    }.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,
      "APPSIGNAL_TRANSACTION_DEBUG_MODE"         => :transaction_debug_mode,
      "APP_REVISION"                             => :revision
    }.freeze

    # Mapping of old and deprecated AppSignal configuration keys
    DEPRECATED_CONFIG_KEY_MAPPING = {
      :api_key => :push_api_key,
      :ignore_exceptions => :ignore_errors
    }.freeze

    # @attribute [r] system_config
    #   Config detected on the system level.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] initial_config
    #   Config detected on the system level.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] file_config
    #   Config loaded from `config/appsignal.yml` config file.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] env_config
    #   Config loaded from the system environment.
    #   Used in diagnose report.
    #   @api private
    #   @return [Hash]
    # @!attribute [r] config_hash
    #   Config used by the AppSignal gem.
    #   Combined Hash of the {system_config}, {initial_config}, {file_config},
    #   {env_config} attributes.
    #   @see #[]
    #   @see #[]=
    #   @api private
    #   @return [Hash]

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

    # Initialize a new configuration object for AppSignal.
    #
    # If this is manually initialized, and not by {Appsignal.start}, it needs
    # to be assigned to the {Appsignal.config} attribute.
    #
    # @example
    #   require "appsignal"
    #   Appsignal.config = Appsignal::Config.new(
    #     app_path,
    #     "production"
    #   )
    #   Appsignal.start
    #
    # @param root_path [String] Root path of the app.
    # @param env [String] The environment to load when AppSignal is started. It
    #   will look for an environment with this name in the `config/appsignal.yml`
    #   config file.
    # @param initial_config [Hash<String, Object>] The initial configuration to
    #   use. This will be overwritten by the file config and environment
    #   variables config.
    # @param logger [Logger] The logger to use for the AppSignal gem. This is
    #   used by the configuration class only. Default: {Appsignal.logger}. See
    #   also {Appsignal.start_logger}.
    # @param config_file [String] Custom config file location. Default
    #   `config/appsignal.yml`.
    #
    # @see https://docs.appsignal.com/ruby/configuration/
    #   Configuration documentation
    # @see https://docs.appsignal.com/ruby/configuration/load-order.html
    #   Configuration load order
    # @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
    #   How to integrate AppSignal manually
    def initialize(root_path, env, initial_config = {}, logger = Appsignal.logger, config_file = nil)
      @root_path      = root_path
      @config_file    = config_file
      @logger         = logger
      @valid          = false
      @config_hash    = Hash[DEFAULT_CONFIG]
      env_loaded_from_initial = env.to_s
      @env =
        if ENV.key?("APPSIGNAL_APP_ENV".freeze)
{'fraction_non_alphanumeric': 0.09215356378097278, 'fraction_numerical': 0.0, 'mean_word_length': 2.0610955056179776, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 124, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4297361', 'n_tokens_mistral': 4067, 'n_tokens_neox': 3963, 'n_words': 711}