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

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Chandler <wchandler@gitlab.com>2023-11-09 23:03:07 +0300
committerWill Chandler <wchandler@gitlab.com>2023-11-11 00:30:52 +0300
commitda3e644d31df21ca28654499a4927f280c93ce86 (patch)
treeab35867d3141bacc4c068e98d1e24c25515c219c
parent8539b2d10ff41ac9256b8f8c8610d59d6d9fb155 (diff)
cgroups: Add stats method
Add the `stats()` method to `genericHandler`. We use reflection here as the stats collected vary significantly between v1 and v2.
-rw-r--r--internal/cgroups/handler_linux.go58
1 files changed, 58 insertions, 0 deletions
diff --git a/internal/cgroups/handler_linux.go b/internal/cgroups/handler_linux.go
index 6af06d332..5f1784377 100644
--- a/internal/cgroups/handler_linux.go
+++ b/internal/cgroups/handler_linux.go
@@ -3,9 +3,11 @@
package cgroups
import (
+ "errors"
"fmt"
"path/filepath"
"strings"
+ "time"
"github.com/containerd/cgroups/v3/cgroup1"
"github.com/containerd/cgroups/v3/cgroup2"
@@ -166,3 +168,59 @@ func (cvh *genericHandler[T, H]) repoPath(groupID int) string {
func (cvh *genericHandler[T, H]) supportsCloneIntoCgroup() bool {
return cvh.supportsClone
}
+
+func (cvh *genericHandler[T, H]) stats() (Stats, error) {
+ processCgroupPath := cvh.currentProcessCgroup()
+
+ control, err := cvh.loadFunc(cvh.hierarchy, processCgroupPath)
+ if err != nil {
+ return Stats{}, err
+ }
+
+ switch c := any(control).(type) {
+ case cgroup1.Cgroup:
+ return v1Stats(c, processCgroupPath)
+ case *cgroup2.Manager:
+ return v2stats(c, processCgroupPath)
+ default:
+ return Stats{}, errors.New("unknown cgroup type")
+ }
+}
+
+func v1Stats(control cgroup1.Cgroup, processCgroupPath string) (Stats, error) {
+ metrics, err := control.Stat()
+ if err != nil {
+ return Stats{}, fmt.Errorf("failed to fetch metrics %s: %w", processCgroupPath, err)
+ }
+
+ return Stats{
+ ParentStats: CgroupStats{
+ CPUThrottledCount: metrics.CPU.Throttling.ThrottledPeriods,
+ CPUThrottledDuration: float64(metrics.CPU.Throttling.ThrottledTime) / float64(time.Second),
+ MemoryUsage: metrics.Memory.Usage.Usage,
+ MemoryLimit: metrics.Memory.Usage.Limit,
+ OOMKills: metrics.MemoryOomControl.OomKill,
+ UnderOOM: metrics.MemoryOomControl.UnderOom != 0,
+ },
+ }, nil
+}
+
+func v2stats(control *cgroup2.Manager, processCgroupPath string) (Stats, error) {
+ metrics, err := control.Stat()
+ if err != nil {
+ return Stats{}, fmt.Errorf("failed to fetch metrics %s: %w", processCgroupPath, err)
+ }
+
+ stats := Stats{
+ ParentStats: CgroupStats{
+ CPUThrottledCount: metrics.CPU.NrThrottled,
+ CPUThrottledDuration: float64(metrics.CPU.ThrottledUsec) / float64(time.Second),
+ MemoryUsage: metrics.Memory.Usage,
+ MemoryLimit: metrics.Memory.UsageLimit,
+ },
+ }
+ if metrics.MemoryEvents != nil {
+ stats.ParentStats.OOMKills = metrics.MemoryEvents.OomKill
+ }
+ return stats, nil
+}