Commit 53f818fd authored by Pawel Chojnacki's avatar Pawel Chojnacki

Refactor method concern to use hashes

parent e56b3d18
...@@ -2,86 +2,122 @@ module Gitlab ...@@ -2,86 +2,122 @@ module Gitlab
module Metrics module Metrics
module Concern module Concern
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
@@_metrics_provider_mutex ||= Mutex.new
@@_metrics_provider_cache ||= {}
end
class_methods do class_methods do
private private
def metrics_provider(type, name, docstring, options = {}) def define_metric(type, name, opts = {}, &block)
@@_metrics_provider_mutex ||= Mutex.new
if instance_methods(false).include?(name) if instance_methods(false).include?(name)
raise ArgumentError, "metrics method #{name} already exists" raise ArgumentError, "metrics method #{name} already exists"
end end
options[:base_labels] ||= {}
args = [name.inspect, %{"#{docstring}"}, options[:base_labels].inspect] define_method(name) do
# avoid unnecessary method call to speed up metric access
return @@_metrics_provider_cache[name] if @@_metrics_provider_cache.has_key?(name)
fetch_metric(type, name, opts, &block)
end
end
def fetch_metric(type, name, opts = {}, &block)
# avoid synchronization to speed up metrics access
return @@_metrics_provider_cache[name] if @@_metrics_provider_cache.has_key?(name)
options = MetricOptions.new(opts)
options.evaluate(&block)
@@_metrics_provider_mutex.synchronize do
@@_metrics_provider_cache[name] ||= build_metric!(type, name, options)
end
@@_metrics_provider_cache[name]
end
def build_metric!(type, name, options)
unless options.with_feature.nil? || Feature.get(options.with_feature).enabled?
return NullMetric.new
end
case type case type
when :gauge when :gauge
options[:multiprocess_mode] ||= :all Gitlab::Metrics.gauge(name, options.docs, options.base_labels, options.multiprocess_mode)
args << options[:multiprocess_mode].inspect when :counter
Gitlab::Metrics.counter(name, options.docs, options.base_labels)
when :histogram when :histogram
options[:buckets] ||= ::Prometheus::Client::Histogram::DEFAULT_BUCKETS options[:buckets] ||= ::Prometheus::Client::Histogram::DEFAULT_BUCKETS
args << options[:buckets].inspect Gitlab::Metrics.histogram(name, options.docs, options.base_labels, options.buckets)
when :summary
raise NotImplementedError, "summary metrics are not currently supported"
else
raise ArgumentError, "uknown metric type #{type}"
end end
end
metric_fetching_code = %{Gitlab::Metrics.#{type}(#{args.join(', ')})} counter :global do
docstring "Global counter"
# optionally wrap in feature multiprocess_mode :all
if options[:with_feature].is_a?(Symbol) buckets [0, 1]
metric_fetching_code = <<-FETCH.strip_heredoc end
if Feature.get(#{options[:with_feature].inspect}).enabled?
#{metric_fetching_code}
else
Gitlab::Metrics::NullMetric.new
end
FETCH
end
method_code, line = <<-METRIC, __LINE__ + 1 # Fetch and/or initialize counter metric
@@_metric_provider_cached_#{name} = nil # @param [Symbol] name
def #{name} # @param [Hash] opts
return @@_metric_provider_cached_#{name} if @@_metric_provider_cached_#{name} def fetch_counter(name, opts = {}, &block)
define_metric(:counter, name, opts, &block)
end
@@_metrics_provider_mutex.synchronize do # DFetch and/or initialize gauge metric
@@_metric_provider_cached_#{name} ||= #{metric_fetching_code} # @param [Symbol] name
end # @param [Hash] opts
end def fetch_gauge(name, opts = {}, &block)
define_metric(:counter, name, opts, &block)
end
def reload_#{name}! # Fetch and/or initialize histogram metric
@@_metric_provider_cached_#{name} = nil # @param [Symbol] name
end # @param [Hash] opts
METRIC def fetch_histogram(name, opts = {}, &block)
define_metric(:histogram, name, opts, &block)
end
instance_eval(method_code, __FILE__, line) # Fetch and/or initialize summary metric
module_eval(method_code, __FILE__, line) # @param [Symbol] name
# @param [Hash] opts
def fetch_summary(name, opts = {}, &block)
define_metric(:summary, name, opts, &block)
end end
# Declare a Counter # Define metric accessor method for a Counter
# @param [Symbol] name # @param [Symbol] name
# @param [String] docstring # @param [Hash] opts
# @param [Hash] options def define_counter(name, opts = {}, &block)
def counter(name, docstring, options = {}) define_metric(:counter, name, opts, &block)
metrics_provider(:counter, name, docstring, options)
end end
# Declare a Gauge # Define metric accessor method for a Gauge
# @param [Symbol] name # @param [Symbol] name
# @param [String] docstring # @param [Hash] opts
# @param [Hash] options def define_gauge(name, opts = {}, &block)
def gauge(name, docstring, options = {}) define_metric(:counter, name, opts, &block)
metrics_provider(:counter, name, docstring, options)
end end
# Declare a Histograam # Define metric accessor method for a Histogram
# @param [Symbol] name # @param [Symbol] name
# @param [String] docstring # @param [Hash] opts
# @param [Hash] options def define_histogram(name, opts = {}, &block)
def histogram(name, docstring, options = {}) define_metric(:histogram, name, opts, &block)
metrics_provider(:histogram, name, docstring, options)
end end
def summary(*args) # Define metric accessor method for a Summary
raise NotImplementedError, "summary metrics are not currently supported" # @param [Symbol] name
# @param [Hash] opts
def define_summary(name, opts = {}, &block)
define_metric(:summary, name, opts, &block)
end end
end end
end end
......
module Gitlab
module Metrics
module Concern
class MetricOptions
def initialize(options = {})
@multiprocess_mode = options[:multiprocess_mode] || :all
@buckets = options[:buckets] || ::Prometheus::Client::Histogram::DEFAULT_BUCKETS
@base_labels = options[:base_labels] || {}
end
def docs(docs = nil)
@docs = docs unless docs.nil?
@docs
end
def multiprocess_mode(mode)
@multiprocess_mode = mode unless @multiprocess_mode.nil?
@multiprocess_mode
end
def buckets(buckets)
@buckets = buckets unless @buckets.nil?
@buckets
end
def base_labels(base_labels)
@base_labels = base_labels unless @base_labels.nil?
@base_labels
end
def with_feature(name)
@feature_name = name unless @feature_name.nil?
@feature_name
end
def evaluate(&block)
instance_eval(&block) if block_given?
self
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment