diff --git a/container.go b/container.go index a705c56f3f..f4726f8b8d 100644 --- a/container.go +++ b/container.go @@ -13,7 +13,10 @@ var ( defaultTimeout = time.Minute * 4 ) -const pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}` +const ( + pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}` + statisticsQuery = `{ "PropertyTypes" : ["Statistics"]}` +) type container struct { handle hcsSystem @@ -26,12 +29,59 @@ type containerProperties struct { Name string SystemType string Owner string - SiloGUID string `json:"SiloGuid,omitempty"` - IsDummy bool `json:",omitempty"` - RuntimeID string `json:"RuntimeId,omitempty"` - Stopped bool `json:",omitempty"` - ExitType string `json:",omitempty"` - AreUpdatesPending bool `json:",omitempty"` + SiloGUID string `json:"SiloGuid,omitempty"` + IsDummy bool `json:",omitempty"` + RuntimeID string `json:"RuntimeId,omitempty"` + Stopped bool `json:",omitempty"` + ExitType string `json:",omitempty"` + AreUpdatesPending bool `json:",omitempty"` + ObRoot string `json:",omitempty"` + Statistics Statistics `json:",omitempty"` +} + +// MemoryStats holds the memory statistics for a container +type MemoryStats struct { + UsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"` + UsageCommitPeakBytes uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"` + UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` +} + +// ProcessorStats holds the processor statistics for a container +type ProcessorStats struct { + TotalRuntime100ns uint64 `json:",omitempty"` + RuntimeUser100ns uint64 `json:",omitempty"` + RuntimeKernel100ns uint64 `json:",omitempty"` +} + +// StorageStats holds the storage statistics for a container +type StorageStats struct { + ReadCountNormalized uint64 `json:",omitempty"` + ReadSizeBytes uint64 `json:",omitempty"` + WriteCountNormalized uint64 `json:",omitempty"` + WriteSizeBytes uint64 `json:",omitempty"` +} + +// NetworkStats holds the network statistics for a container +type NetworkStats struct { + BytesReceived uint64 `json:",omitempty"` + BytesSent uint64 `json:",omitempty"` + PacketsReceived uint64 `json:",omitempty"` + PacketsSent uint64 `json:",omitempty"` + DroppedPacketsIncoming uint64 `json:",omitempty"` + DroppedPacketsOutgoing uint64 `json:",omitempty"` + EndpointId string `json:",omitempty"` + InstanceId string `json:",omitempty"` +} + +// Statistics is the structure returned by a statistics call on a container +type Statistics struct { + Timestamp time.Time `json:",omitempty"` + ContainerStartTime time.Time `json:",omitempty"` + Uptime100ns uint64 `json:",omitempty"` + Memory MemoryStats `json:",omitempty"` + Processor ProcessorStats `json:",omitempty"` + Storage StorageStats `json:",omitempty"` + Network []NetworkStats `json:",omitempty"` } // CreateContainer creates a new container with the given configuration but does not start it. @@ -246,12 +296,10 @@ func (container *container) properties(query string) (*containerProperties, erro return nil, ErrUnexpectedValue } propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp) - properties := &containerProperties{} if err := json.Unmarshal(propertiesRaw, properties); err != nil { return nil, err } - return properties, nil } @@ -269,6 +317,20 @@ func (container *container) HasPendingUpdates() (bool, error) { return properties.AreUpdatesPending, nil } +// Statistics returns statistics for the container +func (container *container) Statistics() (Statistics, error) { + operation := "Statistics" + title := "HCSShim::Container::" + operation + logrus.Debugf(title+" id=%s", container.id) + properties, err := container.properties(statisticsQuery) + if err != nil { + return Statistics{}, makeContainerError(container, operation, "", err) + } + + logrus.Debugf(title+" succeeded id=%s", container.id) + return properties.Statistics, nil +} + // Pause pauses the execution of the container. This feature is not enabled in TP5. func (container *container) Pause() error { operation := "Pause" diff --git a/interface.go b/interface.go index e35e477f01..0eacca38ce 100644 --- a/interface.go +++ b/interface.go @@ -90,6 +90,9 @@ type Container interface { // HasPendingUpdates returns true if the container has updates pending to install. HasPendingUpdates() (bool, error) + // Statistics returns statistics for a container. + Statistics() (Statistics, error) + // CreateProcess launches a new process within the container. CreateProcess(c *ProcessConfig) (Process, error)