diff --git a/libbeat/cmd/instance/metrics.go b/libbeat/cmd/instance/metrics.go index 54cd3ab55d8..fa0d42bbeaf 100644 --- a/libbeat/cmd/instance/metrics.go +++ b/libbeat/cmd/instance/metrics.go @@ -28,6 +28,7 @@ import ( "github.com/elastic/beats/v7/libbeat/metric/system/cpu" "github.com/elastic/beats/v7/libbeat/metric/system/process" "github.com/elastic/beats/v7/libbeat/monitoring" + "github.com/elastic/gosigar/cgroup" ) var ( @@ -65,10 +66,15 @@ func setupMetrics(name string) error { } func setupPlatformSpecificMetrics() { + switch runtime.GOOS { + case "linux": + monitoring.NewFunc(beatMetrics, "cgroup", reportBeatCgroups, monitoring.Report) + case "windows": + setupWindowsHandlesMetrics() + } + if runtime.GOOS != "windows" { monitoring.NewFunc(systemMetrics, "load", reportSystemLoadAverage, monitoring.Report) - } else { - setupWindowsHandlesMetrics() } setupLinuxBSDFDMetrics() @@ -254,3 +260,79 @@ func reportRuntime(_ monitoring.Mode, V monitoring.Visitor) { monitoring.ReportInt(V, "goroutines", int64(runtime.NumGoroutine())) } + +func reportBeatCgroups(_ monitoring.Mode, V monitoring.Visitor) { + V.OnRegistryStart() + defer V.OnRegistryFinished() + + pid, err := process.GetSelfPid() + if err != nil { + logp.Err("error getting PID for self process: %v", err) + return + } + + cgroups, err := cgroup.NewReader("", true) + if err != nil { + if err == cgroup.ErrCgroupsMissing { + logp.Warn("cgroup data collection disabled: %v", err) + } else { + logp.Err("cgroup data collection disabled: %v", err) + } + return + } + selfStats, err := cgroups.GetStatsForProcess(pid) + if err != nil { + logp.Err("error getting group status: %v", err) + return + } + + if cpu := selfStats.CPU; cpu != nil { + monitoring.ReportNamespace(V, "cpu", func() { + if cpu.ID != "" { + monitoring.ReportString(V, "id", cpu.ID) + } + monitoring.ReportNamespace(V, "cfs", func() { + monitoring.ReportNamespace(V, "period", func() { + monitoring.ReportInt(V, "us", int64(cpu.CFS.PeriodMicros)) + }) + monitoring.ReportNamespace(V, "quota", func() { + monitoring.ReportInt(V, "us", int64(cpu.CFS.QuotaMicros)) + }) + }) + monitoring.ReportNamespace(V, "stats", func() { + monitoring.ReportInt(V, "periods", int64(cpu.Stats.Periods)) + monitoring.ReportNamespace(V, "throttled", func() { + monitoring.ReportInt(V, "periods", int64(cpu.Stats.ThrottledPeriods)) + monitoring.ReportInt(V, "ns", int64(cpu.Stats.ThrottledTimeNanos)) + }) + }) + }) + } + + if cpuacct := selfStats.CPUAccounting; cpuacct != nil { + monitoring.ReportNamespace(V, "cpuacct", func() { + if cpuacct.ID != "" { + monitoring.ReportString(V, "id", cpuacct.ID) + } + monitoring.ReportNamespace(V, "total", func() { + monitoring.ReportInt(V, "ns", int64(cpuacct.TotalNanos)) + }) + }) + } + + if memory := selfStats.Memory; memory != nil { + monitoring.ReportNamespace(V, "memory", func() { + if memory.ID != "" { + monitoring.ReportString(V, "id", memory.ID) + } + monitoring.ReportNamespace(V, "mem", func() { + monitoring.ReportNamespace(V, "limit", func() { + monitoring.ReportInt(V, "bytes", int64(memory.Mem.Limit)) + }) + monitoring.ReportNamespace(V, "usage", func() { + monitoring.ReportInt(V, "bytes", int64(memory.Mem.Usage)) + }) + }) + }) + } +}