summaryrefslogtreecommitdiff
path: root/lib/gitlab/metrics
diff options
context:
space:
mode:
authorPawel Chojnacki <pawel@chojnacki.ws>2018-01-16 14:06:56 +0100
committerPawel Chojnacki <pawel@chojnacki.ws>2018-01-29 15:13:03 +0100
commit53f818fdac35d1c0810faa81a8dde20bbf8a3697 (patch)
tree7112880079fe0ed6daaa5bb6af797d56d3b4da60 /lib/gitlab/metrics
parente56b3d180dc9b251f00f0611435a6f25d708d2b6 (diff)
downloadgitlab-ce-53f818fdac35d1c0810faa81a8dde20bbf8a3697.tar.gz
Refactor method concern to use hashes
Diffstat (limited to 'lib/gitlab/metrics')
-rw-r--r--lib/gitlab/metrics/concern.rb138
-rw-r--r--lib/gitlab/metrics/concern/metric_options.rb48
2 files changed, 135 insertions, 51 deletions
diff --git a/lib/gitlab/metrics/concern.rb b/lib/gitlab/metrics/concern.rb
index 940337deb74..a9c45380a5d 100644
--- a/lib/gitlab/metrics/concern.rb
+++ b/lib/gitlab/metrics/concern.rb
@@ -2,86 +2,122 @@ module Gitlab
module Metrics
module Concern
extend ActiveSupport::Concern
+
+ included do
+ @@_metrics_provider_mutex ||= Mutex.new
+ @@_metrics_provider_cache ||= {}
+ end
+
class_methods do
private
- def metrics_provider(type, name, docstring, options = {})
- @@_metrics_provider_mutex ||= Mutex.new
-
+ def define_metric(type, name, opts = {}, &block)
if instance_methods(false).include?(name)
raise ArgumentError, "metrics method #{name} already exists"
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
when :gauge
- options[:multiprocess_mode] ||= :all
- args << options[:multiprocess_mode].inspect
+ Gitlab::Metrics.gauge(name, options.docs, options.base_labels, options.multiprocess_mode)
+ when :counter
+ Gitlab::Metrics.counter(name, options.docs, options.base_labels)
when :histogram
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
- metric_fetching_code = %{Gitlab::Metrics.#{type}(#{args.join(', ')})}
-
- # optionally wrap in feature
- if options[:with_feature].is_a?(Symbol)
- metric_fetching_code = <<-FETCH.strip_heredoc
- if Feature.get(#{options[:with_feature].inspect}).enabled?
- #{metric_fetching_code}
- else
- Gitlab::Metrics::NullMetric.new
- end
- FETCH
- end
+ counter :global do
+ docstring "Global counter"
+ multiprocess_mode :all
+ buckets [0, 1]
+ end
- method_code, line = <<-METRIC, __LINE__ + 1
- @@_metric_provider_cached_#{name} = nil
- def #{name}
- return @@_metric_provider_cached_#{name} if @@_metric_provider_cached_#{name}
+ # Fetch and/or initialize counter metric
+ # @param [Symbol] name
+ # @param [Hash] opts
+ def fetch_counter(name, opts = {}, &block)
+ define_metric(:counter, name, opts, &block)
+ end
- @@_metrics_provider_mutex.synchronize do
- @@_metric_provider_cached_#{name} ||= #{metric_fetching_code}
- end
- end
+ # DFetch and/or initialize gauge metric
+ # @param [Symbol] name
+ # @param [Hash] opts
+ def fetch_gauge(name, opts = {}, &block)
+ define_metric(:counter, name, opts, &block)
+ end
- def reload_#{name}!
- @@_metric_provider_cached_#{name} = nil
- end
- METRIC
+ # Fetch and/or initialize histogram metric
+ # @param [Symbol] name
+ # @param [Hash] opts
+ def fetch_histogram(name, opts = {}, &block)
+ define_metric(:histogram, name, opts, &block)
+ end
- instance_eval(method_code, __FILE__, line)
- module_eval(method_code, __FILE__, line)
+ # Fetch and/or initialize summary metric
+ # @param [Symbol] name
+ # @param [Hash] opts
+ def fetch_summary(name, opts = {}, &block)
+ define_metric(:summary, name, opts, &block)
end
- # Declare a Counter
+ # Define metric accessor method for a Counter
# @param [Symbol] name
- # @param [String] docstring
- # @param [Hash] options
- def counter(name, docstring, options = {})
- metrics_provider(:counter, name, docstring, options)
+ # @param [Hash] opts
+ def define_counter(name, opts = {}, &block)
+ define_metric(:counter, name, opts, &block)
end
- # Declare a Gauge
+ # Define metric accessor method for a Gauge
# @param [Symbol] name
- # @param [String] docstring
- # @param [Hash] options
- def gauge(name, docstring, options = {})
- metrics_provider(:counter, name, docstring, options)
+ # @param [Hash] opts
+ def define_gauge(name, opts = {}, &block)
+ define_metric(:counter, name, opts, &block)
end
- # Declare a Histograam
+ # Define metric accessor method for a Histogram
# @param [Symbol] name
- # @param [String] docstring
- # @param [Hash] options
- def histogram(name, docstring, options = {})
- metrics_provider(:histogram, name, docstring, options)
+ # @param [Hash] opts
+ def define_histogram(name, opts = {}, &block)
+ define_metric(:histogram, name, opts, &block)
end
- def summary(*args)
- raise NotImplementedError, "summary metrics are not currently supported"
+ # Define metric accessor method for a Summary
+ # @param [Symbol] name
+ # @param [Hash] opts
+ def define_summary(name, opts = {}, &block)
+ define_metric(:summary, name, opts, &block)
end
end
end
diff --git a/lib/gitlab/metrics/concern/metric_options.rb b/lib/gitlab/metrics/concern/metric_options.rb
new file mode 100644
index 00000000000..502805c135a
--- /dev/null
+++ b/lib/gitlab/metrics/concern/metric_options.rb
@@ -0,0 +1,48 @@
+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