2018-11-16 19:37:17 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-01-19 09:04:37 -05:00
|
|
|
# rubocop:disable Style/ClassVars
|
|
|
|
|
2018-01-12 11:55:53 -05:00
|
|
|
module Gitlab
|
|
|
|
module Metrics
|
2018-01-29 06:33:08 -05:00
|
|
|
module Methods
|
2018-01-12 11:55:53 -05:00
|
|
|
extend ActiveSupport::Concern
|
2018-01-19 09:04:37 -05:00
|
|
|
|
|
|
|
included do
|
2018-01-22 10:43:04 -05:00
|
|
|
@@_metric_provider_mutex ||= Mutex.new
|
2018-01-22 14:52:41 -05:00
|
|
|
@@_metrics_provider_cache = {}
|
2018-01-19 09:04:37 -05:00
|
|
|
end
|
2018-01-16 08:06:56 -05:00
|
|
|
|
2018-01-12 11:55:53 -05:00
|
|
|
class_methods do
|
2021-10-18 17:12:56 -04:00
|
|
|
def reload_metric!(name = nil)
|
|
|
|
if name.nil?
|
|
|
|
@@_metrics_provider_cache = {}
|
|
|
|
else
|
|
|
|
@@_metrics_provider_cache.delete(name)
|
|
|
|
end
|
2018-01-16 09:47:07 -05:00
|
|
|
end
|
|
|
|
|
2018-01-12 11:55:53 -05:00
|
|
|
private
|
|
|
|
|
2018-01-16 08:06:56 -05:00
|
|
|
def define_metric(type, name, opts = {}, &block)
|
2018-01-17 16:16:25 -05:00
|
|
|
if respond_to?(name)
|
2018-01-19 08:54:40 -05:00
|
|
|
raise ArgumentError, "method #{name} already exists"
|
2018-01-12 11:55:53 -05:00
|
|
|
end
|
|
|
|
|
2018-01-16 09:47:07 -05:00
|
|
|
define_singleton_method(name) do
|
2018-01-22 14:55:48 -05:00
|
|
|
# inlining fetch_metric method to avoid method call overhead when instrumenting hot spots
|
2018-01-22 14:52:41 -05:00
|
|
|
@@_metrics_provider_cache[name] || init_metric(type, name, opts, &block)
|
2018-01-16 08:06:56 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def fetch_metric(type, name, opts = {}, &block)
|
2018-01-22 14:52:41 -05:00
|
|
|
@@_metrics_provider_cache[name] || init_metric(type, name, opts, &block)
|
2018-01-19 08:54:40 -05:00
|
|
|
end
|
2018-01-16 08:06:56 -05:00
|
|
|
|
2018-01-19 08:54:40 -05:00
|
|
|
def init_metric(type, name, opts = {}, &block)
|
2020-06-30 11:08:48 -04:00
|
|
|
options = ::Gitlab::Metrics::Methods::MetricOptions.new(opts)
|
2018-01-16 08:06:56 -05:00
|
|
|
options.evaluate(&block)
|
|
|
|
|
2018-01-18 14:22:49 -05:00
|
|
|
if disabled_by_feature(options)
|
2021-02-09 22:09:31 -05:00
|
|
|
synchronized_cache_fill(name) { ::Gitlab::Metrics::NullMetric.instance }
|
2018-01-18 14:22:49 -05:00
|
|
|
else
|
|
|
|
synchronized_cache_fill(name) { build_metric!(type, name, options) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def synchronized_cache_fill(key)
|
2018-01-19 12:12:19 -05:00
|
|
|
@@_metric_provider_mutex.synchronize do
|
2018-01-22 14:52:41 -05:00
|
|
|
@@_metrics_provider_cache[key] ||= yield
|
2018-01-16 08:06:56 -05:00
|
|
|
end
|
2018-01-18 14:22:49 -05:00
|
|
|
end
|
2018-01-16 08:06:56 -05:00
|
|
|
|
2018-01-18 14:22:49 -05:00
|
|
|
def disabled_by_feature(options)
|
2022-05-10 20:08:02 -04:00
|
|
|
options.with_feature && !::Feature.enabled?(options.with_feature,
|
|
|
|
type: :undefined, default_enabled_if_undefined: false)
|
2018-01-16 08:06:56 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def build_metric!(type, name, options)
|
2018-01-12 11:55:53 -05:00
|
|
|
case type
|
2018-01-16 20:55:52 -05:00
|
|
|
when :gauge
|
2019-02-14 13:05:35 -05:00
|
|
|
::Gitlab::Metrics.gauge(name, options.docstring, options.base_labels, options.multiprocess_mode)
|
2018-01-16 20:55:52 -05:00
|
|
|
when :counter
|
2019-02-14 13:05:35 -05:00
|
|
|
::Gitlab::Metrics.counter(name, options.docstring, options.base_labels)
|
2018-01-16 20:55:52 -05:00
|
|
|
when :histogram
|
2019-02-14 13:05:35 -05:00
|
|
|
::Gitlab::Metrics.histogram(name, options.docstring, options.base_labels, options.buckets)
|
2018-01-16 20:55:52 -05:00
|
|
|
when :summary
|
|
|
|
raise NotImplementedError, "summary metrics are not currently supported"
|
|
|
|
else
|
|
|
|
raise ArgumentError, "uknown metric type #{type}"
|
2018-01-12 11:55:53 -05:00
|
|
|
end
|
2018-01-16 08:06:56 -05:00
|
|
|
end
|
2018-01-12 11:55:53 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|