class ElasticAPM::Metrics::Set

@api private

def collect

def collect
  return if disabled?
  @lock.synchronize do
    metrics.each_with_object({}) do |(key, metric), sets|
      next unless (value = metric.collect)
      # metrics have a key of name and flat array of key-value pairs
      #   eg [name, key, value, key, value]
      # they can be sent in the same metricset but not if they have
      # differing tags. So, we split the resulting sets by tags first.
      name, *tags = key
      sets[tags] ||= Metricset.new
      # then we set the `samples` value for the metricset
      set = sets[tags]
      set.samples[name] = value
      # and finally we copy the tags from the Metric to the Metricset
      set.merge_tags! metric.tags
    end.values
  end
end

def counter(key, tags: nil, **args)

def counter(key, tags: nil, **args)
  metric(Counter, key, tags: tags, **args)
end

def disable!

def disable!
  @disabled = true
end

def disabled?

def disabled?
  @disabled
end

def gauge(key, tags: nil, **args)

def gauge(key, tags: nil, **args)
  metric(Gauge, key, tags: tags, **args)
end

def initialize(config)

def initialize(config)
  @config = config
  @metrics = {}
  @disabled = false
  @lock = Mutex.new
end

def key_with_tags(key, tags)

def key_with_tags(key, tags)
  return key unless tags
  tuple = tags.keys.zip(tags.values)
  tuple.flatten!
  tuple.unshift(key)
end

def metric(kls, key, tags: nil, **args)

def metric(kls, key, tags: nil, **args)
  if @config.disable_metrics.any? { |p| p.match? key }
    return NOOP
  end
  key = key_with_tags(key, tags)
  return metrics[key] if metrics[key]
  @lock.synchronize do
    return metrics[key] if metrics[key]
    metrics[key] =
      if metrics.length < DISTINCT_LABEL_LIMIT
        kls.new(key, tags: tags, **args)
      else
        unless @label_limit_logged
          warn(
            'The limit of %d metricsets has been reached, no new ' \
             'metricsets will be created.', DISTINCT_LABEL_LIMIT
          )
          @label_limit_logged = true
        end
        NOOP
      end
  end
end

def timer(key, tags: nil, **args)

def timer(key, tags: nil, **args)
  metric(Timer, key, tags: tags, **args)
end