Skip to content

Commit

Permalink
feat: add bytesize, queue, mem, profiler and sync packages (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
atzoum committed May 24, 2023
1 parent 4c74116 commit 4bfc4e1
Show file tree
Hide file tree
Showing 46 changed files with 1,544 additions and 0 deletions.
11 changes: 11 additions & 0 deletions bytesize/bytesize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package bytesize

const (
B int64 = 1
KB int64 = 1 << (10 * iota)
MB
GB
TB
PB
EB
)
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/prometheus/client_golang v1.15.0
github.com/prometheus/client_model v0.3.0
github.com/prometheus/common v0.42.0
github.com/shirou/gopsutil/v3 v3.23.4
github.com/spf13/cast v1.5.0
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2
Expand Down Expand Up @@ -50,13 +51,15 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
Expand All @@ -68,15 +71,19 @@ require (
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.37.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect
Expand Down
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.4.2/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
Expand Down Expand Up @@ -176,6 +178,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
Expand Down Expand Up @@ -227,6 +230,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
Expand Down Expand Up @@ -268,6 +273,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
Expand All @@ -282,6 +289,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o=
github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8=
github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
Expand Down Expand Up @@ -317,6 +328,10 @@ github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNG
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/throttled/throttled/v2 v2.11.0 h1:/udbW8pGpm5SutM3OvAk6ygAC3/PbmoVvSkq9xbzjxI=
github.com/throttled/throttled/v2 v2.11.0/go.mod h1:qT849G1rYAXypqSrqtSCewU1p7lNmWDZNBBBSAZUvj8=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
Expand All @@ -332,6 +347,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
Expand Down Expand Up @@ -492,6 +509,7 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -517,6 +535,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -533,6 +552,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
42 changes: 42 additions & 0 deletions httputil/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package httputil

import (
"context"
"net"
"net/http"
"time"
)

func ListenAndServe(ctx context.Context, server *http.Server, shutdownTimeout ...time.Duration) error {
return gracefulFunc(ctx, server, server.ListenAndServe, shutdownTimeout...)
}

func Serve(ctx context.Context, server *http.Server, l net.Listener, shutdownTimeout ...time.Duration) error {
fn := func() error {
return server.Serve(l)
}
return gracefulFunc(ctx, server, fn, shutdownTimeout...)
}

func gracefulFunc(ctx context.Context, server *http.Server, fn func() error, shutdownTimeout ...time.Duration) error {
errCh := make(chan error, 1)
go func() {
errCh <- fn()
}()
select {
case err := <-errCh:
return err
case <-ctx.Done():
switch {
case len(shutdownTimeout) == 0:
return server.Shutdown(context.Background())
case shutdownTimeout[0] == 0:
return server.Close()
default:
ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout[0])
defer cancel()

return server.Shutdown(ctx)
}
}
}
124 changes: 124 additions & 0 deletions mem/internal/cgroup/mem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package cgroup

import (
"strconv"
)

// GetMemoryUsage returns cgroup (v1 or v2) memory usage
func GetMemoryUsage(basePath string) int64 {
n, err := getMemStatCgroup1(basePath, "memory.usage_in_bytes")
if err == nil {
wss := getWSSMemoryCgroup1(basePath, n)
rss := getRSSMemoryCgroup1(basePath)
if wss > rss {
return wss
}
return rss
}
n, err = getMemStatCgroup2(basePath, "memory.current")
if err != nil {
return 0
}
return getWSSMemoryCgroup2(basePath, n)
}

// GetMemoryLimit returns the cgroup's (v1 or v2) memory limit, or [totalMem] if there is no limit set.
// If using cgroups v1, hierarchical memory limit is also taken into consideration if there is no limit set.
//
// - https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
//
// - https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory-interface-files
func GetMemoryLimit(basePath string, totalMem int) int {
getLimit := func() int64 {
// cgroups v1
n, err := getMemStatCgroup1(basePath, "memory.limit_in_bytes")
if err == nil {
if n <= 0 || int64(int(n)) != n || int(n) > totalMem {
// try to get hierarchical limit
n = GetHierarchicalMemoryLimitCgroup1(basePath)
}
return n
}

// cgroups v2
n, err = getMemStatCgroup2(basePath, "memory.max")
if err != nil {
return 0
}
return n
}
limit := getLimit()

// if the number in not within expected boundaries, return totalMem
if limit <= 0 || int64(int(limit)) != limit || int(limit) > totalMem {
return totalMem
}
return int(limit)
}

func getMemStatCgroup2(basePath, statName string) (int64, error) {
// See https: //www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory-interface-files
return getStatGeneric(statName, basePath+"/sys/fs/cgroup", basePath+"/proc/self/cgroup", "")
}

func getMemStatCgroup1(basePath, statName string) (int64, error) {
return getStatGeneric(statName, basePath+"/sys/fs/cgroup/memory", basePath+"/proc/self/cgroup", "memory")
}

// GetHierarchicalMemoryLimitCgroup1 returns hierarchical memory limit
// https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
func GetHierarchicalMemoryLimitCgroup1(basePath string) int64 {
return memStatCgroup1(basePath, "hierarchical_memory_limit")
}

func getRSSMemoryCgroup1(basePath string) int64 {
return memStatCgroup1(basePath, "total_rss")
}

func getWSSMemoryCgroup1(basePath string, used int64) int64 {
inactive := memStatCgroup1(basePath, "total_inactive_file")
if used < inactive {
return 0
}
return used - inactive
}

func getWSSMemoryCgroup2(basePath string, used int64) int64 {
inactive := memStatCgroup2(basePath, "inactive_file")
if used < inactive {
return 0
}
return used - inactive
}

func memStatCgroup1(basePath, key string) int64 {
data, err := getFileContents("memory.stat", basePath+"/sys/fs/cgroup/memory", basePath+"/proc/self/cgroup", "memory")
if err != nil {
return 0
}
memStat, err := grepFirstMatch(data, key, 1, " ")
if err != nil {
return 0
}
n, err := strconv.ParseInt(memStat, 10, 64)
if err != nil {
return 0
}
return n
}

func memStatCgroup2(basePath, key string) int64 {
data, err := getFileContents("memory.stat", basePath+"/sys/fs/cgroup", basePath+"/proc/self/cgroup", "")
if err != nil {
return 0
}
memStat, err := grepFirstMatch(data, key, 1, " ")
if err != nil {
return 0
}
n, err := strconv.ParseInt(memStat, 10, 64)
if err != nil {
return 0
}
return n
}
74 changes: 74 additions & 0 deletions mem/internal/cgroup/mem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package cgroup_test

import (
"testing"

"github.com/rudderlabs/rudder-go-kit/bytesize"
"github.com/rudderlabs/rudder-go-kit/mem/internal/cgroup"
"github.com/stretchr/testify/require"
)

func TestCgroupMemory(t *testing.T) {
t.Run("cgroups v1 with limit", func(t *testing.T) {
basePath := "testdata/cgroups_v1_mem_limit"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, 25*bytesize.GB, limit, "when a limit is set, this limit should be returned")
require.EqualValues(t, 7873486848, cgroup.GetMemoryUsage(basePath))
})

t.Run("cgroups v1 with self limit", func(t *testing.T) {
basePath := "testdata/cgroups_v1_mem_limit_proc_self"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, 25*bytesize.GB, limit, "when a limit is set, this limit should be returned")
require.EqualValues(t, 9456156572, cgroup.GetMemoryUsage(basePath))
})

