diff options
Diffstat (limited to 'lib/gitlab/metrics')
-rw-r--r-- | lib/gitlab/metrics/dashboard/url.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/metrics/exporter/sidekiq_exporter.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/metrics/influx_db.rb | 183 | ||||
-rw-r--r-- | lib/gitlab/metrics/method_call.rb | 13 | ||||
-rw-r--r-- | lib/gitlab/metrics/metric.rb | 54 | ||||
-rw-r--r-- | lib/gitlab/metrics/rack_middleware.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/metrics/samplers/database_sampler.rb | 58 | ||||
-rw-r--r-- | lib/gitlab/metrics/samplers/influx_sampler.rb | 49 | ||||
-rw-r--r-- | lib/gitlab/metrics/samplers/puma_sampler.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/metrics/samplers/ruby_sampler.rb | 26 | ||||
-rw-r--r-- | lib/gitlab/metrics/sidekiq_middleware.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/metrics/subscribers/action_view.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/metrics/system.rb | 81 | ||||
-rw-r--r-- | lib/gitlab/metrics/transaction.rb | 56 |
14 files changed, 126 insertions, 414 deletions
diff --git a/lib/gitlab/metrics/dashboard/url.rb b/lib/gitlab/metrics/dashboard/url.rb index 1d948883151..31670a3f533 100644 --- a/lib/gitlab/metrics/dashboard/url.rb +++ b/lib/gitlab/metrics/dashboard/url.rb @@ -23,7 +23,7 @@ module Gitlab %r{ /environments /(?<environment>\d+) - /metrics + /(metrics_dashboard|metrics) }x ) end diff --git a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb index 5ba7b29734b..054b4949dd6 100644 --- a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb +++ b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb @@ -32,7 +32,7 @@ module Gitlab Sidekiq.logger.error( class: self.class.to_s, message: 'Cannot start sidekiq_exporter', - exception: e.message + 'exception.message' => e.message ) false diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb deleted file mode 100644 index 1f252572461..00000000000 --- a/lib/gitlab/metrics/influx_db.rb +++ /dev/null @@ -1,183 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Metrics - module InfluxDb - extend ActiveSupport::Concern - include Gitlab::Metrics::Methods - - EXECUTION_MEASUREMENT_BUCKETS = [0.001, 0.01, 0.1, 1].freeze - - MUTEX = Mutex.new - private_constant :MUTEX - - class_methods do - def influx_metrics_enabled? - settings[:enabled] || false - end - - # Prometheus histogram buckets used for arbitrary code measurements - - def settings - @settings ||= begin - current_settings = Gitlab::CurrentSettings.current_application_settings - - { - enabled: current_settings[:metrics_enabled], - pool_size: current_settings[:metrics_pool_size], - timeout: current_settings[:metrics_timeout], - method_call_threshold: current_settings[:metrics_method_call_threshold], - host: current_settings[:metrics_host], - port: current_settings[:metrics_port], - sample_interval: current_settings[:metrics_sample_interval] || 15, - packet_size: current_settings[:metrics_packet_size] || 1 - } - end - end - - def mri? - RUBY_ENGINE == 'ruby' - end - - def method_call_threshold - # This is memoized since this method is called for every instrumented - # method. Loading data from an external cache on every method call slows - # things down too much. - # in milliseconds - @method_call_threshold ||= settings[:method_call_threshold] - end - - def submit_metrics(metrics) - prepared = prepare_metrics(metrics) - - pool&.with do |connection| - prepared.each_slice(settings[:packet_size]) do |slice| - connection.write_points(slice) - rescue StandardError - end - end - rescue Errno::EADDRNOTAVAIL, SocketError => ex - Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.') - Gitlab::EnvironmentLogger.error(ex) - end - - def prepare_metrics(metrics) - metrics.map do |hash| - new_hash = hash.symbolize_keys - - new_hash[:tags].each do |key, value| - if value.blank? - new_hash[:tags].delete(key) - else - new_hash[:tags][key] = escape_value(value) - end - end - - new_hash - end - end - - def escape_value(value) - value.to_s.gsub('=', '\\=') - end - - # Measures the execution time of a block. - # - # Example: - # - # Gitlab::Metrics.measure(:find_by_username_duration) do - # UserFinder.new(some_username).find_by_username - # end - # - # name - The name of the field to store the execution time in. - # - # Returns the value yielded by the supplied block. - def measure(name) - trans = current_transaction - - return yield unless trans - - real_start = Time.now.to_f - cpu_start = System.cpu_time - - retval = yield - - cpu_stop = System.cpu_time - real_stop = Time.now.to_f - - real_time = (real_stop - real_start) - cpu_time = cpu_stop - cpu_start - - real_duration_seconds = fetch_histogram("gitlab_#{name}_real_duration_seconds".to_sym) do - docstring "Measure #{name}" - base_labels Transaction::BASE_LABELS - buckets EXECUTION_MEASUREMENT_BUCKETS - end - - real_duration_seconds.observe(trans.labels, real_time) - - cpu_duration_seconds = fetch_histogram("gitlab_#{name}_cpu_duration_seconds".to_sym) do - docstring "Measure #{name}" - base_labels Transaction::BASE_LABELS - buckets EXECUTION_MEASUREMENT_BUCKETS - with_feature "prometheus_metrics_measure_#{name}_cpu_duration" - end - cpu_duration_seconds.observe(trans.labels, cpu_time) - - # InfluxDB stores the _real_time and _cpu_time time values as milliseconds - trans.increment("#{name}_real_time", real_time.in_milliseconds, false) - trans.increment("#{name}_cpu_time", cpu_time.in_milliseconds, false) - trans.increment("#{name}_call_count", 1, false) - - retval - end - - # Sets the action of the current transaction (if any) - # - # action - The name of the action. - def action=(action) - trans = current_transaction - - trans&.action = action - end - - # Tracks an event. - # - # See `Gitlab::Metrics::Transaction#add_event` for more details. - def add_event(*args) - current_transaction&.add_event(*args) - end - - # Returns the prefix to use for the name of a series. - def series_prefix - @series_prefix ||= Gitlab::Runtime.sidekiq? ? 'sidekiq_' : 'rails_' - end - - # Allow access from other metrics related middlewares - def current_transaction - Transaction.current - end - - # When enabled this should be set before being used as the usual pattern - # "@foo ||= bar" is _not_ thread-safe. - def pool - if influx_metrics_enabled? - if @pool.nil? - MUTEX.synchronize do - @pool ||= ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do - host = settings[:host] - port = settings[:port] - - InfluxDB::Client - .new(udp: { host: host, port: port }) - end - end - end - - @pool - end - end - end - end - end -end diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb index d0c63a862c2..fbeda3b75e0 100644 --- a/lib/gitlab/metrics/method_call.rb +++ b/lib/gitlab/metrics/method_call.rb @@ -49,19 +49,6 @@ module Gitlab retval end - # Returns a Metric instance of the current method call. - def to_metric - Metric.new( - Instrumentation.series, - { - duration: real_time.in_milliseconds.to_i, - cpu_duration: cpu_time.in_milliseconds.to_i, - call_count: call_count - }, - method: @name - ) - end - # Returns true if the total runtime of this method exceeds the method call # threshold. def above_threshold? diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb deleted file mode 100644 index 30f181542be..00000000000 --- a/lib/gitlab/metrics/metric.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Metrics - # Class for storing details of a single metric (label, value, etc). - class Metric - JITTER_RANGE = (0.000001..0.001).freeze - - attr_reader :series, :values, :tags, :type - - # series - The name of the series (as a String) to store the metric in. - # values - A Hash containing the values to store. - # tags - A Hash containing extra tags to add to the metrics. - def initialize(series, values, tags = {}, type = :metric) - @values = values - @series = series - @tags = tags - @type = type - end - - def event? - type == :event - end - - # Returns a Hash in a format that can be directly written to InfluxDB. - def to_hash - # InfluxDB overwrites an existing point if a new point has the same - # series, tag set, and timestamp. In a highly concurrent environment - # this means that using the number of seconds since the Unix epoch is - # inevitably going to collide with another timestamp. For example, two - # Rails requests processed by different processes may end up generating - # metrics using the _exact_ same timestamp (in seconds). - # - # Due to the way InfluxDB is set up there's no solution to this problem, - # all we can do is lower the amount of collisions. We do this by using - # System.real_time which returns the nanoseconds as a Float providing - # greater accuracy. We then add a small random value that is large - # enough to distinguish most timestamps but small enough to not alter - # the timestamp significantly. - # - # See https://gitlab.com/gitlab-com/operations/issues/175 for more - # information. - time = System.real_time(:nanosecond) + rand(JITTER_RANGE) - - { - series: @series, - tags: @tags, - values: @values, - timestamp: time.to_i - } - end - end - end -end diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb index 9aa97515961..c6a0457ffe5 100644 --- a/lib/gitlab/metrics/rack_middleware.rb +++ b/lib/gitlab/metrics/rack_middleware.rb @@ -20,10 +20,6 @@ module Gitlab trans.add_event(:rails_exception) raise error - # Even in the event of an error we want to submit any metrics we - # might've gathered up to this point. - ensure - trans.finish end retval diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb new file mode 100644 index 00000000000..9ee4b0960c5 --- /dev/null +++ b/lib/gitlab/metrics/samplers/database_sampler.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Gitlab + module Metrics + module Samplers + class DatabaseSampler < BaseSampler + SAMPLING_INTERVAL_SECONDS = 5 + + METRIC_PREFIX = 'gitlab_database_connection_pool_' + + METRIC_DESCRIPTIONS = { + size: 'Total connection pool capacity', + connections: 'Current connections in the pool', + busy: 'Connections in use where the owner is still alive', + dead: 'Connections in use where the owner is not alive', + idle: 'Connections not in use', + waiting: 'Threads currently waiting on this queue' + }.freeze + + def metrics + @metrics ||= init_metrics + end + + def sample + host_stats.each do |host_stat| + METRIC_DESCRIPTIONS.each_key do |metric| + metrics[metric].set(host_stat[:labels], host_stat[:stats][metric]) + end + end + end + + private + + def init_metrics + METRIC_DESCRIPTIONS.map do |name, description| + [name, ::Gitlab::Metrics.gauge(:"#{METRIC_PREFIX}#{name}", description)] + end.to_h + end + + def host_stats + return [] unless ActiveRecord::Base.connected? + + [{ labels: labels_for_class(ActiveRecord::Base), stats: ActiveRecord::Base.connection_pool.stat }] + end + + def labels_for_class(klass) + { + host: klass.connection_config[:host], + port: klass.connection_config[:port], + class: klass.to_s + } + end + end + end + end +end + +Gitlab::Metrics::Samplers::DatabaseSampler.prepend_if_ee('EE::Gitlab::Metrics::Samplers::DatabaseSampler') diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb deleted file mode 100644 index 4e16e335bee..00000000000 --- a/lib/gitlab/metrics/samplers/influx_sampler.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Metrics - module Samplers - # Class that sends certain metrics to InfluxDB at a specific interval. - # - # This class is used to gather statistics that can't be directly associated - # with a transaction such as system memory usage, garbage collection - # statistics, etc. - class InfluxSampler < BaseSampler - # interval - The sampling interval in seconds. - def initialize(interval = ::Gitlab::Metrics.settings[:sample_interval]) - super(interval) - @last_step = nil - - @metrics = [] - end - - def sample - sample_memory_usage - sample_file_descriptors - - flush - ensure - @metrics.clear - end - - def flush - ::Gitlab::Metrics.submit_metrics(@metrics.map(&:to_hash)) - end - - def sample_memory_usage - add_metric('memory_usage', value: System.memory_usage) - end - - def sample_file_descriptors - add_metric('file_descriptors', value: System.file_descriptor_count) - end - - def add_metric(series, values, tags = {}) - prefix = Gitlab::Runtime.sidekiq? ? 'sidekiq_' : 'rails_' - - @metrics << Metric.new("#{prefix}#{series}", values, tags) - end - end - end - end -end diff --git a/lib/gitlab/metrics/samplers/puma_sampler.rb b/lib/gitlab/metrics/samplers/puma_sampler.rb index f788f51b1ce..98dd517ee3b 100644 --- a/lib/gitlab/metrics/samplers/puma_sampler.rb +++ b/lib/gitlab/metrics/samplers/puma_sampler.rb @@ -26,7 +26,7 @@ module Gitlab json_stats = puma_stats return unless json_stats - stats = JSON.parse(json_stats) + stats = Gitlab::Json.parse(json_stats) if cluster?(stats) sample_cluster(stats) diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb index c38769f39a9..df59c06911b 100644 --- a/lib/gitlab/metrics/samplers/ruby_sampler.rb +++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb @@ -34,14 +34,15 @@ module Gitlab def init_metrics metrics = { - file_descriptors: ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels), - memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:memory, :bytes), 'Memory used', labels), - process_cpu_seconds_total: ::Gitlab::Metrics.gauge(with_prefix(:process, :cpu_seconds_total), 'Process CPU seconds total'), - process_max_fds: ::Gitlab::Metrics.gauge(with_prefix(:process, :max_fds), 'Process max fds'), - process_resident_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :resident_memory_bytes), 'Memory used', labels), - process_start_time_seconds: ::Gitlab::Metrics.gauge(with_prefix(:process, :start_time_seconds), 'Process start time seconds'), - sampler_duration: ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels), - gc_duration_seconds: ::Gitlab::Metrics.histogram(with_prefix(:gc, :duration_seconds), 'GC time', labels, GC_REPORT_BUCKETS) + file_descriptors: ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels), + process_cpu_seconds_total: ::Gitlab::Metrics.gauge(with_prefix(:process, :cpu_seconds_total), 'Process CPU seconds total'), + process_max_fds: ::Gitlab::Metrics.gauge(with_prefix(:process, :max_fds), 'Process max fds'), + process_resident_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :resident_memory_bytes), 'Memory used (RSS)', labels), + process_unique_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :unique_memory_bytes), 'Memory used (USS)', labels), + process_proportional_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :proportional_memory_bytes), 'Memory used (PSS)', labels), + process_start_time_seconds: ::Gitlab::Metrics.gauge(with_prefix(:process, :start_time_seconds), 'Process start time seconds'), + sampler_duration: ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels), + gc_duration_seconds: ::Gitlab::Metrics.histogram(with_prefix(:gc, :duration_seconds), 'GC time', labels, GC_REPORT_BUCKETS) } GC.stat.keys.each do |key| @@ -85,10 +86,13 @@ module Gitlab end def set_memory_usage_metrics - memory_usage = System.memory_usage + metrics[:process_resident_memory_bytes].set(labels, System.memory_usage_rss) - metrics[:memory_bytes].set(labels, memory_usage) - metrics[:process_resident_memory_bytes].set(labels, memory_usage) + if Gitlab::Utils.to_boolean(ENV['enable_memory_uss_pss'] || '1') + memory_uss_pss = System.memory_usage_uss_pss + metrics[:process_unique_memory_bytes].set(labels, memory_uss_pss[:uss]) + metrics[:process_proportional_memory_bytes].set(labels, memory_uss_pss[:pss]) + end end end end diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb index 0b4485feea9..8dfb61046c4 100644 --- a/lib/gitlab/metrics/sidekiq_middleware.rb +++ b/lib/gitlab/metrics/sidekiq_middleware.rb @@ -17,8 +17,6 @@ module Gitlab trans.add_event(:sidekiq_exception) raise error - ensure - trans.finish end end end diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb index 5bd21b8e5d1..24107e42aa9 100644 --- a/lib/gitlab/metrics/subscribers/action_view.rb +++ b/lib/gitlab/metrics/subscribers/action_view.rb @@ -26,23 +26,17 @@ module Gitlab private def track(event) - values = values_for(event) - tags = tags_for(event) + tags = tags_for(event) self.class.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) end def relative_path(path) path.gsub(%r{^#{Rails.root}/?}, '') end - def values_for(event) - { duration: event.duration } - end - def tags_for(event) path = relative_path(event.payload[:identifier]) diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb index 2a61b3de405..43005303dec 100644 --- a/lib/gitlab/metrics/system.rb +++ b/lib/gitlab/metrics/system.rb @@ -7,47 +7,37 @@ module Gitlab # This module relies on the /proc filesystem being available. If /proc is # not available the methods of this module will be stubbed. module System - if File.exist?('/proc') - # Returns the current process' memory usage in bytes. - def self.memory_usage - mem = 0 - match = File.read('/proc/self/status').match(/VmRSS:\s+(\d+)/) - - if match && match[1] - mem = match[1].to_f * 1024 - end - - mem - end - - def self.file_descriptor_count - Dir.glob('/proc/self/fd/*').length - end - - def self.max_open_file_descriptors - match = File.read('/proc/self/limits').match(/Max open files\s*(\d+)/) - - return unless match && match[1] + PROC_STATUS_PATH = '/proc/self/status' + PROC_SMAPS_ROLLUP_PATH = '/proc/self/smaps_rollup' + PROC_LIMITS_PATH = '/proc/self/limits' + PROC_FD_GLOB = '/proc/self/fd/*' + + PRIVATE_PAGES_PATTERN = /^(Private_Clean|Private_Dirty|Private_Hugetlb):\s+(?<value>\d+)/.freeze + PSS_PATTERN = /^Pss:\s+(?<value>\d+)/.freeze + RSS_PATTERN = /VmRSS:\s+(?<value>\d+)/.freeze + MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/.freeze + + # Returns the current process' RSS (resident set size) in bytes. + def self.memory_usage_rss + sum_matches(PROC_STATUS_PATH, rss: RSS_PATTERN)[:rss].kilobytes + end - match[1].to_i - end - else - def self.memory_usage - 0.0 - end + # Returns the current process' USS/PSS (unique/proportional set size) in bytes. + def self.memory_usage_uss_pss + sum_matches(PROC_SMAPS_ROLLUP_PATH, uss: PRIVATE_PAGES_PATTERN, pss: PSS_PATTERN) + .transform_values(&:kilobytes) + end - def self.file_descriptor_count - 0 - end + def self.file_descriptor_count + Dir.glob(PROC_FD_GLOB).length + end - def self.max_open_file_descriptors - 0 - end + def self.max_open_file_descriptors + sum_matches(PROC_LIMITS_PATH, max_fds: MAX_OPEN_FILES_PATTERN)[:max_fds] end def self.cpu_time - Process - .clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :float_second) + Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :float_second) end # Returns the current real time in a given precision. @@ -78,6 +68,27 @@ module Gitlab end_time - start_time end + + # Given a path to a file in /proc and a hash of (metric, pattern) pairs, + # sums up all values found for those patterns under the respective metric. + def self.sum_matches(proc_file, **patterns) + results = patterns.transform_values { 0 } + + begin + File.foreach(proc_file) do |line| + patterns.each do |metric, pattern| + match = line.match(pattern) + value = match&.named_captures&.fetch('value', 0) + results[metric] += value.to_i + end + end + rescue Errno::ENOENT + # This means the procfile we're reading from did not exist; + # this is safe to ignore, since we initialize each metric to 0 + end + + results + end end end end diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb index 552eae639e6..b126efd2dd5 100644 --- a/lib/gitlab/metrics/transaction.rb +++ b/lib/gitlab/metrics/transaction.rb @@ -16,20 +16,18 @@ module Gitlab # The series to store events (e.g. Git pushes) in. EVENT_SERIES = 'events' - attr_reader :tags, :values, :method, :metrics + attr_reader :tags, :method def self.current Thread.current[THREAD_KEY] end def initialize - @metrics = [] @methods = {} @started_at = nil @finished_at = nil - @values = Hash.new(0) @tags = {} @memory_before = 0 @@ -40,10 +38,6 @@ module Gitlab @finished_at ? (@finished_at - @started_at) : 0.0 end - def duration_milliseconds - duration.in_milliseconds.to_i - end - def thread_cpu_duration System.thread_cpu_duration(@thread_cputime_start) end @@ -55,13 +49,13 @@ module Gitlab def run Thread.current[THREAD_KEY] = self - @memory_before = System.memory_usage + @memory_before = System.memory_usage_rss @started_at = System.monotonic_time @thread_cputime_start = System.thread_cpu_time yield ensure - @memory_after = System.memory_usage + @memory_after = System.memory_usage_rss @finished_at = System.monotonic_time self.class.gitlab_transaction_cputime_seconds.observe(labels, thread_cpu_duration) @@ -71,10 +65,6 @@ module Gitlab Thread.current[THREAD_KEY] = nil end - def add_metric(series, values, tags = {}) - @metrics << Metric.new("#{::Gitlab::Metrics.series_prefix}#{series}", values, filter_tags(tags)) - end - # Tracks a business level event # # Business level events including events such as Git pushes, Emails being @@ -85,7 +75,6 @@ module Gitlab def add_event(event_name, tags = {}) filtered_tags = filter_tags(tags) self.class.transaction_metric(event_name, :counter, prefix: 'event_', tags: filtered_tags).increment(filtered_tags.merge(labels)) - @metrics << Metric.new(EVENT_SERIES, { count: 1 }, filtered_tags.merge(event: event_name), :event) end # Returns a MethodCall object for the given name. @@ -99,55 +88,16 @@ module Gitlab def increment(name, value, use_prometheus = true) self.class.transaction_metric(name, :counter).increment(labels, value) if use_prometheus - @values[name] += value end def set(name, value, use_prometheus = true) self.class.transaction_metric(name, :gauge).set(labels, value) if use_prometheus - @values[name] = value - end - - def finish - track_self - submit - end - - def track_self - values = { duration: duration_milliseconds, allocated_memory: allocated_memory } - - @values.each do |name, value| - values[name] = value - end - - add_metric('transactions', values, @tags) - end - - def submit - submit = @metrics.dup - - @methods.each do |name, method| - submit << method.to_metric if method.above_threshold? - end - - submit_hashes = submit.map do |metric| - hash = metric.to_hash - hash[:tags][:action] ||= action if action && !metric.event? - - hash - end - - ::Gitlab::Metrics.submit_metrics(submit_hashes) end def labels BASE_LABELS end - # returns string describing the action performed, usually the class plus method name. - def action - "#{labels[:controller]}##{labels[:action]}" if labels && !labels.empty? - end - define_histogram :gitlab_transaction_cputime_seconds do docstring 'Transaction thread cputime' base_labels BASE_LABELS |