class OneApm::Configuration::Manager

Constants

MALFORMED_LABELS_WARNING
MAX_LABEL_COUNT
MAX_LABEL_LENGTH
PARSING_LABELS_FAILURE

Attributes

stripped_exceptions_whitelist[R]

Public Class Methods

new() click to toggle source
# File lib/one_apm/configuration.rb, line 24
def initialize
  reset_to_defaults
  @callbacks = Hash.new {|hash,key| hash[key] = [] }

  register_callback(:'strip_exception_messages.whitelist') do |whitelist|
    if whitelist
      @stripped_exceptions_whitelist = parse_constant_list(whitelist).compact
    else
      @stripped_exceptions_whitelist = []
    end
  end
end

Public Instance Methods

[](key) click to toggle source

Defining these explicitly saves object allocations that we incur if we use Forwardable and def_delegators.

# File lib/one_apm/configuration.rb, line 39
def [](key)
  @cache[key]
end
_callbacks_(direction, source, key) click to toggle source
# File lib/one_apm/configuration.rb, line 194
def _callbacks_ direction, source, key
  if @cache[key] != source[key]
    @callbacks[key].each do |proc|
      case direction
      when :add    then proc.call(source[key])
      when :append then proc.call(@cache[key], source[key])
      else proc.call(@cache[key])
      end
    end
  end
end
_invoke_callbacks_(source) click to toggle source
# File lib/one_apm/configuration.rb, line 179
def _invoke_callbacks_ source
  return unless source
  @directions = directions(source)
  source.keys.each do |key|
    _callbacks_(@directions[key], source, key) 
  end
end
add_config_for_testing(source, level=0) click to toggle source
# File lib/one_apm/configuration.rb, line 51
def add_config_for_testing(source, level=0)
  raise 'Invalid config type for testing' unless [Hash, OneApm::Support::DottedHash].include?(source.class)
  invoke_callbacks(:add, source)
  @configs_for_testing << [source.freeze, level]
  reset_cache
  log_config(:add, source)
end
app_name() click to toggle source
# File lib/one_apm/configuration.rb, line 269
def app_name
  OneApm::Manager.config[:app_name]
end
apply_mask(hash) click to toggle source
# File lib/one_apm/configuration.rb, line 238
def apply_mask(hash)
  OA_MASK_DEFAULTS. \
    select {|_, proc| proc.call}. \
    each {|key, _| hash.delete(key) }
  hash
end
apply_transformations(key, value) click to toggle source
# File lib/one_apm/configuration.rb, line 157
def apply_transformations(key, value)
  if transform = transform_from_default(key)
    begin
      transform.call(value)
    rescue => e
      OneApm::Manager.logger.error("Error applying transformation for #{key}, falling back to #{value}.", e)
      raise e
    end
  else
    value
  end
end
break_label_string_into_pairs(labels) click to toggle source
# File lib/one_apm/configuration.rb, line 305
def break_label_string_into_pairs(labels)
  stripped_labels = labels.strip
  stripped_labels.split(';').map do |pair|
    pair.split(':').map(&:strip)
  end
end
config_classes_for_testing() click to toggle source
# File lib/one_apm/configuration.rb, line 426
def config_classes_for_testing
  config_stack.map(&:class)
end
configure(source) { || ... } click to toggle source
# File lib/one_apm/configuration.rb, line 103
def configure source
  source.freeze
  was_finished = finished_configuring?
  operation = yield
  case source
  when HighSecuritySource then @high_security_source = source
  when EnvironmentSource  then @environment_source   = source
  when ServerSource       then @server_source        = source
  when ManualSource       then @manual_source        = source
  when YamlSource         then @yaml_source          = source
  when DefaultSource      then @default_source       = source
  else
    OneApm::Manager.logger.warn("Invalid config format; config will be ignored: #{source}")
  end
  reset_cache
  log_config(operation, source)
  notify_finished_configuring if !was_finished && finished_configuring?