t.Run("cgroups v1 with hierarchical limit", func(t *testing.T) {
basePath := "testdata/cgroups_v1_mem_hierarchy"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, 25*bytesize.GB, limit, "when a hierarchical limit is set, this limit should be returned")
require.EqualValues(t, 7873486848, cgroup.GetMemoryUsage(basePath))
})

t.Run("cgroups v1 no limit", func(t *testing.T) {
basePath := "testdata/cgroups_v1_mem_no_limit"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, totalMem, limit, "when no limit is set, total memory should be returned")
require.EqualValues(t, 7873486848, cgroup.GetMemoryUsage(basePath))
})

t.Run("cgroups v2 with limit", func(t *testing.T) {
basePath := "testdata/cgroups_v2_mem_limit"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, 32*bytesize.GB, limit, "when a limit is set, this limit should be returned")
require.EqualValues(t, 26071040, cgroup.GetMemoryUsage(basePath))
})

t.Run("cgroups v2 no limit", func(t *testing.T) {
basePath := "testdata/cgroups_v2_mem_no_limit"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, totalMem, limit, "when no limit is set, total memory should be returned")
require.EqualValues(t, 26071040, cgroup.GetMemoryUsage(basePath))
})

t.Run("no cgroups info", func(t *testing.T) {
basePath := "testdata/invalid_path"
totalMem := int(100 * bytesize.GB)
limit := cgroup.GetMemoryLimit(basePath, totalMem)

require.EqualValues(t, limit, limit, "when no cgroups info is available, this limit should be returned")
require.EqualValues(t, 0, cgroup.GetMemoryUsage(basePath))
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Using cgroup v1 with current memory usage at 9456156672, where no memory limit is set but a hierarchical memory limit is set at 26843545600
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9223372036854771712
Loading

0 comments on commit 4bfc4e1

Please sign in to comment.