kata-containers/src/runtime/virtcontainers/sandbox_metrics.go
Manohar Castelino 4d47aeef2e hypervisor: Export generic interface methods
This is in preparation for creating a seperate hypervisor package.
Non functional change.

Signed-off-by: Manohar Castelino <mcastelino@apple.com>
2021-10-22 16:45:35 -07:00

228 lines
5.6 KiB
Go

// Copyright (c) 2020 Ant Financial
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
mutils "github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
)
const namespaceHypervisor = "kata_hypervisor"
const namespaceKatashim = "kata_shim"
const namespaceVirtiofsd = "kata_virtiofsd"
var (
// hypervisor
hypervisorThreads = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "threads",
Help: "Hypervisor process threads.",
})
hypervisorProcStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "proc_status",
Help: "Hypervisor process status.",
},
[]string{"item"},
)
hypervisorProcStat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "proc_stat",
Help: "Hypervisor process statistics.",
},
[]string{"item"},
)
hypervisorNetdev = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "netdev",
Help: "Net devices statistics.",
},
[]string{"interface", "item"},
)
hypervisorIOStat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "io_stat",
Help: "Process IO statistics.",
},
[]string{"item"},
)
hypervisorOpenFDs = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespaceHypervisor,
Name: "fds",
Help: "Open FDs for hypervisor.",
})
// agent
agentRPCDurationsHistogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespaceKatashim,
Name: "agent_rpc_durations_histogram_milliseconds",
Help: "RPC latency distributions.",
Buckets: prometheus.ExponentialBuckets(1, 2, 10),
},
[]string{"action"},
)
// virtiofsd
virtiofsdThreads = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespaceVirtiofsd,
Name: "threads",
Help: "Virtiofsd process threads.",
})
virtiofsdProcStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceVirtiofsd,
Name: "proc_status",
Help: "Virtiofsd process status.",
},
[]string{"item"},
)
virtiofsdProcStat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceVirtiofsd,
Name: "proc_stat",
Help: "Virtiofsd process statistics.",
},
[]string{"item"},
)
virtiofsdIOStat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespaceVirtiofsd,
Name: "io_stat",
Help: "Process IO statistics.",
},
[]string{"item"},
)
virtiofsdOpenFDs = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespaceVirtiofsd,
Name: "fds",
Help: "Open FDs for virtiofsd.",
})
)
func RegisterMetrics() {
// hypervisor
prometheus.MustRegister(hypervisorThreads)
prometheus.MustRegister(hypervisorProcStatus)
prometheus.MustRegister(hypervisorProcStat)
prometheus.MustRegister(hypervisorNetdev)
prometheus.MustRegister(hypervisorIOStat)
prometheus.MustRegister(hypervisorOpenFDs)
// agent
prometheus.MustRegister(agentRPCDurationsHistogram)
// virtiofsd
prometheus.MustRegister(virtiofsdThreads)
prometheus.MustRegister(virtiofsdProcStatus)
prometheus.MustRegister(virtiofsdProcStat)
prometheus.MustRegister(virtiofsdIOStat)
prometheus.MustRegister(virtiofsdOpenFDs)
}
// UpdateRuntimeMetrics update shim/hypervisor's metrics
func (s *Sandbox) UpdateRuntimeMetrics() error {
pids := s.hypervisor.GetPids()
if len(pids) == 0 {
return nil
}
hypervisorPid := pids[0]
proc, err := procfs.NewProc(hypervisorPid)
if err != nil {
return err
}
// process FDs
if fds, err := proc.FileDescriptorsLen(); err == nil {
hypervisorOpenFDs.Set(float64(fds))
}
// process net device statistics
if netdev, err := proc.NetDev(); err == nil {
// netdev: map[string]NetDevLine
for _, v := range netdev {
mutils.SetGaugeVecNetDev(hypervisorNetdev, v)
}
}
// process statistics
if procStat, err := proc.Stat(); err == nil {
hypervisorThreads.Set(float64(procStat.NumThreads))
mutils.SetGaugeVecProcStat(hypervisorProcStat, procStat)
}
// process status
if procStatus, err := proc.NewStatus(); err == nil {
mutils.SetGaugeVecProcStatus(hypervisorProcStatus, procStatus)
}
// process IO statistics
if ioStat, err := proc.IO(); err == nil {
mutils.SetGaugeVecProcIO(hypervisorIOStat, ioStat)
}
// virtiofs metrics
err = s.UpdateVirtiofsdMetrics()
if err != nil {
return err
}
return nil
}
func (s *Sandbox) UpdateVirtiofsdMetrics() error {
vfsPid := s.hypervisor.GetVirtioFsPid()
if vfsPid == nil {
// virtiofsd is not mandatory for a VMM.
return nil
}
proc, err := procfs.NewProc(*vfsPid)
if err != nil {
return err
}
// process FDs
if fds, err := proc.FileDescriptorsLen(); err == nil {
virtiofsdOpenFDs.Set(float64(fds))
}
// process statistics
if procStat, err := proc.Stat(); err == nil {
virtiofsdThreads.Set(float64(procStat.NumThreads))
mutils.SetGaugeVecProcStat(virtiofsdProcStat, procStat)
}
// process status
if procStatus, err := proc.NewStatus(); err == nil {
mutils.SetGaugeVecProcStatus(virtiofsdProcStatus, procStatus)
}
// process IO statistics
if ioStat, err := proc.IO(); err == nil {
mutils.SetGaugeVecProcIO(virtiofsdIOStat, ioStat)
}
return nil
}
func (s *Sandbox) GetAgentMetrics(ctx context.Context) (string, error) {
r, err := s.agent.getAgentMetrics(ctx, &grpc.GetMetricsRequest{})
if err != nil {
return "", err
}
return r.Metrics, nil
}