end
delete_all_configs_for_testing() click to toggle source
# File lib/one_apm/configuration.rb, line 412
def delete_all_configs_for_testing
  @high_security_source = nil
  @environment_source   = nil
  @server_source        = nil
  @manual_source        = nil
  @yaml_source          = nil
  @default_source       = nil
  @configs_for_testing  = []
end
directions(source) click to toggle source
# File lib/one_apm/configuration.rb, line 206
def directions source
  h = Hash.new{|h, k| h[k] = :add}
  source.each do |key, value|
    h[key] = source[:"#{key}.direction"].to_sym if source[:"#{key}.direction"]
  end 
  h
end
evaluate_procs(value) click to toggle source
# File lib/one_apm/configuration.rb, line 149
def evaluate_procs(value)
  if value.respond_to?(:call)
    instance_eval(&value)
  else
    value
  end
end
fetch(key) click to toggle source
# File lib/one_apm/configuration.rb, line 130
def fetch(key)
  config_stack.each do |config|
    next unless config
    accessor = key.to_sym

    if config.has_key?(accessor)
      evaluated = evaluate_procs(config[accessor])

      begin
        return apply_transformations(accessor, evaluated)
      rescue
        next
      end
    end
  end

  nil
end
finished_configuring?() click to toggle source
# File lib/one_apm/configuration.rb, line 218
def finished_configuring?
  !@server_source.nil?
end
flattened() click to toggle source
# File lib/one_apm/configuration.rb, line 222
def flattened
  config_stack.reverse.inject({}) do |flat,layer|
    thawed_layer = layer.to_hash.dup
    thawed_layer.each do |k,v|
      begin
        thawed_layer[k] = instance_eval(&v) if v.respond_to?(:call)
      rescue => e
        OneApm::Manager.logger.debug("#{e.class.name} : #{e.message} - when accessing config key #{k}")
        thawed_layer[k] = nil
      end
      thawed_layer.delete(:config)
    end
    flat.merge(thawed_layer.to_hash)
  end
end
has_key?(key) click to toggle source
# File lib/one_apm/configuration.rb, line 43
def has_key?(key)
  @cache.has_key?[key]
end
invoke_callbacks(direction, source) click to toggle source
# File lib/one_apm/configuration.rb, line 187
def invoke_callbacks direction, source
  return unless source
  source.keys.each do |key|
   _callbacks_(direction, source, key)
  end
end
keys() click to toggle source
# File lib/one_apm/configuration.rb, line 47
def keys
  @cache.keys
end
limit_number_of_labels(pairs) click to toggle source
# File lib/one_apm/configuration.rb, line 361
def limit_number_of_labels(pairs)
  if pairs.length > MAX_LABEL_COUNT
    OneApm::Manager.logger.warn("Too many labels defined. Only taking first #{MAX_LABEL_COUNT}")
    pairs[0...64]
  else
    pairs
  end
end
log_config(direction, source) click to toggle source
# File lib/one_apm/configuration.rb, line 402
def log_config(direction, source)
  # Just generating this log message (specifically calling
  # flattened.inspect) is expensive enough that we don't want to do it
  # unless we're actually going to be logging the message based on our
  # current log level.
  OneApm::Manager.logger.debug do
    "Updating config (#{direction}) from #{source.class}. Results: #{flattened.inspect}"
  end
end
make_label_hash(pairs, labels = nil) click to toggle source
# File lib/one_apm/configuration.rb, line 328
def make_label_hash(pairs, labels = nil)
  # This can accept a hash, so force it down to an array of pairs first
  pairs = Array(pairs)

  unless valid_label_pairs?(pairs)
    OneApm::Manager.logger.warn("#{MALFORMED_LABELS_WARNING}: #{labels||pairs}")
    return []
  end

  pairs = limit_number_of_labels(pairs)
  pairs = remove_duplicates(pairs)
  pairs.map do |key, value|
    {
      'label_type'  => truncate(key),
      'label_value' => truncate(value.to_s, key)
    }
  end
