pomerium/internal/telemetry/metrics/processes.go

151 lines
3.4 KiB
Go

package metrics
import (
"context"
"github.com/prometheus/procfs"
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
)
// A ProcessCollector collects stats about a process.
type ProcessCollector struct {
cpuTotal *stats.Float64Measure
openFDs *stats.Int64Measure
maxFDs *stats.Int64Measure
vsize *stats.Int64Measure
maxVsize *stats.Int64Measure
rss *stats.Int64Measure
startTime *stats.Float64Measure
views []*view.View
}
// NewProcessCollector creates a new ProcessCollector.
func NewProcessCollector(name string) *ProcessCollector {
pc := &ProcessCollector{
cpuTotal: stats.Float64(
name+"_process_cpu_seconds_total",
"Total user and system CPU time spent in seconds.",
stats.UnitSeconds,
),
openFDs: stats.Int64(
name+"_process_open_fds",
"Number of open file descriptors.",
"{file_descriptor}",
),
maxFDs: stats.Int64(
name+"_process_max_fds",
"Maximum number of open file descriptors.",
"{file_descriptor}",
),
vsize: stats.Int64(
name+"_process_virtual_memory_bytes",
"Virtual memory size in bytes.",
stats.UnitBytes,
),
maxVsize: stats.Int64(
name+"_process_virtual_memory_max_bytes",
"Maximum amount of virtual memory available in bytes.",
stats.UnitBytes,
),
rss: stats.Int64(
name+"_process_resident_memory_bytes",
"Resident memory size in bytes.",
stats.UnitBytes,
),
startTime: stats.Float64(
name+"_process_start_time_seconds",
"Start time of the process since unix epoch in seconds.",
stats.UnitSeconds,
),
}
pc.views = []*view.View{
{
Name: pc.cpuTotal.Name(),
Description: pc.cpuTotal.Description(),
Measure: pc.cpuTotal,
Aggregation: view.LastValue(),
},
{
Name: pc.openFDs.Name(),
Description: pc.openFDs.Description(),
Measure: pc.openFDs,
Aggregation: view.LastValue(),
},
{
Name: pc.maxFDs.Name(),
Description: pc.maxFDs.Description(),
Measure: pc.maxFDs,
Aggregation: view.LastValue(),
},
{
Name: pc.vsize.Name(),
Description: pc.vsize.Description(),
Measure: pc.vsize,
Aggregation: view.LastValue(),
},
{
Name: pc.maxVsize.Name(),
Description: pc.maxVsize.Description(),
Measure: pc.maxVsize,
Aggregation: view.LastValue(),
},
{
Name: pc.rss.Name(),
Description: pc.rss.Description(),
Measure: pc.rss,
Aggregation: view.LastValue(),
},
{
Name: pc.startTime.Name(),
Description: pc.startTime.Description(),
Measure: pc.startTime,
Aggregation: view.LastValue(),
},
}
return pc
}
// Views returns the views for the process collector.
func (pc *ProcessCollector) Views() []*view.View {
return pc.views
}
// Measure measures the stats for a process.
func (pc *ProcessCollector) Measure(ctx context.Context, pid int) error {
proc, err := procfs.NewProc(pid)
if err != nil {
return err
}
procStat, err := proc.Stat()
if err != nil {
return err
}
procStartTime, err := procStat.StartTime()
if err != nil {
return err
}
procFDLen, err := proc.FileDescriptorsLen()
if err != nil {
return err
}
procLimits, err := proc.Limits()
if err != nil {
return err
}
stats.Record(ctx,
pc.cpuTotal.M(procStat.CPUTime()),
pc.openFDs.M(int64(procFDLen)),
pc.maxFDs.M(int64(procLimits.OpenFiles)),
pc.vsize.M(int64(procStat.VSize)),
pc.maxVsize.M(int64(procLimits.AddressSpace)),
pc.rss.M(int64(procStat.RSS)),
pc.startTime.M(procStartTime),
)
return nil
}