Class: LogStash::Instrument::PeriodicPoller::Cgroup

Inherits:
Object
  • Object
show all
Includes:
Util::Loggable
Defined in:
lib/logstash/instrument/periodic_poller/cgroup.rb

Defined Under Namespace

Classes: CpuStats

Constant Summary collapse

CONTROL_GROUP_RE =
Regexp.compile("\\d+:([^:,]+(?:,[^:,]+)?):(/.*)")
CONTROLLER_SEPERATOR_RE =
","
PROC_SELF_CGROUP_FILE =
Pathname.new("/proc/self/cgroup")
PROC_CGROUP_CPU_DIR =
Pathname.new("/sys/fs/cgroup/cpu")
PROC_CGROUP_CPUACCT_DIR =
Pathname.new("/sys/fs/cgroup/cpuacct")
GROUP_CPUACCT =
"cpuacct"
CPUACCT_USAGE_FILE =
"cpuacct.usage"
GROUP_CPU =
"cpu"
CPU_FS_PERIOD_US_FILE =
"cpu.cfs_period_us"
CPU_FS_QUOTA_US_FILE =
"cpu.cfs_quota_us"
CPU_STATS_FILE =
"cpu.stat"

Class Method Summary collapse

Methods included from Util::Loggable

included, #logger, #slow_logger

Class Method Details

.are_cgroup_available?Boolean

Returns:

  • (Boolean)


28
29
30
31
32
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 28

def are_cgroup_available?
  [::File.exist?(PROC_SELF_CGROUP_FILE),
   Dir.exist?(PROC_CGROUP_CPU_DIR),
   Dir.exist?(PROC_CGROUP_CPUACCT_DIR)].all?
end

.cgroup_cpu_fs_period_micros(control_group) ⇒ Object



55
56
57
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 55

def cgroup_cpu_fs_period_micros(control_group)
  read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group, CPU_FS_PERIOD_US_FILE)).to_i
end

.cgroup_cpu_fs_quota_micros(control_group) ⇒ Object



59
60
61
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 59

def cgroup_cpu_fs_quota_micros(control_group)
  read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group,  CPU_FS_QUOTA_US_FILE)).to_i
end

.cgroup_cpuacct_cpu_stat(control_group) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 81

def cgroup_cpuacct_cpu_stat(control_group)
  lines = read_sys_fs_cgroup_cpuacct_cpu_stat(control_group);

  number_of_elapsed_periods = -1;
  number_of_times_throttled = -1;
  time_throttled_nanos = -1;

  lines.each do |line|
    fields = line.split(/\s+/)
    case fields.first
    when "nr_periods" then number_of_elapsed_periods = fields[1].to_i
    when "nr_throttled" then number_of_times_throttled= fields[1].to_i
    when "throttled_time" then time_throttled_nanos = fields[1].to_i
    end
  end

  CpuStats.new(number_of_elapsed_periods, number_of_times_throttled, time_throttled_nanos)
end

.cgroup_cpuacct_usage_nanos(control_group) ⇒ Object



51
52
53
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 51

def cgroup_cpuacct_usage_nanos(control_group)
  read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group, CPUACCT_USAGE_FILE)).to_i
end

.control_groupsObject



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 34

def control_groups
  response = {}

  read_proc_self_cgroup_lines.each do |line|
    matches = CONTROL_GROUP_RE.match(line)
    # multiples controlles, same hierachy
    controllers = matches[1].split(CONTROLLER_SEPERATOR_RE)
    controllers.each_with_object(response) { |controller| response[controller] = matches[2] }
  end

  response
end

.getObject



132
133
134
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 132

def get
  are_cgroup_available? ? get_all : nil
end

.get_allObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 100

def get_all
 groups = control_groups
 return if groups.empty?

 cgroups_stats = {
   :cpuacct => {},
   :cpu => {}
 }

 cpuacct_group = groups[GROUP_CPUACCT]
 cgroups_stats[:cpuacct][:control_group] = cpuacct_group
 cgroups_stats[:cpuacct][:usage_nanos] = cgroup_cpuacct_usage_nanos(cpuacct_group)

 cpu_group = groups[GROUP_CPU]
 cgroups_stats[:cpu][:control_group] = cpu_group
 cgroups_stats[:cpu][:cfs_period_micros] = cgroup_cpu_fs_period_micros(cpu_group)
 cgroups_stats[:cpu][:cfs_quota_micros] = cgroup_cpu_fs_quota_micros(cpu_group)

 cpu_stats = cgroup_cpuacct_cpu_stat(cpu_group)

 cgroups_stats[:cpu][:stat] = {
   :number_of_elapsed_periods => cpu_stats.number_of_elapsed_periods,
   :number_of_times_throttled => cpu_stats.number_of_times_throttled,
   :time_throttled_nanos => cpu_stats.time_throttled_nanos
 }

 cgroups_stats
rescue => e
  logger.debug("Error, cannot retrieve cgroups information", :exception => e.class.name, :message => e.message) if logger.debug?
  nil
end

.read_first_line(path) ⇒ Object



47
48
49
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 47

def read_first_line(path)
  IO.readlines(path).first
end

.read_proc_self_cgroup_linesObject



63
64
65
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 63

def read_proc_self_cgroup_lines
  IO.readlines(PROC_SELF_CGROUP_FILE)
end

.read_sys_fs_cgroup_cpuacct_cpu_stat(control_group) ⇒ Object



77
78
79
# File 'lib/logstash/instrument/periodic_poller/cgroup.rb', line 77

def read_sys_fs_cgroup_cpuacct_cpu_stat(control_group)
  IO.readlines(::File.join(PROC_CGROUP_CPU_DIR, control_group, CPU_STATS_FILE))
end