summaryrefslogtreecommitdiff
path: root/lib/gitlab/metrics
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/metrics')
-rw-r--r--lib/gitlab/metrics/dashboard/url.rb2
-rw-r--r--lib/gitlab/metrics/exporter/sidekiq_exporter.rb2
-rw-r--r--lib/gitlab/metrics/influx_db.rb183
-rw-r--r--lib/gitlab/metrics/method_call.rb13
-rw-r--r--lib/gitlab/metrics/metric.rb54
-rw-r--r--lib/gitlab/metrics/rack_middleware.rb4
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb58
-rw-r--r--lib/gitlab/metrics/samplers/influx_sampler.rb49
-rw-r--r--lib/gitlab/metrics/samplers/puma_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb26
-rw-r--r--lib/gitlab/metrics/sidekiq_middleware.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/action_view.rb8
-rw-r--r--lib/gitlab/metrics/system.rb81
-rw-r--r--lib/gitlab/metrics/transaction.rb56
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