2018-01-12 16:55:53 +00:00
|
|
|
module Gitlab
|
|
|
|
module Metrics
|
|
|
|
module Concern
|
|
|
|
extend ActiveSupport::Concern
|
2018-01-17 18:15:50 +00:00
|
|
|
MUTEX = Mutex.new
|
2018-01-16 13:06:56 +00:00
|
|
|
|
2018-01-12 16:55:53 +00:00
|
|
|
class_methods do
|
2018-01-16 14:47:07 +00:00
|
|
|
def reload_metric!(name)
|
2018-01-17 18:15:50 +00:00
|
|
|
@_metrics_provider_cache&.delete(name)
|
2018-01-16 14:47:07 +00:00
|
|
|
end
|
|
|
|
|
2018-01-12 16:55:53 +00:00
|
|
|
private
|
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
def define_metric(type, name, opts = {}, &block)
|
2018-01-17 21:16:25 +00:00
|
|
|
if respond_to?(name)
|
2018-01-12 23:20:27 +00:00
|
|
|
raise ArgumentError, "metrics method #{name} already exists"
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
|
2018-01-16 14:47:07 +00:00
|
|
|
define_singleton_method(name) do
|
2018-01-16 13:06:56 +00:00
|
|
|
# avoid unnecessary method call to speed up metric access
|
2018-01-17 18:15:50 +00:00
|
|
|
metric = @_metrics_provider_cache&.[](name)
|
|
|
|
return metric if metric
|
2018-01-16 13:06:56 +00:00
|
|
|
|
|
|
|
fetch_metric(type, name, opts, &block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def fetch_metric(type, name, opts = {}, &block)
|
|
|
|
# avoid synchronization to speed up metrics access
|
2018-01-17 18:15:50 +00:00
|
|
|
metric = @_metrics_provider_cache&.[](name)
|
|
|
|
return metric if metric
|
2018-01-16 13:06:56 +00:00
|
|
|
|
|
|
|
options = MetricOptions.new(opts)
|
|
|
|
options.evaluate(&block)
|
|
|
|
|
2018-01-18 19:22:49 +00:00
|
|
|
if disabled_by_feature(options)
|
2018-01-19 13:54:06 +00:00
|
|
|
synchronized_cache_fill(name) { NullMetric.instance }
|
2018-01-18 19:22:49 +00:00
|
|
|
else
|
|
|
|
synchronized_cache_fill(name) { build_metric!(type, name, options) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def synchronized_cache_fill(key)
|
2018-01-17 18:15:50 +00:00
|
|
|
MUTEX.synchronize do
|
|
|
|
@_metrics_provider_cache ||= {}
|
2018-01-18 19:22:49 +00:00
|
|
|
@_metrics_provider_cache[key] ||= yield
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
2018-01-18 19:22:49 +00:00
|
|
|
end
|
2018-01-16 13:06:56 +00:00
|
|
|
|
2018-01-18 19:22:49 +00:00
|
|
|
def disabled_by_feature(options)
|
|
|
|
options.with_feature && !Feature.get(options.with_feature).enabled?
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def build_metric!(type, name, options)
|
2018-01-12 16:55:53 +00:00
|
|
|
case type
|
2018-01-17 01:55:52 +00:00
|
|
|
when :gauge
|
|
|
|
Gitlab::Metrics.gauge(name, options.docstring, options.base_labels, options.multiprocess_mode)
|
|
|
|
when :counter
|
|
|
|
Gitlab::Metrics.counter(name, options.docstring, options.base_labels)
|
|
|
|
when :histogram
|
|
|
|
Gitlab::Metrics.histogram(name, options.docstring, options.base_labels, options.buckets)
|
|
|
|
when :summary
|
|
|
|
raise NotImplementedError, "summary metrics are not currently supported"
|
|
|
|
else
|
|
|
|
raise ArgumentError, "uknown metric type #{type}"
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
2018-01-12 16:55:53 +00:00
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Fetch and/or initialize counter metric
|
|
|
|
# @param [Symbol] name
|
|
|
|
# @param [Hash] opts
|
|
|
|
def fetch_counter(name, opts = {}, &block)
|
2018-01-16 19:03:30 +00:00
|
|
|
fetch_metric(:counter, name, opts, &block)
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
2018-01-12 16:55:53 +00:00
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# DFetch and/or initialize gauge metric
|
|
|
|
# @param [Symbol] name
|
|
|
|
# @param [Hash] opts
|
|
|
|
def fetch_gauge(name, opts = {}, &block)
|
2018-01-17 21:16:25 +00:00
|
|
|
fetch_metric(:gauge, name, opts, &block)
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
2018-01-15 21:06:40 +00:00
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Fetch and/or initialize histogram metric
|
|
|
|
# @param [Symbol] name
|
|
|
|
# @param [Hash] opts
|
|
|
|
def fetch_histogram(name, opts = {}, &block)
|
2018-01-16 19:03:30 +00:00
|
|
|
fetch_metric(:histogram, name, opts, &block)
|
2018-01-16 13:06:56 +00:00
|
|
|
end
|
2018-01-12 16:55:53 +00:00
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Fetch and/or initialize summary metric
|
|
|
|
# @param [Symbol] name
|
|
|
|
# @param [Hash] opts
|
|
|
|
def fetch_summary(name, opts = {}, &block)
|
2018-01-16 19:03:30 +00:00
|
|
|
fetch_metric(:summary, name, opts, &block)
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Define metric accessor method for a Counter
|
2018-01-12 16:55:53 +00:00
|
|
|
# @param [Symbol] name
|
2018-01-16 13:06:56 +00:00
|
|
|
# @param [Hash] opts
|
|
|
|
def define_counter(name, opts = {}, &block)
|
|
|
|
define_metric(:counter, name, opts, &block)
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Define metric accessor method for a Gauge
|
2018-01-12 16:55:53 +00:00
|
|
|
# @param [Symbol] name
|
2018-01-16 13:06:56 +00:00
|
|
|
# @param [Hash] opts
|
|
|
|
def define_gauge(name, opts = {}, &block)
|
2018-01-17 21:16:25 +00:00
|
|
|
define_metric(:gauge, name, opts, &block)
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# Define metric accessor method for a Histogram
|
2018-01-12 16:55:53 +00:00
|
|
|
# @param [Symbol] name
|
2018-01-16 13:06:56 +00:00
|
|
|
# @param [Hash] opts
|
|
|
|
def define_histogram(name, opts = {}, &block)
|
|
|
|
define_metric(:histogram, name, opts, &block)
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
|
2018-01-16 13:06:56 +00:00
|
|
|
# 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)
|
2018-01-12 16:55:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|