diff options
Diffstat (limited to 'lib/gitlab/metrics/system.rb')
-rw-r--r-- | lib/gitlab/metrics/system.rb | 81 |
1 files changed, 46 insertions, 35 deletions
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 |