Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
8f1ee26
replace escaped hyphens in container names (fixes coroot/coroot#306)
def Aug 7, 2024
3f56517
Merge pull request #120 from coroot/issue_306
def Aug 7, 2024
f21f868
trace connection closure only through the `close` syscall
def Aug 21, 2024
a90fb2d
Merge pull request #121 from coroot/fix_short_lived_connections_handling
def Aug 21, 2024
dcaa29b
logparser v1.1.5
def Sep 23, 2024
99a6368
Merge pull request #127 from coroot/logparser_update
def Sep 23, 2024
b388bc2
CRI-O: try connecting with different socket paths
jeinwag Sep 25, 2024
93f0d1f
Merge pull request #129 from jeinwag/crio_retry
def Sep 25, 2024
8af5e1a
Merge remote-tracking branch 'upstream/main' into rebase-upstream
mayankpande88 Sep 25, 2024
f4f3b0d
remove `ipsByNs` cache
def Oct 1, 2024
ccd14a5
Merge pull request #130 from coroot/tcp_listen_sockets
def Oct 1, 2024
0b4c590
Merge remote-tracking branch 'upstream/main' into rebase-upstream
mayankpande88 Oct 2, 2024
7276a81
Merge pull request #79 from nudgebee/rebase-upstream
mayankpande88 Oct 10, 2024
f411fa1
add `--insecure-skip-verify` CLI argument to skip certificate validat…
def Oct 15, 2024
dd275c6
Merge pull request #132 from coroot/insecure_skip_verify
def Oct 15, 2024
1d3c74b
fix .NET app name collisions
def Oct 15, 2024
ad6ad6a
Merge pull request #133 from coroot/fix_dotnet_apps_collisions
def Oct 15, 2024
150658e
collapsed metrics of CronJob pods
def Oct 17, 2024
f1d06c3
Merge pull request #134 from coroot/collapsing_metrics_of_cronjob_pods
def Oct 17, 2024
b809e4d
collapse high-cardinality metrics (TCP, L7) related to interactions …
def Nov 1, 2024
667b87c
Merge pull request #136 from coroot/collapse-s3-metrics
def Nov 1, 2024
5867b91
add support for Talos Linux runtime
def Nov 1, 2024
7ebae09
Merge pull request #137 from coroot/talos_support
def Nov 1, 2024
ec07a0b
image: switch to `ubi9` base
apetruhin Nov 5, 2024
00ad291
Merge pull request #81 from nudgebee/main
mayankpande88 Nov 12, 2024
5941c6a
application types: add `valkey` and `dragonfly`
def Nov 12, 2024
5eecdd7
Merge pull request #139 from coroot/redis_alternatives
def Nov 12, 2024
a72509b
skip connections to link-local IPs
def Nov 13, 2024
4785312
group HTTP statuses (e.g., 2xx, 4xx) to reduce the number of metrics …
def Nov 13, 2024
c7356a0
DNS metric optimization
def Nov 14, 2024
4ede0a3
Merge pull request #140 from coroot/metric_optimizations
def Nov 14, 2024
3ebb3d5
tls: support "invalid" go versions
apetruhin Nov 22, 2024
480ea30
Merge pull request #142 from coroot/tls_invalid_go_versions_support
apetruhin Nov 26, 2024
a8ee24d
conntrack: use `Dump` in `GetActualDestination`
apetruhin Nov 22, 2024
55183ef
Merge pull request #143 from coroot/conntrack_get_via_dump
apetruhin Nov 26, 2024
5430687
build: gzip+base64 ebpf progs
apetruhin Nov 26, 2024
a87bc34
ebpf: apply extra padding for tracepoints arguments (5.14-el9 kernels)
apetruhin Nov 26, 2024
92f532f
Merge pull request #144 from coroot/openshift_fixes
apetruhin Nov 26, 2024
8d332f3
Revert "conntrack: use `Dump` in `GetActualDestination`"
apetruhin Nov 27, 2024
3eea121
build: upgrade `go`, `cilium/ebpf`, `pyroscope/ebpf`
apetruhin Nov 27, 2024
ffd3971
ebpf: buffered read from perfmaps
apetruhin Nov 27, 2024
e02bf28
Merge pull request #145 from coroot/ebpf_perfmap_buffered_read
apetruhin Nov 27, 2024
1279365
eBPF-based resolving of actual TCP connection destinations (conntrack)
def Nov 29, 2024
1dac238
Merge pull request #146 from coroot/ebpf_conntrack
def Nov 29, 2024
6702469
persist OTel tracers in containers
def Nov 29, 2024
f51d5cc
Merge pull request #147 from coroot/persistent_tracer_per_container
def Nov 29, 2024
a1524ba
logs: multilineCollectorTimeout=1s (instead of 100ms)
def Nov 29, 2024
649b1bf
Merge pull request #148 from coroot/log_reader_optimization
def Nov 29, 2024
1e16696
file events: skip reading `fdinfo` for previously seen mounts
def Dec 4, 2024
98808a0
Merge pull request #149 from coroot/fdinfo_optimization
def Dec 4, 2024
bcf6e0b
optimize FQDNs normalization
def Dec 4, 2024
42a8e5c
Merge pull request #150 from coroot/fast_fqdn_normalization
def Dec 4, 2024
b996840
fix kernel version validation (#152)
apetruhin Dec 9, 2024
29f5d2c
Merge pull request #153 from coroot/kernel_version_fix
apetruhin Dec 9, 2024
3d08524
conntrack: use kprobe on `nf_confirm` for 5.3+ kernels where it is ex…
def Dec 10, 2024
45feb6b
feat: added sensitive log pattern related stats (#83)
mayankpande88 Dec 10, 2024
803664f
fix cgroup detection
def Dec 10, 2024
d7bdc41
use kprobe on `path_get` to determine the relevant mount for file ope…
def Dec 10, 2024
9386698
Merge pull request #154 from coroot/ebpf_compatibility
def Dec 10, 2024
de1e1e9
fix: fix updated sensitive log rules (#84)
mayankpande88 Dec 10, 2024
566e5d7
feat: added pattern name and regex (#85)
mayankpande88 Dec 11, 2024
a989468
conntrack: use kprobe on `nf_ct_deliver_cached_events` for tracking c…
def Dec 11, 2024
6dcf8fe
Merge pull request #156 from coroot/nf_ct_deliver_cached_events
def Dec 11, 2024
638facd
cgroup: don't report CPU, Memory, and IO usage for `/` cgroup
def Dec 16, 2024
7f46467
Merge pull request #157 from coroot/fix_resource_usage_metrics
def Dec 16, 2024
77944fa
feat: added pattern hash in metric (#86)
mayankpande88 Dec 17, 2024
e9ecd30
build(deps): bump github.com/opencontainers/runc from 1.1.12 to 1.1.1…
dependabot[bot] Dec 17, 2024
1217e5e
add support for ClickHouse native protocol
def Dec 19, 2024
7adb723
Merge pull request #159 from coroot/clickhouse_protocol_support
def Dec 19, 2024
fedbdbd
add support for Zookeeper client protocol
def Dec 20, 2024
f6185e0
Merge pull request #160 from coroot/zk_protocol_support
def Dec 20, 2024
da1d263
handle missing `nf_conntrack` gracefully
def Dec 23, 2024
1da58fa
Merge pull request #161 from coroot/disabled_nf_conntrack
def Dec 23, 2024
8ed2571
handle partial Zookeeper reads
def Dec 23, 2024
1dbf538
Merge pull request #162 from coroot/partial_zk_reads
def Dec 25, 2024
09c1209
close existing connection with same PID:FD when creating a new one
def Dec 27, 2024
f49ea14
Merge pull request #164 from coroot/handling_out_of_order
def Dec 27, 2024
0c9b1b5
fix: use informer index workload watchers (#88)
mayankpande88 Dec 30, 2024
704288b
Merge remote-tracking branch 'upstream/main' into rebase-upstream-30-12
mayankpande88 Dec 30, 2024
e292d66
fix: fix for go version
mayankpande88 Dec 30, 2024
2828e1a
fix: fix for active connection metric
mayankpande88 Dec 30, 2024
82e0454
fix: fix for tracing conflict
mayankpande88 Dec 30, 2024
0919f17
fix: fix for src workload
mayankpande88 Dec 30, 2024
7b2c011
Merge pull request #89 from nudgebee/rebase-upstream-30-12
mayankpande88 Dec 30, 2024
28066d5
fix: removed loggers (#90)
mayankpande88 Dec 31, 2024
e81ad31
Merge pull request #91 from nudgebee/main
mayankpande88 Dec 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: '1.23'
- run: sudo apt install -y libsystemd-dev
- name: gofmt -l .
run: files=$(gofmt -l .); if [[ -n "$files" ]]; then echo "$files"; exit 1; fi
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/dev-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ on:
workflow_dispatch:
push:
branches: [ "main" ]

jobs:
goreleaser:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Below are some basic guidelines.

## Requirements
* Linux ≥v4.16 (amd64, arm64)
* Go v1.21
* Go v1.23


## Running
Expand Down
8 changes: 5 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21-bullseye AS builder
FROM golang:1.23-bullseye AS builder
RUN apt update && apt install -y libsystemd-dev
WORKDIR /tmp/src
COPY go.mod .
Expand All @@ -8,7 +8,9 @@ COPY . .
ARG VERSION=unknown
RUN CGO_ENABLED=1 go build -mod=readonly -ldflags "-X main.version=$VERSION" -o coroot-node-agent .

FROM debian:bullseye-slim
RUN apt update && apt install -y ca-certificates && apt clean
FROM registry.access.redhat.com/ubi9/ubi

ARG VERSION=unknown

COPY --from=builder /tmp/src/coroot-node-agent /usr/bin/coroot-node-agent
ENTRYPOINT ["coroot-node-agent"]
10 changes: 5 additions & 5 deletions Dockerfile.alpine
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
FROM --platform=linux/amd64 golang:1.22-alpine as build-stage

FROM --platform=linux/amd64 golang:1.23-alpine as build-stage
# Set destination for COPY
WORKDIR /app
RUN apk add --no-cache --update go gcc g++ bash git
Expand All @@ -8,7 +7,7 @@ RUN echo "unicode=\"YES\"" >> /etc/rc.conf && \
autoconf file libc-dev make pkgconf python3 py3-pip ninja \
util-linux pciutils usbutils coreutils binutils findutils grep \
build-base abuild binutils binutils-doc gcc-doc gperf libcap libcap-dev \
valgrind-dev libmount && pip3 install meson --break-system-packages
valgrind-dev libmount && pip3 install meson --break-system-packages

RUN cd /tmp && git clone https://github.com/systemd/systemd

Expand All @@ -18,9 +17,10 @@ RUN cd /tmp && git clone https://github.com/systemd/systemd

RUN apk add elogind-dev

# Download Go modules
COPY go.mod go.sum ./
RUN go mod download

RUN go mod download

COPY ./ ./
ARG VERSION=unknown
RUN CGO_ENABLED=1 go build -mod=readonly -ldflags "-X main.version=$VERSION" -o coroot-node-agent .
Expand Down
56 changes: 33 additions & 23 deletions cgroup/cgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var (
containerdIdRegexp = regexp.MustCompile(`cri-containerd[-:]([a-z0-9]{64})`)
lxcIdRegexp = regexp.MustCompile(`/lxc/([^/]+)`)
systemSliceIdRegexp = regexp.MustCompile(`(/(system|runtime)\.slice/([^/]+))`)
talosIdRegexp = regexp.MustCompile(`/(system|podruntime)/([^/]+)`)
)

type Version uint8
Expand All @@ -43,6 +44,7 @@ const (
ContainerTypeLxc
ContainerTypeSystemdService
ContainerTypeSandbox
ContainerTypeTalosRuntime
)

func (t ContainerType) String() string {
Expand Down Expand Up @@ -105,24 +107,25 @@ func NewFromProcessCgroupFile(filePath string) (*Cgroup, error) {
cg.subsystems[cgType] = path.Join(baseCgroupPath, parts[2])
}
}
if p := cg.subsystems["name=systemd"]; p != "" {
cg.Id = p
cg.Version = V1
} else if p = cg.subsystems["cpu"]; p != "" {
cg.Id = p
cg.Version = V1
} else {
cg.Id = cg.subsystems[""]
if cg.Id = cg.subsystems[""]; cg.Id != "" {
cg.Version = V2
} else if cg.Id = cg.subsystems["cpu"]; cg.Id != "" {
cg.Version = V1
}
if (cg.Id == "" || cg.Id == "/") && cg.subsystems["name=systemd"] != "/" {
cg.Id = cg.subsystems["name=systemd"]
}
if cg.ContainerType, cg.ContainerId, err = containerByCgroup(cg.Id); err != nil {
return nil, err
}
return cg, nil
}

func containerByCgroup(path string) (ContainerType, string, error) {
parts := strings.Split(strings.TrimLeft(path, "/"), "/")
func containerByCgroup(cgroupPath string) (ContainerType, string, error) {
parts := strings.Split(strings.TrimLeft(cgroupPath, "/"), "/")
if cgroupPath == "/init" {
return ContainerTypeTalosRuntime, "/talos/init", nil
}
if len(parts) < 2 {
return ContainerTypeStandaloneProcess, "", nil
}
Expand All @@ -134,43 +137,50 @@ func containerByCgroup(path string) (ContainerType, string, error) {
return ContainerTypeStandaloneProcess, "", nil
}
if prefix == "docker" || (prefix == "system.slice" && strings.HasPrefix(parts[1], "docker-")) {
matches := dockerIdRegexp.FindStringSubmatch(path)
matches := dockerIdRegexp.FindStringSubmatch(cgroupPath)
if matches == nil {
return ContainerTypeUnknown, "", fmt.Errorf("invalid docker cgroup %s", path)
return ContainerTypeUnknown, "", fmt.Errorf("invalid docker cgroup %s", cgroupPath)
}
return ContainerTypeDocker, matches[1], nil
}
if strings.Contains(path, "kubepods") {
crioMatches := crioIdRegexp.FindStringSubmatch(path)
if strings.Contains(cgroupPath, "kubepods") {
crioMatches := crioIdRegexp.FindStringSubmatch(cgroupPath)
if crioMatches != nil {
return ContainerTypeCrio, crioMatches[1], nil
}
if strings.Contains(path, "crio-conmon-") {
if strings.Contains(cgroupPath, "crio-conmon-") {
return ContainerTypeUnknown, "", nil
}
containerdMatches := containerdIdRegexp.FindStringSubmatch(path)
containerdMatches := containerdIdRegexp.FindStringSubmatch(cgroupPath)
if containerdMatches != nil {
return ContainerTypeContainerd, containerdMatches[1], nil
}
matches := dockerIdRegexp.FindStringSubmatch(path)
matches := dockerIdRegexp.FindStringSubmatch(cgroupPath)
if matches == nil {
return ContainerTypeSandbox, "", nil
}
return ContainerTypeDocker, matches[1], nil
}
if prefix == "lxc" {
matches := lxcIdRegexp.FindStringSubmatch(path)
matches := lxcIdRegexp.FindStringSubmatch(cgroupPath)
if matches == nil {
return ContainerTypeUnknown, "", fmt.Errorf("invalid lxc cgroup %s", path)
return ContainerTypeUnknown, "", fmt.Errorf("invalid lxc cgroup %s", cgroupPath)
}
return ContainerTypeLxc, matches[1], nil
}
if prefix == "system" || prefix == "podruntime" {
matches := talosIdRegexp.FindStringSubmatch(cgroupPath)
if matches == nil {
return ContainerTypeUnknown, "", fmt.Errorf("invalid talos runtime cgroup %s", cgroupPath)
}
return ContainerTypeTalosRuntime, path.Join("/talos/", matches[2]), nil
}
if prefix == "system.slice" || prefix == "runtime.slice" {
matches := systemSliceIdRegexp.FindStringSubmatch(path)
matches := systemSliceIdRegexp.FindStringSubmatch(cgroupPath)
if matches == nil {
return ContainerTypeUnknown, "", fmt.Errorf("invalid systemd cgroup %s", path)
return ContainerTypeUnknown, "", fmt.Errorf("invalid systemd cgroup %s", cgroupPath)
}
return ContainerTypeSystemdService, matches[1], nil
return ContainerTypeSystemdService, strings.Replace(matches[1], "\\x2d", "-", -1), nil
}
return ContainerTypeUnknown, "", fmt.Errorf("unknown container: %s", path)
return ContainerTypeUnknown, "", fmt.Errorf("unknown container: %s", cgroupPath)
}
43 changes: 42 additions & 1 deletion cgroup/cgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ func TestNewFromProcessCgroupFile(t *testing.T) {
assert.Equal(t, "/system.slice/springboot.service", cg.ContainerId)
assert.Equal(t, ContainerTypeSystemdService, cg.ContainerType)

cg, err = NewFromProcessCgroupFile(path.Join("fixtures/proc/700/cgroup"))
assert.Nil(t, err)
assert.Equal(t, V2, cg.Version)
assert.Equal(t, "/podruntime/runtime", cg.Id)
assert.Equal(t, "/talos/runtime", cg.ContainerId)
assert.Equal(t, ContainerTypeTalosRuntime, cg.ContainerType)

cg, err = NewFromProcessCgroupFile(path.Join("fixtures/proc/800/cgroup"))
assert.Nil(t, err)
assert.Equal(t, V2, cg.Version)
assert.Equal(t, "/system.slice/docker-cf87ba651579c9231db817909e7865e5747bd7abcac0c57ce23cf4abbaee046b.scope", cg.Id)
assert.Equal(t, "cf87ba651579c9231db817909e7865e5747bd7abcac0c57ce23cf4abbaee046b", cg.ContainerId)
assert.Equal(t, ContainerTypeDocker, cg.ContainerType)

cg, err = NewFromProcessCgroupFile(path.Join("fixtures/proc/900/cgroup"))
assert.Nil(t, err)
assert.Equal(t, V1, cg.Version)
assert.Equal(t, "/system.slice/python-app.service", cg.Id)
assert.Equal(t, "/system.slice/python-app.service", cg.ContainerId)
assert.Equal(t, ContainerTypeSystemdService, cg.ContainerType)

baseCgroupPath = "/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podc83d0428_58af_41eb_8dba_b9e6eddffe7b.slice/docker-0e612005fd07e7f47e2cd07df99a2b4e909446814d71d0b5e4efc7159dd51252.scope"
defer func() {
baseCgroupPath = ""
Expand Down Expand Up @@ -97,6 +118,11 @@ func TestContainerByCgroup(t *testing.T) {
as.Equal("63425c4a8b4291744a79dd9011fddc7a1f8ffda61f65d72196aa01d00cae2e2d", id)
as.Nil(err)

typ, id, err = containerByCgroup("/docker/63425c4a8b4291744a79dd9011fddc7a1f8ffda61f65d72196aa01d00cae2e2d")
as.Equal(typ, ContainerTypeDocker)
as.Equal("63425c4a8b4291744a79dd9011fddc7a1f8ffda61f65d72196aa01d00cae2e2d", id)
as.Nil(err)

typ, id, err = containerByCgroup("/lxc/mysql-primary-db")
as.Equal(typ, ContainerTypeLxc)
as.Equal("mysql-primary-db", id)
Expand All @@ -119,7 +145,7 @@ func TestContainerByCgroup(t *testing.T) {

typ, id, err = containerByCgroup("/system.slice/system-serial\\x2dgetty.slice")
as.Equal(typ, ContainerTypeSystemdService)
as.Equal("/system.slice/system-serial\\x2dgetty.slice", id)
as.Equal("/system.slice/system-serial-getty.slice", id)
as.Nil(err)

typ, id, err = containerByCgroup("/runtime.slice/kubelet.service")
Expand All @@ -136,4 +162,19 @@ func TestContainerByCgroup(t *testing.T) {
as.Equal(typ, ContainerTypeContainerd)
as.Equal("d4a9f9195eaf7e4a729f24151101e1de61f1398677e7b82acfb936dff0b4ce55", id)
as.Nil(err)

typ, id, err = containerByCgroup("/podruntime/kubelet")
as.Equal(typ, ContainerTypeTalosRuntime)
as.Equal("/talos/kubelet", id)
as.Nil(err)

typ, id, err = containerByCgroup("/system/dashboard")
as.Equal(typ, ContainerTypeTalosRuntime)
as.Equal("/talos/dashboard", id)
as.Nil(err)

typ, id, err = containerByCgroup("/init")
as.Equal(typ, ContainerTypeTalosRuntime)
as.Equal("/talos/init", id)
as.Nil(err)
}
63 changes: 34 additions & 29 deletions cgroup/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package cgroup

import (
"fmt"
"io/ioutil"
"os"
"path"
"strconv"
"strings"

"github.com/coroot/coroot-node-agent/common"
)

type CPUStat struct {
Expand All @@ -14,27 +16,32 @@ type CPUStat struct {
LimitCores float64
}

func (cg Cgroup) CpuStat() (*CPUStat, error) {
func (cg Cgroup) CpuStat() *CPUStat {
if cg.Version == V1 {
return cg.cpuStatV1()
st, _ := cg.cpuStatV1()
return st
}
return cg.cpuStatV2()
st, _ := cg.cpuStatV2()
return st
}

func (cg Cgroup) cpuStatV1() (*CPUStat, error) {
if cg.subsystems["cpu"] == "/" || cg.subsystems["cpuacct"] == "/" {
return nil, nil
}
throttling, err := readVariablesFromFile(path.Join(cgRoot, "cpu", cg.subsystems["cpu"], "cpu.stat"))
if err != nil {
return nil, err
}
usageNs, err := readIntFromFile(path.Join(cgRoot, "cpuacct", cg.subsystems["cpuacct"], "cpuacct.usage"))
usageNs, err := common.ReadIntFromFile(path.Join(cgRoot, "cpuacct", cg.subsystems["cpuacct"], "cpuacct.usage"))
if err != nil {
return nil, err
}
periodUs, err := readIntFromFile(path.Join(cgRoot, "cpu", cg.subsystems["cpu"], "cpu.cfs_period_us"))
periodUs, err := common.ReadIntFromFile(path.Join(cgRoot, "cpu", cg.subsystems["cpu"], "cpu.cfs_period_us"))
if err != nil {
return nil, err
}
quotaUs, err := readIntFromFile(path.Join(cgRoot, "cpu", cg.subsystems["cpu"], "cpu.cfs_quota_us"))
quotaUs, err := common.ReadIntFromFile(path.Join(cgRoot, "cpu", cg.subsystems["cpu"], "cpu.cfs_quota_us"))
if err != nil {
return nil, err
}
Expand All @@ -57,28 +64,26 @@ func (cg Cgroup) cpuStatV2() (*CPUStat, error) {
UsageSeconds: float64(vars["usage_usec"]) / 1e6,
ThrottledTimeSeconds: float64(vars["throttled_usec"]) / 1e6,
}
payload, err := ioutil.ReadFile(path.Join(cgRoot, cg.subsystems[""], "cpu.max"))
if err != nil {
return nil, err
}
data := strings.TrimSpace(string(payload))
parts := strings.Fields(data)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid cpu.max payload: %s", data)
}
if parts[0] == "max" { //no limit
return res, nil
}
quotaUs, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid quota value in cpu.max: %s", parts[0])
}
periodUs, err := strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid period value in cpu.max: %s", parts[1])
}
if periodUs > 0 {
res.LimitCores = float64(quotaUs) / float64(periodUs)
if payload, err := os.ReadFile(path.Join(cgRoot, cg.subsystems[""], "cpu.max")); err == nil {
data := strings.TrimSpace(string(payload))
parts := strings.Fields(data)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid cpu.max payload: %s", data)
}
if parts[0] == "max" { //no limit
return res, nil
}
quotaUs, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid quota value in cpu.max: %s", parts[0])
}
periodUs, err := strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid period value in cpu.max: %s", parts[1])
}
if periodUs > 0 {
res.LimitCores = float64(quotaUs) / float64(periodUs)
}
}
return res, nil
}
17 changes: 9 additions & 8 deletions cgroup/cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,29 @@ func TestCgroup_CpuStat(t *testing.T) {
cgRoot = "fixtures/cgroup"

cg, _ := NewFromProcessCgroupFile(path.Join("fixtures/proc/100/cgroup"))
s, err := cg.CpuStat()
assert.Nil(t, err)
s := cg.CpuStat()
assert.Equal(t, 0., s.LimitCores)
assert.Equal(t, 26778.913419246, s.UsageSeconds)

cg, _ = NewFromProcessCgroupFile(path.Join("fixtures/proc/200/cgroup"))
s, err = cg.CpuStat()
assert.Nil(t, err)
s = cg.CpuStat()
assert.Equal(t, 1.5, s.LimitCores)
assert.Equal(t, 254005.032764376, s.ThrottledTimeSeconds)

cg, _ = NewFromProcessCgroupFile(path.Join("fixtures/proc/400/cgroup"))
s, err = cg.CpuStat()
assert.Nil(t, err)
s = cg.CpuStat()
assert.Equal(t, 0.1, s.LimitCores)
assert.Equal(t, 0.363166, s.ThrottledTimeSeconds)
assert.Equal(t, 3795.681254, s.UsageSeconds)

cg, _ = NewFromProcessCgroupFile(path.Join("fixtures/proc/500/cgroup"))
s, err = cg.CpuStat()
assert.Nil(t, err)
s = cg.CpuStat()
assert.Equal(t, 0., s.LimitCores)
assert.Equal(t, 0., s.ThrottledTimeSeconds)
assert.Equal(t, 5531.521992, s.UsageSeconds)

cg, _ = NewFromProcessCgroupFile(path.Join("fixtures/proc/1000/cgroup"))
s, err := cg.cpuStatV1()
assert.NoError(t, err)
assert.Nil(t, s)
}
Loading