Skip to content

Commit 7c07d8a

Browse files
feat: add ability to get individual controller stats
This adds methods to retrieve statistics for individual cgroup controllers (CPU, memory, pids, IO, hugetlb, rdma, misc) instead of requiring all stats to be fetched at once. This enables tools like cadvisor to collect specific metrics with different housekeeping intervals, reducing computational overhead. Fixes: #44 Signed-off-by: Sambhav Jain <jnsmbhv@gmail.com>
1 parent e0c56cb commit 7c07d8a

File tree

5 files changed

+337
-0
lines changed

5 files changed

+337
-0
lines changed

cgroups.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ type Manager interface {
4444
// GetStats returns cgroups statistics.
4545
GetStats() (*Stats, error)
4646

47+
// GetCpuStats returns cgroups cpu statistics
48+
GetCpuStats() (*Stats, error)
49+
50+
// GetMemoryStats returns cgroups memory statistics
51+
GetMemoryStats() (*Stats, error)
52+
53+
// GetPidsStats returns cgroups pids statistics
54+
GetPidsStats() (*Stats, error)
55+
56+
// GetIoStats returns cgroups io statistics
57+
GetIoStats() (*Stats, error)
58+
59+
// GetHugetlbStats returns cgroups hugetlb statistics
60+
GetHugetlbStats() (*Stats, error)
61+
62+
// GetRdmaStats returns cgroups rdma statistics
63+
GetRdmaStats() (*Stats, error)
64+
65+
// GetMiscStats returns cgroups misc statistics
66+
GetMiscStats() (*Stats, error)
67+
4768
// Freeze sets the freezer cgroup to the specified state.
4869
Freeze(state FreezerState) error
4970

fs/fs.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,111 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
196196
return stats, nil
197197
}
198198