end
notify_finished_configuring() click to toggle source
# File lib/one_apm/configuration.rb, line 214
def notify_finished_configuring
  OneApm::Manager.agent.events.notify(:finished_configuring)
end
num_configs_for_testing() click to toggle source
# File lib/one_apm/configuration.rb, line 422
def num_configs_for_testing
  config_stack.size
end
parse_labels_from_dictionary() click to toggle source

parse hash of labels delete key eql 'labels.xxx.notified'

# File lib/one_apm/configuration.rb, line 378
def parse_labels_from_dictionary
  labels = OneApm::Manager.config[:labels]
  labels.delete_if{|k, v| k.include?(".notified")}
  make_label_hash(labels)
end
parse_labels_from_string() click to toggle source
# File lib/one_apm/configuration.rb, line 299
def parse_labels_from_string
  labels = OneApm::Manager.config[:labels]
  label_pairs = break_label_string_into_pairs(labels)
  make_label_hash(label_pairs, labels)
end
parsed_labels() click to toggle source
# File lib/one_apm/configuration.rb, line 287
def parsed_labels
  case OneApm::Manager.config[:labels]
  when String
    parse_labels_from_string
  else
    parse_labels_from_dictionary
  end
rescue => e
  OneApm::Manager.logger.error(PARSING_LABELS_FAILURE, e)
  []
end
register_callback(key, &proc) click to toggle source
# File lib/one_apm/configuration.rb, line 174
def register_callback(key, &proc)
  @callbacks[key] << proc
  proc.call(@cache[key])
end
remove_config(source) click to toggle source
# File lib/one_apm/configuration.rb, line 72
def remove_config(source)
  case source
  when HighSecuritySource then @high_security_source = nil
  when EnvironmentSource  then @environment_source   = nil
  when ServerSource       then @server_source        = nil
  when ManualSource       then @manual_source        = nil
  when YamlSource         then @yaml_source          = nil
  when DefaultSource      then @default_source       = nil
  else
    @configs_for_testing.delete_if {|src,lvl| src == source}
  end

  reset_cache
  invoke_callbacks(:remove, source)
  log_config(:remove, source)
end
remove_config_type(sym) click to toggle source
# File lib/one_apm/configuration.rb, line 59
def remove_config_type(sym)
  source = case sym
  when :high_security then @high_security_source
  when :environment   then @environment_source
  when :server        then @server_source
  when :manual        then @manual_source
  when :yaml          then @yaml_source
  when :default       then @default_source
  end

  remove_config(source)
end
remove_duplicates(pairs) click to toggle source

We only take the last value provided for a given label type key

# File lib/one_apm/configuration.rb, line 371
def remove_duplicates(pairs)
  grouped_by_type = pairs.group_by(&:first)
  grouped_by_type.values.map(&:last)
end
replace_or_add_config(source) click to toggle source
# File lib/one_apm/configuration.rb, line 89
def replace_or_add_config source
  configure(source) do 
    invoke_callbacks(:add, source)
    :add
  end
end
reset_cache() click to toggle source
# File lib/one_apm/configuration.rb, line 398
def reset_cache
  @cache = Hash.new {|hash,key| hash[key] = self.fetch(key) }
end
reset_to_defaults() click to toggle source

Generally only useful during initial construction and tests

# File lib/one_apm/configuration.rb, line 385
def reset_to_defaults
  @high_security_source = nil
  @environment_source   = EnvironmentSource.new
  @server_source        = nil
  @manual_source        = nil
  @yaml_source          = nil
  @default_source       = DefaultSource.new

  @configs_for_testing  = []

  reset_cache
end
source(key) click to toggle source
# File lib/one_apm/configuration.rb, line 122
def source(key)
  config_stack.each do |config|
    if config.respond_to?(key.to_sym) || config.has_key?(key.to_sym)
      return config
    end
  end
