Initiaal implementation of metrics concern
This commit is contained in:
parent
51897df564
commit
ef44fef15f
3 changed files with 96 additions and 44 deletions
84
lib/gitlab/metrics/concern.rb
Normal file
84
lib/gitlab/metrics/concern.rb
Normal file
|
@ -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
|
||||
# Class for tracking timing information about method calls
|
||||
class MethodCall
|
||||
@@measurement_enabled_cache = Concurrent::AtomicBoolean.new(false)
|
||||
@@measurement_enabled_cache_expires_at = Concurrent::AtomicReference.new(Time.now.to_i)
|
||||
MUTEX = Mutex.new
|
||||
include Gitlab::Metrics::Concern
|
||||
BASE_LABELS = { module: nil, method: nil }.freeze
|
||||
attr_reader :real_time, :cpu_time, :call_count, :labels
|
||||
|
||||
def self.call_duration_histogram
|
||||
return @call_duration_histogram if @call_duration_histogram
|
||||
|
||||
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
|
||||
histogram :gitlab_method_call_duration_seconds, 'Method calls real duration',
|
||||
base_labels: Transaction::BASE_LABELS.merge(BASE_LABELS),
|
||||
buckets: [0.01, 0.05, 0.1, 0.5, 1]
|
||||
|
||||
# name - The full name of the method (including namespace) such as
|
||||
# `User#sign_in`.
|
||||
|
@ -53,8 +39,8 @@ module Gitlab
|
|||
@cpu_time += cpu_time
|
||||
@call_count += 1
|
||||
|
||||
if call_measurement_enabled? && above_threshold?
|
||||
self.class.call_duration_histogram.observe(@transaction.labels.merge(labels), real_time)
|
||||
if above_threshold?
|
||||
gitlab_method_call_duration_seconds.observe(@transaction.labels.merge(labels), real_time)
|
||||
end
|
||||
|
||||
retval
|
||||
|
@ -78,17 +64,6 @@ module Gitlab
|
|||
def above_threshold?
|
||||
real_time.in_milliseconds >= Metrics.method_call_threshold
|
||||
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
|
||||
|
|
|
@ -3,6 +3,11 @@ module Gitlab
|
|||
module Subscribers
|
||||
# Class for tracking the rendering timings of views.
|
||||
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
|
||||
|
||||
SERIES = 'views'.freeze
|
||||
|
@ -15,23 +20,11 @@ module Gitlab
|
|||
|
||||
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)
|
||||
values = values_for(event)
|
||||
tags = tags_for(event)
|
||||
|
||||
metric_view_rendering_duration_seconds.observe(
|
||||
current_transaction.labels.merge(tags),
|
||||
event.duration
|
||||
)
|
||||
gitlab_view_rendering_duration_seconds.observe(current_transaction.labels.merge(tags), event.duration)
|
||||
|
||||
current_transaction.increment(:view_duration, event.duration)
|
||||
current_transaction.add_metric(SERIES, values, tags)
|
||||
|
|
Loading…
Reference in a new issue