199+
func (m *Manager) GetCpuStats() (*cgroups.Stats, error) {
200+
m.mu.Lock()
201+
defer m.mu.Unlock()
202+
stats := cgroups.NewStats()
203+
204+
cpuGroup := &CpuGroup{}
205+
if path := m.paths["cpu"]; path != "" {
206+
if err := cpuGroup.GetStats(path, stats); err != nil {
207+
return nil, err
208+
}
209+
}
210+
211+
cpuacctGroup := &CpuacctGroup{}
212+
if path := m.paths["cpuacct"]; path != "" {
213+
if err := cpuacctGroup.GetStats(path, stats); err != nil {
214+
return nil, err
215+
}
216+
}
217+
218+
return stats, nil
219+
}
220+
221+
func (m *Manager) GetMemoryStats() (*cgroups.Stats, error) {
222+
m.mu.Lock()
223+
defer m.mu.Unlock()
224+
stats := cgroups.NewStats()
225+
226+
memoryGroup := &MemoryGroup{}
227+
if path := m.paths["memory"]; path != "" {
228+
if err := memoryGroup.GetStats(path, stats); err != nil {
229+
return nil, err
230+
}
231+
}
232+
233+
return stats, nil
234+
}
235+
236+
func (m *Manager) GetPidsStats() (*cgroups.Stats, error) {
237+
m.mu.Lock()
238+
defer m.mu.Unlock()
239+
stats := cgroups.NewStats()
240+
241+
pidsGroup := &PidsGroup{}
242+
if path := m.paths["pids"]; path != "" {
243+
if err := pidsGroup.GetStats(path, stats); err != nil {
244+
return nil, err
245+
}
246+
}
247+
248+
return stats, nil
249+
}
250+
251+
func (m *Manager) GetIoStats() (*cgroups.Stats, error) {
252+
m.mu.Lock()
253+
defer m.mu.Unlock()
254+
stats := cgroups.NewStats()
255+
256+
blkioGroup := &BlkioGroup{}
257+
if path := m.paths["blkio"]; path != "" {
258+
if err := blkioGroup.GetStats(path, stats); err != nil {
259+
return nil, err
260+
}
261+
}
262+
263+
return stats, nil
264+
}
265+
266+
func (m *Manager) GetHugetlbStats() (*cgroups.Stats, error) {
267+
m.mu.Lock()
268+
defer m.mu.Unlock()
269+
stats := cgroups.NewStats()
270+
271+
hugetlbGroup := &HugetlbGroup{}
272+
if path := m.paths["hugetlb"]; path != "" {
273+
if err := hugetlbGroup.GetStats(path, stats); err != nil {
274+
return nil, err
275+
}
276+
}
277+
278+
return stats, nil
279+
}
280+
281+
func (m *Manager) GetRdmaStats() (*cgroups.Stats, error) {
282+
m.mu.Lock()
283+
defer m.mu.Unlock()
284+
stats := cgroups.NewStats()
285+
286+
rdmaGroup := &RdmaGroup{}
287+
if path := m.paths["rdma"]; path != "" {
288+
if err := rdmaGroup.GetStats(path, stats); err != nil {
289+
return nil, err
290+
}
291+
}
292+
293+
return stats, nil
294+
}
295+
296+
func (m *Manager) GetMiscStats() (*cgroups.Stats, error) {
297+
m.mu.Lock()
298+
defer m.mu.Unlock()
299+
stats := cgroups.NewStats()
300+
301+
return stats, nil
302+
}
303+
199304
func (m *Manager) Set(r *cgroups.Resources) error {
200305
if r == nil {
201306
return nil

fs2/fs2.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,84 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
155155
return st, nil
156156
}
157157

158+
func (m *Manager) GetCpuStats() (*cgroups.Stats, error) {
159+
st := cgroups.NewStats()
160+
161+
if err := statCpu(m.dirPath, st); err != nil && !os.IsNotExist(err) {
162+
return st, err
163+
}
164+
165+
var err error
166+
if st.CpuStats.PSI, err = statPSI(m.dirPath, "cpu.pressure"); err != nil {
167+
return st, err
168+
}
169+
170+
return st, nil
171+
}
172+
173+
func (m *Manager) GetMemoryStats() (*cgroups.Stats, error) {
174+
st := cgroups.NewStats()
175+
176+
if err := statMemory(m.dirPath, st); err != nil && !os.IsNotExist(err) {
177+
return st, err
178+
}
179+
180+
var err error
181+
if st.MemoryStats.PSI, err = statPSI(m.dirPath, "memory.pressure"); err != nil {
182+
return st, err
183+
}
184+
185+
return st, nil
186+
}
187+
188+
func (m *Manager) GetPidsStats() (*cgroups.Stats, error) {
189+
st := cgroups.NewStats()
190+
err := statPids(m.dirPath, st)
191+
return st, err
192+
}
193+
194+
func (m *Manager) GetIoStats() (*cgroups.Stats, error) {
195+
st := cgroups.NewStats()
196+
197+
if err := statIo(m.dirPath, st); err != nil && !os.IsNotExist(err) {
198+
return st, err
199+
}
200+
201+
var err error
202+
if st.BlkioStats.PSI, err = statPSI(m.dirPath, "io.pressure"); err != nil {
203+
return st, err
204+
}
205+
206+
return st, nil
207+
}
208+
209+
func (m *Manager) GetHugetlbStats() (*cgroups.Stats, error) {
210+
st := cgroups.NewStats()
211+
err := statHugeTlb(m.dirPath, st)
212+
if err != nil && !os.IsNotExist(err) {
213+
return st, err
214+
}
215+
return st, nil
216+
}
217+
218+
func (m *Manager) GetRdmaStats() (*cgroups.Stats, error) {
219+
st := cgroups.NewStats()
220+
err := fscommon.RdmaGetStats(m.dirPath, st)
221+
if err != nil && !os.IsNotExist(err) {
222+
return st, err
223+
}
224+
return st, nil
225+
}
226+
227+
func (m *Manager) GetMiscStats() (*cgroups.Stats, error) {
228+
st := cgroups.NewStats()
229+
err := statMisc(m.dirPath, st)
230+
if err != nil && !os.IsNotExist(err) {
231+
return st, err
232+
}
233+
return st, nil
234+
}
235+
158236
func (m *Manager) Freeze(state cgroups.FreezerState) error {
159237
if m.config.Resources == nil {
160238
return errors.New("cannot toggle freezer: cgroups not configured for container")

systemd/v1.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,111 @@ func (m *LegacyManager) GetStats() (*cgroups.Stats, error) {
355355
return stats, nil
356356
}
357357

358+
func (m *LegacyManager) GetCpuStats() (*cgroups.Stats, error) {
359+
m.mu.Lock()
360+
defer m.mu.Unlock()
361+
stats := cgroups.NewStats()
362+
363+
cpuGroup := &fs.CpuGroup{}
364+
if path := m.paths["cpu"]; path != "" {
365+
if err := cpuGroup.GetStats(path, stats); err != nil {
366+
return nil, err
367+
}
368+
}
369+
370+
cpuacctGroup := &fs.CpuacctGroup{}
371+
if path := m.paths["cpuacct"]; path != "" {
372+
if err := cpuacctGroup.GetStats(path, stats); err != nil {
373+
return nil, err
374+
}
375+
}
376+
377+
return stats, nil
378+
}
379+
380+
func (m *LegacyManager) GetMemoryStats() (*cgroups.Stats, error) {
381+
m.mu.Lock()
382+
defer m.mu.Unlock()
383+
stats := cgroups.NewStats()
384+
385+
memoryGroup := &fs.MemoryGroup{}
386+
if path := m.paths["memory"]; path != "" {
387+
if err := memoryGroup.GetStats(path, stats); err != nil {
388+
return nil, err
389+
}
390+
}
391+
392+
return stats, nil
393+
}
394+
395+
func (m *LegacyManager) GetPidsStats() (*cgroups.Stats, error) {
396+
m.mu.Lock()
397+
defer m.mu.Unlock()
398+
stats := cgroups.NewStats()
399+
400+
pidsGroup := &fs.PidsGroup{}
401+
if path := m.paths["pids"]; path != "" {
402+
if err := pidsGroup.GetStats(path, stats); err != nil {
403+
return nil, err
404+
}
405+
}
406+
407+
return stats, nil
408+
}
409+
410+
func (m *LegacyManager) GetIoStats() (*cgroups.Stats, error) {
411+
m.mu.Lock()
412+
defer m.mu.Unlock()
413+
stats := cgroups.NewStats()
414+
415+
blkioGroup := &fs.BlkioGroup{}
416+
if path := m.paths["blkio"]; path != "" {
417+
if err := blkioGroup.GetStats(path, stats); err != nil {
418+
return nil, err
419+
}
420+
}
421+
422+
return stats, nil
423+
}
424+
425+
func (m *LegacyManager) GetHugetlbStats() (*cgroups.Stats, error) {
426+
m.mu.Lock()
427+
defer m.mu.Unlock()
428+
stats := cgroups.NewStats()
429+
430+
hugetlbGroup := &fs.HugetlbGroup{}
431+
if path := m.paths["hugetlb"]; path != "" {
432+
if err := hugetlbGroup.GetStats(path, stats); err != nil {
433+
return nil, err
434+
}
435+
}
436+
437+
return stats, nil
438+
}
439+
440+
func (m *LegacyManager) GetRdmaStats() (*cgroups.Stats, error) {
441+
m.mu.Lock()
442+
defer m.mu.Unlock()
443+
stats := cgroups.NewStats()
444+
445+
rdmaGroup := &fs.RdmaGroup{}
446+
if path := m.paths["rdma"]; path != "" {
447+
if err := rdmaGroup.GetStats(path, stats); err != nil {
448+
return nil, err
449+
}
450+
}
451+
452+
return stats, nil
453+
}
454+
455+
func (m *LegacyManager) GetMiscStats() (*cgroups.Stats, error) {
456+
m.mu.Lock()
457+
defer m.mu.Unlock()
458+
stats := cgroups.NewStats()
459+
460+
return stats, nil
461+
}
462+
358463
func (m *LegacyManager) Set(r *cgroups.Resources) error {
359464
if r == nil {
360465
return nil

systemd/v2.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,34 @@ func (m *UnifiedManager) GetStats() (*cgroups.Stats, error) {
497497
return m.fsMgr.GetStats()
498498
}
499499

500+
func (m *UnifiedManager) GetCpuStats() (*cgroups.Stats, error) {
501+
return m.fsMgr.GetCpuStats()
502+
}
503+
504+
func (m *UnifiedManager) GetMemoryStats() (*cgroups.Stats, error) {
505+
return m.fsMgr.GetMemoryStats()
506+
}
507+
508+
func (m *UnifiedManager) GetPidsStats() (*cgroups.Stats, error) {
509+
return m.fsMgr.GetPidsStats()
510+
}
511+
512+
func (m *UnifiedManager) GetIoStats() (*cgroups.Stats, error) {
513+
return m.fsMgr.GetIoStats()
514+
}
515+
516+
func (m *UnifiedManager) GetHugetlbStats() (*cgroups.Stats, error) {
517+
return m.fsMgr.GetHugetlbStats()
518+
}
519+
520+
func (m *UnifiedManager) GetRdmaStats() (*cgroups.Stats, error) {
521+
return m.fsMgr.GetRdmaStats()
522+
}
523+
524+
func (m *UnifiedManager) GetMiscStats() (*cgroups.Stats, error) {
525+
return m.fsMgr.GetMiscStats()
526+
}
527+
500528
func (m *UnifiedManager) Set(r *cgroups.Resources) error {
501529
if r == nil {
502530
return nil

0 commit comments

Comments
 (0)