Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for cgroup CPUQuota and CPUPeriod prometheus limit #969

Merged
merged 1 commit into from
Feb 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions container/raw/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
if utils.FileExists(cpuRoot) {
spec.HasCpu = true
spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add this metric only to the raw driver?
Is it possible to extract this metrics even for docker containers?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@f0 Any thoughts on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jimmidyson hm not really , why not but i think this should be done in a different PR

spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us")
quota := readString(cpuRoot, "cpu.cfs_quota_us")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the readInt64 method as above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because if the quota is not set, -1 is returned and internally readInt64 uses an uint and this breaks with -1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check that - so really readInt64 should really be readUInt64...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes this would be much cleaner


if quota != "-1" {
val, err := strconv.ParseUint(quota, 10, 64)
if err != nil {
glog.Errorf("raw driver: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err)
}
spec.Cpu.Quota = val
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions info/v1/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type CpuSpec struct {
Limit uint64 `json:"limit"`
MaxLimit uint64 `json:"max_limit"`
Mask string `json:"mask,omitempty"`
Quota uint64 `json:"quota,omitempty"`
Period uint64 `json:"period,omitempty"`
}

type MemorySpec struct {
Expand Down
4 changes: 4 additions & 0 deletions info/v2/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ type CpuSpec struct {
// Cpu affinity mask.
// TODO(rjnagal): Add a library to convert mask string to set of cpu bitmask.
Mask string `json:"mask,omitempty"`
// CPUQuota Default is disabled
Quota uint64 `json:"quota,omitempty"`
// Period is the CPU reference time in ns e.g the quota is compared aginst this.
Period uint64 `json:"period,omitempty"`
}

type MemorySpec struct {
Expand Down
8 changes: 7 additions & 1 deletion metrics/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,16 @@ func (c *PrometheusCollector) collectContainersInfo(ch chan<- prometheus.Metric)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.CreationTime.Unix()), baseLabelValues...)

if container.Spec.HasCpu {
desc = prometheus.NewDesc("container_spec_cpu_period", "CPU period of the container.", baseLabels, nil)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Period), baseLabelValues...)
if container.Spec.Cpu.Quota != 0 {
desc = prometheus.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", baseLabels, nil)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Quota), baseLabelValues...)
}
desc := prometheus.NewDesc("container_spec_cpu_shares", "CPU share of the container.", baseLabels, nil)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Limit), baseLabelValues...)
}

}
if container.Spec.HasMemory {
desc := prometheus.NewDesc("container_spec_memory_limit_bytes", "Memory limit for the container.", baseLabels, nil)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.Limit), baseLabelValues...)
Expand Down
8 changes: 7 additions & 1 deletion metrics/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ func (p testSubcontainersInfoProvider) SubcontainersInfo(string, *info.Container
Aliases: []string{"testcontaineralias"},
},
Spec: info.ContainerSpec{
Image: "test",
Image: "test",
HasCpu: true,
Cpu: info.CpuSpec{
Limit: 1000,
Period: 10,
Quota: 10000,
},
CreationTime: time.Unix(1257894000, 0),
Labels: map[string]string{
"foo.label": "bar",
Expand Down
11 changes: 10 additions & 1 deletion metrics/testdata/prometheus_metrics
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ container_network_transmit_packets_total{foo_env="prod",foo_label="bar",id="test
# HELP container_scrape_error 1 if there was an error while getting container metrics, 0 otherwise
# TYPE container_scrape_error gauge
container_scrape_error 0
# HELP container_spec_cpu_period CPU period of the container.
# TYPE container_spec_cpu_period gauge
container_spec_cpu_period{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 10
# HELP container_spec_cpu_quota CPU quota of the container.
# TYPE container_spec_cpu_quota gauge
container_spec_cpu_quota{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 10000
# HELP container_spec_cpu_shares CPU share of the container.
# TYPE container_spec_cpu_shares gauge
container_spec_cpu_shares{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 1000
# HELP container_start_time_seconds Start time of the container since unix epoch in seconds.
# TYPE container_start_time_seconds gauge
container_start_time_seconds{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 1.257894e+09
Expand Down Expand Up @@ -173,4 +182,4 @@ process_resident_memory_bytes 7.74144e+06
process_start_time_seconds 1.42620369439e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 1.16420608e+08
process_virtual_memory_bytes 1.16420608e+08