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.rb69
1 files changed, 53 insertions, 16 deletions
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index 9bbcd1e056c..e646846face 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -7,6 +7,9 @@ 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
+ extend self
+
+ PROC_STAT_PATH = '/proc/self/stat'
PROC_STATUS_PATH = '/proc/self/status'
PROC_SMAPS_ROLLUP_PATH = '/proc/self/smaps_rollup'
PROC_LIMITS_PATH = '/proc/self/limits'
@@ -17,7 +20,7 @@ module Gitlab
RSS_PATTERN = /VmRSS:\s+(?<value>\d+)/.freeze
MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/.freeze
- def self.summary
+ def summary
proportional_mem = memory_usage_uss_pss
{
version: RUBY_DESCRIPTION,
@@ -32,43 +35,43 @@ module Gitlab
end
# Returns the current process' RSS (resident set size) in bytes.
- def self.memory_usage_rss
+ def memory_usage_rss
sum_matches(PROC_STATUS_PATH, rss: RSS_PATTERN)[:rss].kilobytes
end
# Returns the current process' USS/PSS (unique/proportional set size) in bytes.
- def self.memory_usage_uss_pss
+ def 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
+ def file_descriptor_count
Dir.glob(PROC_FD_GLOB).length
end
- def self.max_open_file_descriptors
+ def max_open_file_descriptors
sum_matches(PROC_LIMITS_PATH, max_fds: MAX_OPEN_FILES_PATTERN)[:max_fds]
end
- def self.cpu_time
+ 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 self.real_time(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 self.monotonic_time
+ def monotonic_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
end
- def self.thread_cpu_time
+ 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)
@@ -76,33 +79,67 @@ module Gitlab
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
end
- def self.thread_cpu_duration(start_time)
+ 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 self.sum_matches(proc_file, **patterns)
+ def sum_matches(proc_file, **patterns)
results = patterns.transform_values { 0 }
- begin
- File.foreach(proc_file) do |line|
+ safe_yield_procfile(proc_file) do |io|
+ io.each_line 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
+
+ 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
end
end
end