Commit ef44fef1 authored by Pawel Chojnacki's avatar Pawel Chojnacki

Initiaal implementation of metrics concern

parent 51897df5
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment