Initiaal implementation of metrics concern
This commit is contained in:
parent
51897df564
commit
ef44fef15f
|
|
@ -0,0 +1,84 @@
|
||||||
|
module Gitlab
|
||||||
|
module Metrics
|
||||||
|
module Concern
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
class_methods do
|
||||||
|
private
|
||||||
|
|
||||||
|
def metrics_provider(type, name, docstring, options = {})
|
||||||
|
@@_metrics_provider_mutex ||= Mutex.new
|
||||||
|
|
||||||
|
if instance_methods(false).include?(name)
|
||||||
|
raise ArgumentError, "metrics class method #{name} already exists"
|
||||||
|
end
|
||||||
|
options[:base_labels] ||= {}
|
||||||
|
|
||||||
|
args = [name.inspect, %{"#{docstring}"}, options[:base_labels].inspect]
|
||||||
|
|
||||||
|
case type
|
||||||
|
when :gauge
|
||||||
|
options[:multiprocess_mode] ||= :all
|
||||||
|
args << options[:multiprocess_mode].inspect
|
||||||
|
when :histogram
|
||||||
|
options[:buckets] ||= ::Prometheus::Client::Histogram::DEFAULT_BUCKETS
|
||||||
|
args << options[:buckets].inspect
|
||||||
|
end
|
||||||
|
|
||||||
|
metric_fetching_code = %{Gitlab::Metrics::Prometheus.#{type}(#{args.join(', ')})}
|
||||||
|
|
||||||
|
# optionally wrap in feature
|
||||||
|
metric_fetching_code = if options[:with_feature].is_a?(Symbol)
|
||||||
|
<<-FETCH.strip_heredoc
|
||||||
|
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
|
||||||
|
def #{name}
|
||||||
|
@@_metric_provider_cached_#{name} if @@_metric_provider_cached_#{name}
|
||||||
|
|
||||||
|
@@_metrics_provider_mutex.synchronize do
|
||||||
|
@_metric_provider_cached_#{name} ||= #{metric_fetching_code}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
METRIC
|
||||||
|
|
||||||
|
class_eval(method_code, __FILE__, line)
|
||||||
|
module_eval(method_code, __FILE__, line)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Declare a Counter
|
||||||
|
# @param [Symbol] name
|
||||||
|
# @param [String] docstring
|
||||||
|
# @param [Hash] opts
|
||||||
|
def counter(name, docstring, opts = {})
|
||||||
|
metrics_provider(:counter, name, docstring, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Declare a Gauge
|
||||||
|
# @param [Symbol] name
|
||||||
|
# @param [String] docstring
|
||||||
|
# @param [Hash] opts
|
||||||
|
def gauge(name, docstring, opts = {})
|
||||||
|
metrics_provider(:counter, name, docstring, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Declare a Histograam
|
||||||
|
# @param [Symbol] name
|
||||||
|
# @param [String] docstring
|
||||||
|
# @param [Hash] opts
|
||||||
|
def histogram(name, docstring, opts = {})
|
||||||
|
metrics_provider(:histogram, name, docstring, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def summary(*args)
|
||||||
|
raise NotImplementedError, "summary metrics are not currently supported"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -4,27 +4,13 @@ module Gitlab
|
||||||
module Metrics
|
module Metrics
|
||||||
# Class for tracking timing information about method calls
|
# Class for tracking timing information about method calls
|
||||||
class MethodCall
|
class MethodCall
|
||||||
@@measurement_enabled_cache = Concurrent::AtomicBoolean.new(false)
|
include Gitlab::Metrics::Concern
|
||||||
@@measurement_enabled_cache_expires_at = Concurrent::AtomicReference.new(Time.now.to_i)
|
|
||||||
MUTEX = Mutex.new
|
|
||||||
BASE_LABELS = { module: nil, method: nil }.freeze
|
BASE_LABELS = { module: nil, method: nil }.freeze
|
||||||
attr_reader :real_time, :cpu_time, :call_count, :labels
|
attr_reader :real_time, :cpu_time, :call_count, :labels
|
||||||
|
|
||||||
def self.call_duration_histogram
|
histogram :gitlab_method_call_duration_seconds, 'Method calls real duration',
|
||||||
return @call_duration_histogram if @call_duration_histogram
|
base_labels: Transaction::BASE_LABELS.merge(BASE_LABELS),
|
||||||
|
buckets: [0.01, 0.05, 0.1, 0.5, 1]
|
||||||
MUTEX.synchronize do
|
|
||||||
@call_duration_histogram ||= Gitlab::Metrics.histogram(
|
|
||||||
:gitlab_method_call_duration_seconds,
|
|
||||||
'Method calls real duration',
|
|
||||||
Transaction::BASE_LABELS.merge(BASE_LABELS),
|
|
||||||
[0.01, 0.05, 0.1, 0.5, 1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.measurement_enabled_cache_expires_at
|
|
||||||
@@measurement_enabled_cache_expires_at
|
|
||||||
end
|
|
||||||
|
|
||||||
# name - The full name of the method (including namespace) such as
|
# name - The full name of the method (including namespace) such as
|
||||||
# `User#sign_in`.
|
# `User#sign_in`.
|
||||||
|
|
@ -53,8 +39,8 @@ module Gitlab
|
||||||
@cpu_time += cpu_time
|
@cpu_time += cpu_time
|
||||||
@call_count += 1
|
@call_count += 1
|
||||||
|
|
||||||
if call_measurement_enabled? && above_threshold?
|
if above_threshold?
|
||||||
self.class.call_duration_histogram.observe(@transaction.labels.merge(labels), real_time)
|
gitlab_method_call_duration_seconds.observe(@transaction.labels.merge(labels), real_time)
|
||||||
end
|
end
|
||||||
|
|
||||||
retval
|
retval
|
||||||
|
|
@ -78,17 +64,6 @@ module Gitlab
|
||||||
def above_threshold?
|
def above_threshold?
|
||||||
real_time.in_milliseconds >= Metrics.method_call_threshold
|
real_time.in_milliseconds >= Metrics.method_call_threshold
|
||||||
end
|
end
|
||||||
|
|
||||||
def call_measurement_enabled?
|
|
||||||
expires_at = @@measurement_enabled_cache_expires_at.value
|
|
||||||
if expires_at < Time.now.to_i
|
|
||||||
if @@measurement_enabled_cache_expires_at.compare_and_set(expires_at, 1.minute.from_now.to_i)
|
|
||||||
@@measurement_enabled_cache.value = Feature.get(:prometheus_metrics_method_instrumentation).enabled?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@@measurement_enabled_cache.value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@ module Gitlab
|
||||||
module Subscribers
|
module Subscribers
|
||||||
# Class for tracking the rendering timings of views.
|
# Class for tracking the rendering timings of views.
|
||||||
class ActionView < ActiveSupport::Subscriber
|
class ActionView < ActiveSupport::Subscriber
|
||||||
|
include Gitlab::Metrics::Concern
|
||||||
|
histogram :gitlab_view_rendering_duration_seconds, 'View rendering time',
|
||||||
|
base_labels: Transaction::BASE_LABELS.merge({ path: nil }),
|
||||||
|
buckets: [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.500, 2.0, 10.0]
|
||||||
|
|
||||||
attach_to :action_view
|
attach_to :action_view
|
||||||
|
|
||||||
SERIES = 'views'.freeze
|
SERIES = 'views'.freeze
|
||||||
|
|
@ -15,23 +20,11 @@ module Gitlab
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def metric_view_rendering_duration_seconds
|
|
||||||
@metric_view_rendering_duration_seconds ||= Gitlab::Metrics.histogram(
|
|
||||||
:gitlab_view_rendering_duration_seconds,
|
|
||||||
'View rendering time',
|
|
||||||
Transaction::BASE_LABELS.merge({ path: nil }),
|
|
||||||
[0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.500, 2.0, 10.0]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def track(event)
|
def track(event)
|
||||||
values = values_for(event)
|
values = values_for(event)
|
||||||
tags = tags_for(event)
|
tags = tags_for(event)
|
||||||
|
|
||||||
metric_view_rendering_duration_seconds.observe(
|
gitlab_view_rendering_duration_seconds.observe(current_transaction.labels.merge(tags), event.duration)
|
||||||
current_transaction.labels.merge(tags),
|
|
||||||
event.duration
|
|
||||||
)
|
|
||||||
|
|
||||||
current_transaction.increment(:view_duration, event.duration)
|
current_transaction.increment(:view_duration, event.duration)
|
||||||
current_transaction.add_metric(SERIES, values, tags)
|
current_transaction.add_metric(SERIES, values, tags)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue