lib/opentelemetry/instrumentation/base.rb in opentelemetry-instrumentation-base-0.18.3 vs lib/opentelemetry/instrumentation/base.rb in opentelemetry-instrumentation-base-0.19.0

- old
+ new

@@ -144,15 +144,24 @@ # @param default The default value to be used, or to used if validation fails # @param [Callable, Symbol] validate Accepts a callable or a symbol that matches # a key in the VALIDATORS hash. The supported keys are, :array, :boolean, # :callable, :integer, :string. def option(name, default:, validate:) - validate = VALIDATORS[validate] || validate - raise ArgumentError, "validate must be #{VALIDATORS.keys.join(', ')}, or a callable" unless validate.respond_to?(:call) + validator = VALIDATORS[validate] || validate + raise ArgumentError, "validate must be #{VALIDATORS.keys.join(', ')}, or a callable" unless validator.respond_to?(:call) || validator.respond_to?(:include?) @options ||= [] - @options << { name: name, default: default, validate: validate } + + validation_type = if VALIDATORS[validate] + validate + elsif validate.respond_to?(:include?) + :enum + else + :callable + end + + @options << { name: name, default: default, validator: validator, validation_type: validation_type } end def instance @instance ||= new(instrumentation_name, instrumentation_version, install_blk, present_blk, compatible_blk, options) @@ -255,21 +264,29 @@ # config hash is valid. # Unknown configuration keys are not included in the final config hash. # Invalid configuration values are logged, and replaced by the default. # # @param [Hash] user_config The user supplied configuration hash - def config_options(user_config) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def config_options(user_config) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity @options ||= {} user_config ||= {} + config_overrides = config_overrides_from_env validated_config = @options.each_with_object({}) do |option, h| option_name = option[:name] config_value = user_config[option_name] + config_override = coerce_env_var(config_overrides[option_name], option[:validation_type]) if config_overrides[option_name] - value = if config_value.nil? + value = if config_value.nil? && config_override.nil? option[:default] - elsif option[:validate].call(config_value) + elsif option[:validator].respond_to?(:include?) && option[:validator].include?(config_override) + config_override + elsif option[:validator].respond_to?(:include?) && option[:validator].include?(config_value) config_value + elsif option[:validator].respond_to?(:call) && option[:validator].call(config_override) + config_override + elsif option[:validator].respond_to?(:call) && option[:validator].call(config_value) + config_value else OpenTelemetry.logger.warn( "Instrumentation #{name} configuration option #{option_name} value=#{config_value} " \ "failed validation, falling back to default value=#{option[:default]}" ) @@ -300,9 +317,52 @@ n.gsub!('::', '_') n.gsub!('OPENTELEMETRY_', 'OTEL_RUBY_') n << '_ENABLED' end ENV[var_name] != 'false' + end + + def config_overrides_from_env + var_name = name.dup.tap do |n| + n.upcase! + n.gsub!('::', '_') + n.gsub!('OPENTELEMETRY_', 'OTEL_RUBY_') + n << '_CONFIG_OPTS' + end + + environment_config_overrides = {} + env_config_options = ENV[var_name]&.split(';') + + return environment_config_overrides if env_config_options.nil? + + env_config_options.each_with_object(environment_config_overrides) do |env_config_option, eco| + parts = env_config_option.split('=') + option_name = parts[0].to_sym + eco[option_name] = parts[1] + end + + environment_config_overrides + end + + def coerce_env_var(env_var, validation_type) # rubocop:disable Metrics/CyclomaticComplexity + case validation_type + when :array + env_var.split(',').map(&:strip) + when :boolean + env_var.to_s.strip.downcase == 'true' + when :integer + env_var.to_i + when :string + env_var.to_s.strip + when :enum + env_var.to_s.strip.to_sym + when :callable + OpenTelemetry.logger.warn( + "Instrumentation #{name} options that accept a callable are not " \ + "configurable using environment variables. Ignoring raw value: #{env_var}" + ) + nil + end end end end end