end
tier_names() click to toggle source
# File lib/one_apm/configuration.rb, line 273
def tier_names
  case OneApm::Manager.config[:tier_name]
  when Array then OneApm::Manager.config[:tier_name]
  when String then OneApm::Manager.config[:tier_name].split(';')
  else []
  end
end
to_collector_hash() click to toggle source
# File lib/one_apm/configuration.rb, line 245
def to_collector_hash
  OneApm::Support::DottedHash.new(apply_mask(flattened)).to_hash.delete_if do |k, v|
    default = DEFAULTS[k]
    if default
      default[:local_only]
    else
      # In our tests, we add totally bogus configs, because testing.
      # In those cases, there will be no default. So we'll just let
      # them through.
      false
    end
  end
end
to_notified_hash() click to toggle source
# File lib/one_apm/configuration.rb, line 259
def to_notified_hash
  @notified_hash = {}
  to_collector_hash.each{|k, v| @notified_hash[k]= v.to_s}
  return @notified_hash unless OneApm::Manager.config[:'notified.enable']
  @notified_hash.select do |k, v|
    default = DEFAULTS[k]
    OneApm::Manager.config[:"#{k}.notified"] || (default && default.fetch(:notified, false))
  end
end
transform_from_default(key) click to toggle source
# File lib/one_apm/configuration.rb, line 170
def transform_from_default(key)
  ::OneApm::Configuration::DefaultSource.transform_for(key)
end
truncate(text, key=nil) click to toggle source
# File lib/one_apm/configuration.rb, line 347
def truncate(text, key=nil)
  if text.length > MAX_LABEL_LENGTH
    if key
      msg = "The value for the label '#{key}' is longer than the allowed #{MAX_LABEL_LENGTH} and will be truncated. Value = '#{text}'"
    else
      msg = "Label name longer than the allowed #{MAX_LABEL_LENGTH} will be truncated. Name = '#{text}'"
    end
    OneApm::Manager.logger.warn(msg)
    text[0..MAX_LABEL_LENGTH-1]
  else
    text
  end
end
update_config(source) click to toggle source
# File lib/one_apm/configuration.rb, line 96
def update_config source
  configure(source) do 
    _invoke_callbacks_(source)
    :update
  end
end
valid_label_item?(item) click to toggle source
# File lib/one_apm/configuration.rb, line 318
def valid_label_item?(item)
  case item
  when String  then !item.empty?
  when Numeric then true
  when true    then true
  when false   then true
  else false
  end
end
valid_label_pairs?(label_pairs) click to toggle source
# File lib/one_apm/configuration.rb, line 312
def valid_label_pairs?(label_pairs)
  label_pairs.all? do |pair|
    pair.length == 2 && valid_label_item?(pair.first) && valid_label_item?(pair.last)
  end
end

Private Instance Methods

config_stack() click to toggle source
# File lib/one_apm/configuration.rb, line 432
def config_stack
  stack = [
    @high_security_source,
    @environment_source,
    @server_source,
    @manual_source,
    @yaml_source,
    @default_source
  ]

  stack.compact!

  @configs_for_testing.each do |config, at_start|
    if at_start
      stack.insert(0, config)
    else
      stack.push(config)
    end
  end

  stack
end
constantize(class_name) click to toggle source
# File lib/one_apm/configuration.rb, line 467
def constantize(class_name)
  namespaces = class_name.split('::')

  namespaces.inject(Object) do |namespace, name|
    return unless namespace
    namespace.const_get(name) if namespace.const_defined?(name)
  end
end
parse_constant_list(list) click to toggle source
# File lib/one_apm/configuration.rb, line 455
def parse_constant_list(list)
  list.split(/\s*,\s*/).map do |class_name|
    const = constantize(class_name)

    unless const
      OneApm::Manager.logger.warn "Configuration referenced undefined constant: #{class_name}"
    end

    const
  end
end