1# frozen_string_literal: true 2 3# rubocop:disable Style/ClassVars 4 5module Gitlab 6 module Metrics 7 module Methods 8 extend ActiveSupport::Concern 9 10 included do 11 @@_metric_provider_mutex ||= Mutex.new 12 @@_metrics_provider_cache = {} 13 end 14 15 class_methods do 16 def reload_metric!(name = nil) 17 if name.nil? 18 @@_metrics_provider_cache = {} 19 else 20 @@_metrics_provider_cache.delete(name) 21 end 22 end 23 24 private 25 26 def define_metric(type, name, opts = {}, &block) 27 if respond_to?(name) 28 raise ArgumentError, "method #{name} already exists" 29 end 30 31 define_singleton_method(name) do 32 # inlining fetch_metric method to avoid method call overhead when instrumenting hot spots 33 @@_metrics_provider_cache[name] || init_metric(type, name, opts, &block) 34 end 35 end 36 37 def fetch_metric(type, name, opts = {}, &block) 38 @@_metrics_provider_cache[name] || init_metric(type, name, opts, &block) 39 end 40 41 def init_metric(type, name, opts = {}, &block) 42 options = ::Gitlab::Metrics::Methods::MetricOptions.new(opts) 43 options.evaluate(&block) 44 45 if disabled_by_feature(options) 46 synchronized_cache_fill(name) { ::Gitlab::Metrics::NullMetric.instance } 47 else 48 synchronized_cache_fill(name) { build_metric!(type, name, options) } 49 end 50 end 51 52 def synchronized_cache_fill(key) 53 @@_metric_provider_mutex.synchronize do 54 @@_metrics_provider_cache[key] ||= yield 55 end 56 end 57 58 def disabled_by_feature(options) 59 options.with_feature && !::Feature.enabled?(options.with_feature, type: :ops) 60 end 61 62 def build_metric!(type, name, options) 63 case type 64 when :gauge 65 ::Gitlab::Metrics.gauge(name, options.docstring, options.base_labels, options.multiprocess_mode) 66 when :counter 67 ::Gitlab::Metrics.counter(name, options.docstring, options.base_labels) 68 when :histogram 69 ::Gitlab::Metrics.histogram(name, options.docstring, options.base_labels, options.buckets) 70 when :summary 71 raise NotImplementedError, "summary metrics are not currently supported" 72 else 73 raise ArgumentError, "uknown metric type #{type}" 74 end 75 end 76 end 77 end 78 end 79end 80