init cgroups
This commit is contained in:
33
cgroups/controller.go
Normal file
33
cgroups/controller.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package cgroups
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
//go:generate stringer -type=Controller -linecomment
|
||||||
|
|
||||||
|
const (
|
||||||
|
ControllerUndefined Controller = iota // undefined
|
||||||
|
ControllerPids // pids
|
||||||
|
ControllerCPU // cpu
|
||||||
|
ControllerMemory // memory
|
||||||
|
ControllerRdma // rdma
|
||||||
|
ControllerIo // io
|
||||||
|
)
|
||||||
|
|
||||||
|
type Controller int
|
||||||
|
|
||||||
|
func ParseController(in string) (Controller, error) {
|
||||||
|
switch in {
|
||||||
|
case ControllerPids.String():
|
||||||
|
return ControllerPids, nil
|
||||||
|
case ControllerCPU.String():
|
||||||
|
return ControllerCPU, nil
|
||||||
|
case ControllerMemory.String():
|
||||||
|
return ControllerMemory, nil
|
||||||
|
case ControllerRdma.String():
|
||||||
|
return ControllerRdma, nil
|
||||||
|
case ControllerIo.String():
|
||||||
|
return ControllerIo, nil
|
||||||
|
default:
|
||||||
|
return ControllerUndefined, fmt.Errorf("Controller(%s)", in)
|
||||||
|
}
|
||||||
|
}
|
||||||
28
cgroups/controller_string.go
Normal file
28
cgroups/controller_string.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Code generated by "stringer -type=Controller -linecomment"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[ControllerUndefined-0]
|
||||||
|
_ = x[ControllerPids-1]
|
||||||
|
_ = x[ControllerCPU-2]
|
||||||
|
_ = x[ControllerMemory-3]
|
||||||
|
_ = x[ControllerRdma-4]
|
||||||
|
_ = x[ControllerIo-5]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Controller_name = "undefinedpidscpumemoryrdmaio"
|
||||||
|
|
||||||
|
var _Controller_index = [...]uint8{0, 9, 13, 16, 22, 26, 28}
|
||||||
|
|
||||||
|
func (i Controller) String() string {
|
||||||
|
if i < 0 || i >= Controller(len(_Controller_index)-1) {
|
||||||
|
return "Controller(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Controller_name[_Controller_index[i]:_Controller_index[i+1]]
|
||||||
|
}
|
||||||
190
cgroups/cpu.go
Normal file
190
cgroups/cpu.go
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
package cgroups
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
cgroups "github.com/containerd/cgroups/v3/cgroup2"
|
||||||
|
"github.com/containerd/cgroups/v3/cgroup2/stats"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option supports configuring optional settings for runtime metrics.
|
||||||
|
type Option interface {
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig(controllers []Controller, opts ...Option) config {
|
||||||
|
cfg := config{
|
||||||
|
controllers: controllers,
|
||||||
|
provider: otel.GetMeterProvider(),
|
||||||
|
prefix: "cgroups.",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.apply(&cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
controllers []Controller
|
||||||
|
provider metric.MeterProvider
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
type cgroup struct {
|
||||||
|
meter metric.Meter
|
||||||
|
stats func() (*stats.Metrics, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cgroup) cpu(prefix string) (func(context.Context, metric.Observer, *stats.Metrics), []metric.Observable, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
usageUsec metric.Int64ObservableGauge
|
||||||
|
userUsec metric.Int64ObservableGauge
|
||||||
|
systemUsec metric.Int64ObservableGauge
|
||||||
|
nrPeriods metric.Int64ObservableGauge
|
||||||
|
nrThrottled metric.Int64ObservableGauge
|
||||||
|
throttledUsec metric.Int64ObservableGauge
|
||||||
|
)
|
||||||
|
|
||||||
|
if usageUsec, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"usage_usec",
|
||||||
|
metric.WithDescription("Total cpu usage"),
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("usage_usec:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if userUsec, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"user_usec",
|
||||||
|
metric.WithDescription("Current cpu usage in user space"),
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("user_usec:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if systemUsec, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"system_usec",
|
||||||
|
metric.WithDescription("Current cpu usage in kernel space"),
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("system_usec:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nrPeriods, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"nr_periods",
|
||||||
|
metric.WithDescription("Current cpu number of periods (only if controller is enabled)"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("nr_periods:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nrThrottled, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"nr_throttled",
|
||||||
|
metric.WithDescription("Total number of times tasks have been throttled (only if controller is enabled)"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("nr_throttled:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if throttledUsec, err = c.meter.Int64ObservableGauge(
|
||||||
|
prefix+"throttled_usec",
|
||||||
|
metric.WithDescription("Total time duration for which tasks have been throttled. (only if controller is enabled)"),
|
||||||
|
metric.WithUnit("microseconds"),
|
||||||
|
); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("throttled_usec:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(ctx context.Context, o metric.Observer, m *stats.Metrics) {
|
||||||
|
o.ObserveInt64(usageUsec, int64(m.CPU.UsageUsec))
|
||||||
|
o.ObserveInt64(userUsec, int64(m.CPU.UserUsec))
|
||||||
|
o.ObserveInt64(systemUsec, int64(m.CPU.SystemUsec))
|
||||||
|
o.ObserveInt64(nrPeriods, int64(m.CPU.NrPeriods))
|
||||||
|
o.ObserveInt64(nrThrottled, int64(m.CPU.NrThrottled))
|
||||||
|
o.ObserveInt64(throttledUsec, int64(m.CPU.ThrottledUsec))
|
||||||
|
}, []metric.Observable{
|
||||||
|
usageUsec, userUsec, systemUsec, nrPeriods, nrThrottled, throttledUsec,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cgroup) register(prefix string, ctrls ...Controller) (metric.Registration, error) {
|
||||||
|
observable := make([]metric.Observable, 0, len(ctrls))
|
||||||
|
callbacks := make([]func(context.Context, metric.Observer, *stats.Metrics), 0, len(ctrls))
|
||||||
|
for _, ctrl := range ctrls {
|
||||||
|
switch ctrl {
|
||||||
|
case ControllerCPU:
|
||||||
|
cpu, cpus, err := c.cpu(prefix + "cpu.")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("controller cpu:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
observable = append(observable, cpus...)
|
||||||
|
callbacks = append(callbacks, cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lock sync.Mutex
|
||||||
|
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
ureg, err := c.meter.RegisterCallback(
|
||||||
|
func(ctx context.Context, obsrv metric.Observer) error {
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
stats, uErr := c.stats()
|
||||||
|
if uErr != nil {
|
||||||
|
return fmt.Errorf("cpu get stat:%w", uErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
callback(ctx, obsrv, stats)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
observable...,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("register callback:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ureg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start(group string, opts ...Option) (metric.Registration, error) {
|
||||||
|
manager, err := cgroups.Load(group)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
controllers, cerr := manager.Controllers()
|
||||||
|
if cerr != nil {
|
||||||
|
return nil, fmt.Errorf("controllers:%w", cerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrls := make([]Controller, 0, len(controllers))
|
||||||
|
for _, controller := range controllers {
|
||||||
|
ctrl, err := ParseController(controller)
|
||||||
|
if err == nil {
|
||||||
|
ctrls = append(ctrls, ctrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := newConfig(ctrls, opts...)
|
||||||
|
|
||||||
|
cgr := cgroup{
|
||||||
|
meter: cfg.provider.Meter(
|
||||||
|
"gitoa.ru/go-4devs/otel/cgroups",
|
||||||
|
metric.WithInstrumentationVersion(Version()),
|
||||||
|
),
|
||||||
|
stats: manager.Stat,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cgr.register(cfg.prefix+group+".", cfg.controllers...)
|
||||||
|
}
|
||||||
23
cgroups/go.mod
Normal file
23
cgroups/go.mod
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
module gitoa.ru/go-4devs/otel/cgroups
|
||||||
|
|
||||||
|
go 1.22.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/containerd/cgroups/v3 v3.0.3
|
||||||
|
go.opentelemetry.io/otel v1.25.0
|
||||||
|
go.opentelemetry.io/otel/metric v1.25.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cilium/ebpf v0.11.0 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4 // indirect
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.2 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.25.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
||||||
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
)
|
||||||
59
cgroups/go.sum
Normal file
59
cgroups/go.sum
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
||||||
|
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
||||||
|
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||||
|
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
||||||
|
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
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/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
|
||||||
|
go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
|
||||||
|
go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
|
||||||
|
go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
|
||||||
|
go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
|
||||||
|
go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
|
||||||
|
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||||
|
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
||||||
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
5
cgroups/version.go
Normal file
5
cgroups/version.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package cgroups
|
||||||
|
|
||||||
|
func Version() string {
|
||||||
|
return "0.0.1"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user