Make uptime available in the stat output for a container

This commit is contained in:
Dane Everitt 2021-10-03 12:59:03 -07:00
parent 0cfd72e1d1
commit d9ebf693e0
4 changed files with 37 additions and 7 deletions

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"math" "math"
"time"
"emperror.dev/errors" "emperror.dev/errors"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -12,6 +13,23 @@ import (
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
) )
// Uptime returns the current uptime of the container in milliseconds. If the
// container is not currently running this will return 0.
func (e *Environment) Uptime(ctx context.Context) (int64, error) {
ins, err := e.client.ContainerInspect(ctx, e.Id)
if err != nil {
return 0, errors.Wrap(err, "environment: could not inspect container")
}
if !ins.State.Running {
return 0, nil
}
started, err := time.Parse(time.RFC3339, ins.State.StartedAt)
if err != nil {
return 0, errors.Wrap(err, "environment: failed to parse container start time")
}
return time.Since(started).Milliseconds(), nil
}
// Attach to the instance and then automatically emit an event whenever the resource usage for the // Attach to the instance and then automatically emit an event whenever the resource usage for the
// server process changes. // server process changes.
func (e *Environment) pollResources(ctx context.Context) error { func (e *Environment) pollResources(ctx context.Context) error {
@ -28,6 +46,11 @@ func (e *Environment) pollResources(ctx context.Context) error {
} }
defer stats.Body.Close() defer stats.Body.Close()
uptime, err := e.Uptime(ctx)
if err != nil {
e.log().WithField("error", err).Warn("failed to calculate container uptime")
}
dec := json.NewDecoder(stats.Body) dec := json.NewDecoder(stats.Body)
for { for {
select { select {
@ -50,7 +73,12 @@ func (e *Environment) pollResources(ctx context.Context) error {
return nil return nil
} }
if !v.PreRead.IsZero() {
uptime = uptime + v.Read.Sub(v.PreRead).Milliseconds()
}
st := environment.Stats{ st := environment.Stats{
Uptime: uptime,
Memory: calculateDockerMemory(v.MemoryStats), Memory: calculateDockerMemory(v.MemoryStats),
MemoryLimit: v.MemoryStats.Limit, MemoryLimit: v.MemoryStats.Limit,
CpuAbsolute: calculateDockerAbsoluteCpu(v.PreCPUStats, v.CPUStats), CpuAbsolute: calculateDockerAbsoluteCpu(v.PreCPUStats, v.CPUStats),

View File

@ -104,4 +104,8 @@ type ProcessEnvironment interface {
// handle this itself, but there are some scenarios where it is helpful for the server // handle this itself, but there are some scenarios where it is helpful for the server
// to update the state externally (e.g. starting -> started). // to update the state externally (e.g. starting -> started).
SetState(string) SetState(string)
// Uptime returns the current environment uptime in milliseconds. This is
// the time that has passed since it was last started.
Uptime(ctx context.Context) (int64, error)
} }

View File

@ -1,8 +1,6 @@
package environment package environment
// Defines the current resource usage for a given server instance. If a server is offline you // Stats defines the current resource usage for a given server instance.
// should obviously expect memory and CPU usage to be 0. However, disk will always be returned
// since that is not dependent on the server being running to collect that data.
type Stats struct { type Stats struct {
// The total amount of memory, in bytes, that this server instance is consuming. This is // The total amount of memory, in bytes, that this server instance is consuming. This is
// calculated slightly differently than just using the raw Memory field that the stats // calculated slightly differently than just using the raw Memory field that the stats
@ -19,12 +17,11 @@ type Stats struct {
// does not take into account any limits on the server process itself. // does not take into account any limits on the server process itself.
CpuAbsolute float64 `json:"cpu_absolute"` CpuAbsolute float64 `json:"cpu_absolute"`
// The current disk space being used by the server. This is cached to prevent slow lookup
// issues on frequent refreshes.
// Disk int64 `json:"disk_bytes"`
// Current network transmit in & out for a container. // Current network transmit in & out for a container.
Network NetworkStats `json:"network"` Network NetworkStats `json:"network"`
// The current uptime of the container, in milliseconds.
Uptime int64 `json:"uptime"`
} }
type NetworkStats struct { type NetworkStats struct {

View File

@ -46,6 +46,7 @@ func (ru *ResourceUsage) Reset() {
ru.Memory = 0 ru.Memory = 0
ru.CpuAbsolute = 0 ru.CpuAbsolute = 0
ru.Uptime = 0
ru.Network.TxBytes = 0 ru.Network.TxBytes = 0
ru.Network.RxBytes = 0 ru.Network.RxBytes = 0
} }