Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/metrics/system.rb')
-rw-r--r--lib/gitlab/metrics/system.rb167
1 files changed, 3 insertions, 164 deletions
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index 80ce155321b..92a8a2b95c4 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -1,172 +1,11 @@
# frozen_string_literal: true
+require 'gitlab/utils/system'
+
module Gitlab
module Metrics
- # Module for gathering system/process statistics such as the memory usage.
- #
- # This module relies on the /proc filesystem being available. If /proc is
- # not available the methods of this module will be stubbed.
module System
- extend self
-
- PROC_STAT_PATH = '/proc/self/stat'
- PROC_STATUS_PATH = '/proc/%s/status'
- PROC_SMAPS_ROLLUP_PATH = '/proc/%s/smaps_rollup'
- PROC_LIMITS_PATH = '/proc/self/limits'
- PROC_FD_GLOB = '/proc/self/fd/*'
- PROC_MEM_INFO = '/proc/meminfo'
-
- PRIVATE_PAGES_PATTERN = /^(Private_Clean|Private_Dirty|Private_Hugetlb):\s+(?<value>\d+)/
- PSS_PATTERN = /^Pss:\s+(?<value>\d+)/
- RSS_TOTAL_PATTERN = /^VmRSS:\s+(?<value>\d+)/
- RSS_ANON_PATTERN = /^RssAnon:\s+(?<value>\d+)/
- RSS_FILE_PATTERN = /^RssFile:\s+(?<value>\d+)/
- MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/
- MEM_TOTAL_PATTERN = /^MemTotal:\s+(?<value>\d+) (.+)/
-
- def summary
- proportional_mem = memory_usage_uss_pss
- {
- version: RUBY_DESCRIPTION,
- gc_stat: GC.stat,
- memory_rss: memory_usage_rss[:total],
- memory_uss: proportional_mem[:uss],
- memory_pss: proportional_mem[:pss],
- time_cputime: cpu_time,
- time_realtime: real_time,
- time_monotonic: monotonic_time
- }
- end
-
- # Returns the given process' RSS (resident set size) in bytes.
- def memory_usage_rss(pid: 'self')
- results = { total: 0, anon: 0, file: 0 }
-
- safe_yield_procfile(PROC_STATUS_PATH % pid) do |io|
- io.each_line do |line|
- if (value = parse_metric_value(line, RSS_TOTAL_PATTERN)) > 0
- results[:total] = value.kilobytes
- elsif (value = parse_metric_value(line, RSS_ANON_PATTERN)) > 0
- results[:anon] = value.kilobytes
- elsif (value = parse_metric_value(line, RSS_FILE_PATTERN)) > 0
- results[:file] = value.kilobytes
- end
- end
- end
-
- results
- end
-
- # Returns the given process' USS/PSS (unique/proportional set size) in bytes.
- def memory_usage_uss_pss(pid: 'self')
- sum_matches(PROC_SMAPS_ROLLUP_PATH % pid, uss: PRIVATE_PAGES_PATTERN, pss: PSS_PATTERN)
- .transform_values(&:kilobytes)
- end
-
- def memory_total
- sum_matches(PROC_MEM_INFO, memory_total: MEM_TOTAL_PATTERN)[:memory_total].kilobytes
- end
-
- def file_descriptor_count
- Dir.glob(PROC_FD_GLOB).length
- end
-
- def max_open_file_descriptors
- sum_matches(PROC_LIMITS_PATH, max_fds: MAX_OPEN_FILES_PATTERN)[:max_fds]
- end
-
- def cpu_time
- Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :float_second)
- end
-
- # Returns the current real time in a given precision.
- #
- # Returns the time as a Float for precision = :float_second.
- def real_time(precision = :float_second)
- Process.clock_gettime(Process::CLOCK_REALTIME, precision)
- end
-
- # Returns the current monotonic clock time as seconds with microseconds precision.
- #
- # Returns the time as a Float.
- def monotonic_time
- Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
- end
-
- def thread_cpu_time
- # Not all OS kernels are supporting `Process::CLOCK_THREAD_CPUTIME_ID`
- # Refer: https://gitlab.com/gitlab-org/gitlab/issues/30567#note_221765627
- return unless defined?(Process::CLOCK_THREAD_CPUTIME_ID)
-
- Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
- end
-
- def thread_cpu_duration(start_time)
- end_time = thread_cpu_time
- return unless start_time && end_time
-
- end_time - start_time
- end
-
- # Returns the total time the current process has been running in seconds.
- def process_runtime_elapsed_seconds
- # Entry 22 (1-indexed) contains the process `starttime`, see:
- # https://man7.org/linux/man-pages/man5/proc.5.html
- #
- # This value is a fixed timestamp in clock ticks.
- # To obtain an elapsed time in seconds, we divide by the number
- # of ticks per second and subtract from the system uptime.
- start_time_ticks = proc_stat_entries[21].to_f
- clock_ticks_per_second = Etc.sysconf(Etc::SC_CLK_TCK)
- uptime - (start_time_ticks / clock_ticks_per_second)
- end
-
- private
-
- # 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 sum_matches(proc_file, **patterns)
- results = patterns.transform_values { 0 }
-
- safe_yield_procfile(proc_file) do |io|
- io.each_line do |line|
- patterns.each do |metric, pattern|
- results[metric] += parse_metric_value(line, pattern)
- end
- end
- end
-
- results
- end
-
- def parse_metric_value(line, pattern)
- match = line.match(pattern)
- return 0 unless match
-
- match.named_captures.fetch('value', 0).to_i
- end
-
- def proc_stat_entries
- safe_yield_procfile(PROC_STAT_PATH) do |io|
- io.read.split(' ')
- end || []
- end
-
- def safe_yield_procfile(path, &block)
- File.open(path, &block)
- rescue Errno::ENOENT
- # This means the procfile we're reading from did not exist;
- # most likely we're on Darwin.
- end
-
- # Equivalent to reading /proc/uptime on Linux 2.6+.
- #
- # Returns 0 if not supported, e.g. on Darwin.
- def uptime
- Process.clock_gettime(Process::CLOCK_BOOTTIME)
- rescue NameError
- 0
- end
+ extend Gitlab::Utils::System
end
end
end