Add support for container statistics (#318)

Closes #138

This rounds up cgroup and network stats (via netlink) and exposes them
via an agent rpc and on LinuxContainer. While this is not an entirely
accurate view into the full resources being used by the container given
the virtualized nature (doesn't account for vcpu, device etc overhead)
it should give an accurate overview of the workload resource usage in
the guest.

This change besides the stated goal also removes the interfaceStatistics
rpc and just moves these network stats into the new containerStatistics
one. Related to that, it also renames the InterfaceStatistics struct to
NetworkStatistics and moves this into ContainerStatistics as a nested
struct.
This commit is contained in:
Danny Canter
2025-10-08 10:09:10 -04:00
committed by GitHub
parent 85de8fc0c5
commit 06d3a37f8d
13 changed files with 1321 additions and 382 deletions
@@ -0,0 +1,177 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
/// Statistics for a container.
public struct ContainerStatistics: Sendable {
public var id: String
public var process: ProcessStatistics
public var memory: MemoryStatistics
public var cpu: CPUStatistics
public var blockIO: BlockIOStatistics
public var networks: [NetworkStatistics]
public init(
id: String,
process: ProcessStatistics,
memory: MemoryStatistics,
cpu: CPUStatistics,
blockIO: BlockIOStatistics,
networks: [NetworkStatistics]
) {
self.id = id
self.process = process
self.memory = memory
self.cpu = cpu
self.blockIO = blockIO
self.networks = networks
}
/// Process statistics for a container.
public struct ProcessStatistics: Sendable {
public var current: UInt64
public var limit: UInt64
public init(current: UInt64, limit: UInt64) {
self.current = current
self.limit = limit
}
}
/// Memory statistics for a container.
public struct MemoryStatistics: Sendable {
public var usageBytes: UInt64
public var limitBytes: UInt64
public var swapUsageBytes: UInt64
public var swapLimitBytes: UInt64
public var cacheBytes: UInt64
public var kernelStackBytes: UInt64
public var slabBytes: UInt64
public var pageFaults: UInt64
public var majorPageFaults: UInt64
public init(
usageBytes: UInt64,
limitBytes: UInt64,
swapUsageBytes: UInt64,
swapLimitBytes: UInt64,
cacheBytes: UInt64,
kernelStackBytes: UInt64,
slabBytes: UInt64,
pageFaults: UInt64,
majorPageFaults: UInt64
) {
self.usageBytes = usageBytes
self.limitBytes = limitBytes
self.swapUsageBytes = swapUsageBytes
self.swapLimitBytes = swapLimitBytes
self.cacheBytes = cacheBytes
self.kernelStackBytes = kernelStackBytes
self.slabBytes = slabBytes
self.pageFaults = pageFaults
self.majorPageFaults = majorPageFaults
}
}
/// CPU statistics for a container.
public struct CPUStatistics: Sendable {
public var usageUsec: UInt64
public var userUsec: UInt64
public var systemUsec: UInt64
public var throttlingPeriods: UInt64
public var throttledPeriods: UInt64
public var throttledTimeUsec: UInt64
public init(
usageUsec: UInt64,
userUsec: UInt64,
systemUsec: UInt64,
throttlingPeriods: UInt64,
throttledPeriods: UInt64,
throttledTimeUsec: UInt64
) {
self.usageUsec = usageUsec
self.userUsec = userUsec
self.systemUsec = systemUsec
self.throttlingPeriods = throttlingPeriods
self.throttledPeriods = throttledPeriods
self.throttledTimeUsec = throttledTimeUsec
}
}
/// Block I/O statistics for a container.
public struct BlockIOStatistics: Sendable {
public var devices: [BlockIODevice]
public init(devices: [BlockIODevice]) {
self.devices = devices
}
}
/// Block I/O statistics for a specific device.
public struct BlockIODevice: Sendable {
public var major: UInt64
public var minor: UInt64
public var readBytes: UInt64
public var writeBytes: UInt64
public var readOperations: UInt64
public var writeOperations: UInt64
public init(
major: UInt64,
minor: UInt64,
readBytes: UInt64,
writeBytes: UInt64,
readOperations: UInt64,
writeOperations: UInt64
) {
self.major = major
self.minor = minor
self.readBytes = readBytes
self.writeBytes = writeBytes
self.readOperations = readOperations
self.writeOperations = writeOperations
}
}
/// Statistics for a network interface.
public struct NetworkStatistics: Sendable {
public var interface: String
public var receivedPackets: UInt64
public var transmittedPackets: UInt64
public var receivedBytes: UInt64
public var transmittedBytes: UInt64
public var receivedErrors: UInt64
public var transmittedErrors: UInt64
public init(
interface: String,
receivedPackets: UInt64,
transmittedPackets: UInt64,
receivedBytes: UInt64,
transmittedBytes: UInt64,
receivedErrors: UInt64,
transmittedErrors: UInt64
) {
self.interface = interface
self.receivedPackets = receivedPackets
self.transmittedPackets = transmittedPackets
self.receivedBytes = receivedBytes
self.transmittedBytes = transmittedBytes
self.receivedErrors = receivedErrors
self.transmittedErrors = transmittedErrors
}
}
}
@@ -1,44 +0,0 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
/// Statistics for a network interface.
public struct InterfaceStatistics {
public var name: String
public var receivedPackets: UInt64?
public var transmittedPackets: UInt64?
public var receivedBytes: UInt64?
public var transmittedBytes: UInt64?
public var receivedErrors: UInt64?
public var transmittedErrors: UInt64?
public init(
name: String,
receivedPackets: UInt64?,
transmittedPackets: UInt64?,
receivedBytes: UInt64?,
transmittedBytes: UInt64?,
receivedErrors: UInt64?,
transmittedErrors: UInt64?
) {
self.name = name
self.receivedPackets = receivedPackets
self.transmittedPackets = transmittedPackets
self.receivedBytes = receivedBytes
self.transmittedBytes = transmittedBytes
self.receivedErrors = receivedErrors
self.transmittedErrors = transmittedErrors
}
}
+21 -2
View File
@@ -821,6 +821,24 @@ extension LinuxContainer {
return try await state.process.closeStdin()
}
/// Get statistics for the container.
public func statistics() async throws -> ContainerStatistics {
let state = try self.state.withLock { try $0.startedState("statistics") }
let stats = try await state.vm.withAgent { agent in
let allStats = try await agent.containerStatistics(containerIDs: [self.id])
guard let containerStats = allStats.first else {
throw ContainerizationError(
.notFound,
message: "statistics for container \(self.id) not found"
)
}
return containerStats
}
return stats
}
/// Relay a unix socket from in the container to the host, or from the host
/// to inside the container.
public func relayUnixSocket(socket: UnixSocketConfiguration) async throws {
@@ -865,11 +883,12 @@ extension LinuxContainer {
extension VirtualMachineInstance {
/// Scoped access to an agent instance to ensure the resources are always freed (mostly close(2)'ing
/// the vsock fd)
fileprivate func withAgent(fn: @Sendable (VirtualMachineAgent) async throws -> Void) async throws {
fileprivate func withAgent<T>(fn: @Sendable (VirtualMachineAgent) async throws -> T) async throws -> T {
let agent = try await self.dialAgent()
do {
try await fn(agent)
let result = try await fn(agent)
try await agent.close()
return result
} catch {
try? await agent.close()
throw error
@@ -114,6 +114,11 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtoc
callOptions: CallOptions?
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinRequest, Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse>
func containerStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
callOptions: CallOptions?
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>
func proxyVsock(
_ request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest,
callOptions: CallOptions?
@@ -154,11 +159,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtoc
callOptions: CallOptions?
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_ConfigureHostsRequest, Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse>
func interfaceStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
callOptions: CallOptions?
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>
func sync(
_ request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
callOptions: CallOptions?
@@ -464,6 +464,24 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtocol {
)
}
/// Get statistics for containers.
///
/// - Parameters:
/// - request: Request to send to ContainerStatistics.
/// - callOptions: Call options.
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
public func containerStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
callOptions: CallOptions? = nil
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse> {
return self.makeUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.containerStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeContainerStatisticsInterceptors() ?? []
)
}
/// Proxy a vsock port to a unix domain socket in the guest, or vice versa.
///
/// - Parameters:
@@ -608,24 +626,6 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtocol {
)
}
/// Get statistics about an interface.
///
/// - Parameters:
/// - request: Request to send to InterfaceStatistics.
/// - callOptions: Call options.
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
public func interfaceStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
callOptions: CallOptions? = nil
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse> {
return self.makeUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.interfaceStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeInterfaceStatisticsInterceptors() ?? []
)
}
/// Perform the sync syscall.
///
/// - Parameters:
@@ -806,6 +806,11 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientP
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinRequest, Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse>
func makeContainerStatisticsCall(
_ request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>
func makeProxyVsockCall(
_ request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest,
callOptions: CallOptions?
@@ -846,11 +851,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientP
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_ConfigureHostsRequest, Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse>
func makeInterfaceStatisticsCall(
_ request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>
func makeSyncCall(
_ request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
callOptions: CallOptions?
@@ -1064,6 +1064,18 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
)
}
public func makeContainerStatisticsCall(
_ request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse> {
return self.makeAsyncUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.containerStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeContainerStatisticsInterceptors() ?? []
)
}
public func makeProxyVsockCall(
_ request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest,
callOptions: CallOptions? = nil
@@ -1160,18 +1172,6 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
)
}
public func makeInterfaceStatisticsCall(
_ request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse> {
return self.makeAsyncUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.interfaceStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeInterfaceStatisticsInterceptors() ?? []
)
}
public func makeSyncCall(
_ request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
callOptions: CallOptions? = nil
@@ -1391,6 +1391,18 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
)
}
public func containerStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
callOptions: CallOptions? = nil
) async throws -> Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse {
return try await self.performAsyncUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.containerStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeContainerStatisticsInterceptors() ?? []
)
}
public func proxyVsock(
_ request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest,
callOptions: CallOptions? = nil
@@ -1487,18 +1499,6 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
)
}
public func interfaceStatistics(
_ request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
callOptions: CallOptions? = nil
) async throws -> Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse {
return try await self.performAsyncUnaryCall(
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.interfaceStatistics.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeInterfaceStatisticsInterceptors() ?? []
)
}
public func sync(
_ request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
callOptions: CallOptions? = nil
@@ -1591,6 +1591,9 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientInterc
/// - Returns: Interceptors to use when invoking 'closeProcessStdin'.
func makeCloseProcessStdinInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinRequest, Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse>]
/// - Returns: Interceptors to use when invoking 'containerStatistics'.
func makeContainerStatisticsInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>]
/// - Returns: Interceptors to use when invoking 'proxyVsock'.
func makeProxyVsockInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest, Com_Apple_Containerization_Sandbox_V3_ProxyVsockResponse>]
@@ -1615,9 +1618,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientInterc
/// - Returns: Interceptors to use when invoking 'configureHosts'.
func makeConfigureHostsInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_ConfigureHostsRequest, Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse>]
/// - Returns: Interceptors to use when invoking 'interfaceStatistics'.
func makeInterfaceStatisticsInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>]
/// - Returns: Interceptors to use when invoking 'sync'.
func makeSyncInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_SyncRequest, Com_Apple_Containerization_Sandbox_V3_SyncResponse>]
@@ -1646,6 +1646,7 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.waitProcess,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.resizeProcess,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.closeProcessStdin,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.containerStatistics,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.proxyVsock,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.stopVsockProxy,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.ipLinkSet,
@@ -1654,7 +1655,6 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.ipRouteAddDefault,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.configureDns,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.configureHosts,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.interfaceStatistics,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.sync,
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.kill,
]
@@ -1757,6 +1757,12 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
type: GRPCCallType.unary
)
public static let containerStatistics = GRPCMethodDescriptor(
name: "ContainerStatistics",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/ContainerStatistics",
type: GRPCCallType.unary
)
public static let proxyVsock = GRPCMethodDescriptor(
name: "ProxyVsock",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/ProxyVsock",
@@ -1805,12 +1811,6 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
type: GRPCCallType.unary
)
public static let interfaceStatistics = GRPCMethodDescriptor(
name: "InterfaceStatistics",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/InterfaceStatistics",
type: GRPCCallType.unary
)
public static let sync = GRPCMethodDescriptor(
name: "Sync",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/Sync",
@@ -1880,6 +1880,9 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider: Ca
/// Close IO for a given process.
func closeProcessStdin(request: Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse>
/// Get statistics for containers.
func containerStatistics(request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>
/// Proxy a vsock port to a unix domain socket in the guest, or vice versa.
func proxyVsock(request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_ProxyVsockResponse>
@@ -1904,9 +1907,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider: Ca
/// Configure /etc/hosts.
func configureHosts(request: Com_Apple_Containerization_Sandbox_V3_ConfigureHostsRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse>
/// Get statistics about an interface.
func interfaceStatistics(request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>
/// Perform the sync syscall.
func sync(request: Com_Apple_Containerization_Sandbox_V3_SyncRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_SyncResponse>
@@ -2070,6 +2070,15 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider {
userFunction: self.closeProcessStdin(request:context:)
)
case "ContainerStatistics":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest>(),
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>(),
interceptors: self.interceptors?.makeContainerStatisticsInterceptors() ?? [],
userFunction: self.containerStatistics(request:context:)
)
case "ProxyVsock":
return UnaryServerHandler(
context: context,
@@ -2142,15 +2151,6 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider {
userFunction: self.configureHosts(request:context:)
)
case "InterfaceStatistics":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest>(),
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>(),
interceptors: self.interceptors?.makeInterfaceStatisticsInterceptors() ?? [],
userFunction: self.interfaceStatistics(request:context:)
)
case "Sync":
return UnaryServerHandler(
context: context,
@@ -2280,6 +2280,12 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvide
context: GRPCAsyncServerCallContext
) async throws -> Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse
/// Get statistics for containers.
func containerStatistics(
request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
context: GRPCAsyncServerCallContext
) async throws -> Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse
/// Proxy a vsock port to a unix domain socket in the guest, or vice versa.
func proxyVsock(
request: Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest,
@@ -2328,12 +2334,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvide
context: GRPCAsyncServerCallContext
) async throws -> Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse
/// Get statistics about an interface.
func interfaceStatistics(
request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
context: GRPCAsyncServerCallContext
) async throws -> Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse
/// Perform the sync syscall.
func sync(
request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
@@ -2510,6 +2510,15 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvider {
wrapping: { try await self.closeProcessStdin(request: $0, context: $1) }
)
case "ContainerStatistics":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest>(),
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>(),
interceptors: self.interceptors?.makeContainerStatisticsInterceptors() ?? [],
wrapping: { try await self.containerStatistics(request: $0, context: $1) }
)
case "ProxyVsock":
return GRPCAsyncServerHandler(
context: context,
@@ -2582,15 +2591,6 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvider {
wrapping: { try await self.configureHosts(request: $0, context: $1) }
)
case "InterfaceStatistics":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest>(),
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>(),
interceptors: self.interceptors?.makeInterfaceStatisticsInterceptors() ?? [],
wrapping: { try await self.interfaceStatistics(request: $0, context: $1) }
)
case "Sync":
return GRPCAsyncServerHandler(
context: context,
@@ -2681,6 +2681,10 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextServerInterc
/// Defaults to calling `self.makeInterceptors()`.
func makeCloseProcessStdinInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinRequest, Com_Apple_Containerization_Sandbox_V3_CloseProcessStdinResponse>]
/// - Returns: Interceptors to use when handling 'containerStatistics'.
/// Defaults to calling `self.makeInterceptors()`.
func makeContainerStatisticsInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse>]
/// - Returns: Interceptors to use when handling 'proxyVsock'.
/// Defaults to calling `self.makeInterceptors()`.
func makeProxyVsockInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_ProxyVsockRequest, Com_Apple_Containerization_Sandbox_V3_ProxyVsockResponse>]
@@ -2713,10 +2717,6 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextServerInterc
/// Defaults to calling `self.makeInterceptors()`.
func makeConfigureHostsInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_ConfigureHostsRequest, Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse>]
/// - Returns: Interceptors to use when handling 'interfaceStatistics'.
/// Defaults to calling `self.makeInterceptors()`.
func makeInterfaceStatisticsInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse>]
/// - Returns: Interceptors to use when handling 'sync'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSyncInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_SyncRequest, Com_Apple_Containerization_Sandbox_V3_SyncResponse>]
@@ -2747,6 +2747,7 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.waitProcess,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.resizeProcess,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.closeProcessStdin,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.containerStatistics,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.proxyVsock,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.stopVsockProxy,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.ipLinkSet,
@@ -2755,7 +2756,6 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.ipRouteAddDefault,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.configureDns,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.configureHosts,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.interfaceStatistics,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.sync,
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.kill,
]
@@ -2858,6 +2858,12 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
type: GRPCCallType.unary
)
public static let containerStatistics = GRPCMethodDescriptor(
name: "ContainerStatistics",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/ContainerStatistics",
type: GRPCCallType.unary
)
public static let proxyVsock = GRPCMethodDescriptor(
name: "ProxyVsock",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/ProxyVsock",
@@ -2906,12 +2912,6 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
type: GRPCCallType.unary
)
public static let interfaceStatistics = GRPCMethodDescriptor(
name: "InterfaceStatistics",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/InterfaceStatistics",
type: GRPCCallType.unary
)
public static let sync = GRPCMethodDescriptor(
name: "Sync",
path: "/com.apple.containerization.sandbox.v3.SandboxContext/Sync",
@@ -954,89 +954,6 @@ public struct Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse: Send
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var interface: String = String()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var receivedPackets: UInt64 {
get {return _receivedPackets ?? 0}
set {_receivedPackets = newValue}
}
/// Returns true if `receivedPackets` has been explicitly set.
public var hasReceivedPackets: Bool {return self._receivedPackets != nil}
/// Clears the value of `receivedPackets`. Subsequent reads from it will return its default value.
public mutating func clearReceivedPackets() {self._receivedPackets = nil}
public var transmittedPackets: UInt64 {
get {return _transmittedPackets ?? 0}
set {_transmittedPackets = newValue}
}
/// Returns true if `transmittedPackets` has been explicitly set.
public var hasTransmittedPackets: Bool {return self._transmittedPackets != nil}
/// Clears the value of `transmittedPackets`. Subsequent reads from it will return its default value.
public mutating func clearTransmittedPackets() {self._transmittedPackets = nil}
public var receivedBytes: UInt64 {
get {return _receivedBytes ?? 0}
set {_receivedBytes = newValue}
}
/// Returns true if `receivedBytes` has been explicitly set.
public var hasReceivedBytes: Bool {return self._receivedBytes != nil}
/// Clears the value of `receivedBytes`. Subsequent reads from it will return its default value.
public mutating func clearReceivedBytes() {self._receivedBytes = nil}
public var transmittedBytes: UInt64 {
get {return _transmittedBytes ?? 0}
set {_transmittedBytes = newValue}
}
/// Returns true if `transmittedBytes` has been explicitly set.
public var hasTransmittedBytes: Bool {return self._transmittedBytes != nil}
/// Clears the value of `transmittedBytes`. Subsequent reads from it will return its default value.
public mutating func clearTransmittedBytes() {self._transmittedBytes = nil}
public var receivedErrors: UInt64 {
get {return _receivedErrors ?? 0}
set {_receivedErrors = newValue}
}
/// Returns true if `receivedErrors` has been explicitly set.
public var hasReceivedErrors: Bool {return self._receivedErrors != nil}
/// Clears the value of `receivedErrors`. Subsequent reads from it will return its default value.
public mutating func clearReceivedErrors() {self._receivedErrors = nil}
public var transmittedErrors: UInt64 {
get {return _transmittedErrors ?? 0}
set {_transmittedErrors = newValue}
}
/// Returns true if `transmittedErrors` has been explicitly set.
public var hasTransmittedErrors: Bool {return self._transmittedErrors != nil}
/// Clears the value of `transmittedErrors`. Subsequent reads from it will return its default value.
public mutating func clearTransmittedErrors() {self._transmittedErrors = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _receivedPackets: UInt64? = nil
fileprivate var _transmittedPackets: UInt64? = nil
fileprivate var _receivedBytes: UInt64? = nil
fileprivate var _transmittedBytes: UInt64? = nil
fileprivate var _receivedErrors: UInt64? = nil
fileprivate var _transmittedErrors: UInt64? = nil
}
public struct Com_Apple_Containerization_Sandbox_V3_SyncRequest: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
@@ -1083,6 +1000,212 @@ public struct Com_Apple_Containerization_Sandbox_V3_KillResponse: Sendable {
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Empty = all containers
public var containerIds: [String] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var containers: [Com_Apple_Containerization_Sandbox_V3_ContainerStats] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_ContainerStats: @unchecked Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var containerID: String {
get {return _storage._containerID}
set {_uniqueStorage()._containerID = newValue}
}
public var process: Com_Apple_Containerization_Sandbox_V3_ProcessStats {
get {return _storage._process ?? Com_Apple_Containerization_Sandbox_V3_ProcessStats()}
set {_uniqueStorage()._process = newValue}
}
/// Returns true if `process` has been explicitly set.
public var hasProcess: Bool {return _storage._process != nil}
/// Clears the value of `process`. Subsequent reads from it will return its default value.
public mutating func clearProcess() {_uniqueStorage()._process = nil}
public var memory: Com_Apple_Containerization_Sandbox_V3_MemoryStats {
get {return _storage._memory ?? Com_Apple_Containerization_Sandbox_V3_MemoryStats()}
set {_uniqueStorage()._memory = newValue}
}
/// Returns true if `memory` has been explicitly set.
public var hasMemory: Bool {return _storage._memory != nil}
/// Clears the value of `memory`. Subsequent reads from it will return its default value.
public mutating func clearMemory() {_uniqueStorage()._memory = nil}
public var cpu: Com_Apple_Containerization_Sandbox_V3_CPUStats {
get {return _storage._cpu ?? Com_Apple_Containerization_Sandbox_V3_CPUStats()}
set {_uniqueStorage()._cpu = newValue}
}
/// Returns true if `cpu` has been explicitly set.
public var hasCpu: Bool {return _storage._cpu != nil}
/// Clears the value of `cpu`. Subsequent reads from it will return its default value.
public mutating func clearCpu() {_uniqueStorage()._cpu = nil}
public var blockIo: Com_Apple_Containerization_Sandbox_V3_BlockIOStats {
get {return _storage._blockIo ?? Com_Apple_Containerization_Sandbox_V3_BlockIOStats()}
set {_uniqueStorage()._blockIo = newValue}
}
/// Returns true if `blockIo` has been explicitly set.
public var hasBlockIo: Bool {return _storage._blockIo != nil}
/// Clears the value of `blockIo`. Subsequent reads from it will return its default value.
public mutating func clearBlockIo() {_uniqueStorage()._blockIo = nil}
public var networks: [Com_Apple_Containerization_Sandbox_V3_NetworkStats] {
get {return _storage._networks}
set {_uniqueStorage()._networks = newValue}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _storage = _StorageClass.defaultInstance
}
public struct Com_Apple_Containerization_Sandbox_V3_ProcessStats: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var current: UInt64 = 0
/// 0 or max value = unlimited
public var limit: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_MemoryStats: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var usageBytes: UInt64 = 0
public var limitBytes: UInt64 = 0
public var swapUsageBytes: UInt64 = 0
public var swapLimitBytes: UInt64 = 0
public var cacheBytes: UInt64 = 0
public var kernelStackBytes: UInt64 = 0
public var slabBytes: UInt64 = 0
public var pageFaults: UInt64 = 0
public var majorPageFaults: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_CPUStats: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var usageUsec: UInt64 = 0
public var userUsec: UInt64 = 0
public var systemUsec: UInt64 = 0
public var throttlingPeriods: UInt64 = 0
public var throttledPeriods: UInt64 = 0
public var throttledTimeUsec: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_BlockIOStats: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var devices: [Com_Apple_Containerization_Sandbox_V3_BlockIOEntry] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_BlockIOEntry: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var major: UInt64 = 0
public var minor: UInt64 = 0
public var readBytes: UInt64 = 0
public var writeBytes: UInt64 = 0
public var readOperations: UInt64 = 0
public var writeOperations: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public struct Com_Apple_Containerization_Sandbox_V3_NetworkStats: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var interface: String = String()
public var receivedPackets: UInt64 = 0
public var transmittedPackets: UInt64 = 0
public var receivedBytes: UInt64 = 0
public var transmittedBytes: UInt64 = 0
public var receivedErrors: UInt64 = 0
public var transmittedErrors: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "com.apple.containerization.sandbox.v3"
@@ -2864,104 +2987,6 @@ extension Com_Apple_Containerization_Sandbox_V3_ConfigureHostsResponse: SwiftPro
}
}
extension Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".InterfaceStatisticsRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "interface"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.interface) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.interface.isEmpty {
try visitor.visitSingularStringField(value: self.interface, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest, rhs: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest) -> Bool {
if lhs.interface != rhs.interface {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".InterfaceStatisticsResponse"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "receivedPackets"),
2: .same(proto: "transmittedPackets"),
3: .same(proto: "receivedBytes"),
4: .same(proto: "transmittedBytes"),
5: .same(proto: "receivedErrors"),
6: .same(proto: "transmittedErrors"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularUInt64Field(value: &self._receivedPackets) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self._transmittedPackets) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self._receivedBytes) }()
case 4: try { try decoder.decodeSingularUInt64Field(value: &self._transmittedBytes) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self._receivedErrors) }()
case 6: try { try decoder.decodeSingularUInt64Field(value: &self._transmittedErrors) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = self._receivedPackets {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
} }()
try { if let v = self._transmittedPackets {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 2)
} }()
try { if let v = self._receivedBytes {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 3)
} }()
try { if let v = self._transmittedBytes {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 4)
} }()
try { if let v = self._receivedErrors {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 5)
} }()
try { if let v = self._transmittedErrors {
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 6)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse, rhs: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse) -> Bool {
if lhs._receivedPackets != rhs._receivedPackets {return false}
if lhs._transmittedPackets != rhs._transmittedPackets {return false}
if lhs._receivedBytes != rhs._receivedBytes {return false}
if lhs._transmittedBytes != rhs._transmittedBytes {return false}
if lhs._receivedErrors != rhs._receivedErrors {return false}
if lhs._transmittedErrors != rhs._transmittedErrors {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_SyncRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SyncRequest"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
@@ -3069,3 +3094,521 @@ extension Com_Apple_Containerization_Sandbox_V3_KillResponse: SwiftProtobuf.Mess
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContainerStatisticsRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "container_ids"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedStringField(value: &self.containerIds) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.containerIds.isEmpty {
try visitor.visitRepeatedStringField(value: self.containerIds, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest, rhs: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest) -> Bool {
if lhs.containerIds != rhs.containerIds {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContainerStatisticsResponse"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "containers"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.containers) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.containers.isEmpty {
try visitor.visitRepeatedMessageField(value: self.containers, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse, rhs: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse) -> Bool {
if lhs.containers != rhs.containers {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_ContainerStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContainerStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "container_id"),
2: .same(proto: "process"),
3: .same(proto: "memory"),
4: .same(proto: "cpu"),
5: .standard(proto: "block_io"),
6: .same(proto: "networks"),
]
fileprivate class _StorageClass {
var _containerID: String = String()
var _process: Com_Apple_Containerization_Sandbox_V3_ProcessStats? = nil
var _memory: Com_Apple_Containerization_Sandbox_V3_MemoryStats? = nil
var _cpu: Com_Apple_Containerization_Sandbox_V3_CPUStats? = nil
var _blockIo: Com_Apple_Containerization_Sandbox_V3_BlockIOStats? = nil
var _networks: [Com_Apple_Containerization_Sandbox_V3_NetworkStats] = []
// This property is used as the initial default value for new instances of the type.
// The type itself is protecting the reference to its storage via CoW semantics.
// This will force a copy to be made of this reference when the first mutation occurs;
// hence, it is safe to mark this as `nonisolated(unsafe)`.
static nonisolated(unsafe) let defaultInstance = _StorageClass()
private init() {}
init(copying source: _StorageClass) {
_containerID = source._containerID
_process = source._process
_memory = source._memory
_cpu = source._cpu
_blockIo = source._blockIo
_networks = source._networks
}
}
fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &_storage._containerID) }()
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._process) }()
case 3: try { try decoder.decodeSingularMessageField(value: &_storage._memory) }()
case 4: try { try decoder.decodeSingularMessageField(value: &_storage._cpu) }()
case 5: try { try decoder.decodeSingularMessageField(value: &_storage._blockIo) }()
case 6: try { try decoder.decodeRepeatedMessageField(value: &_storage._networks) }()
default: break
}
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
if !_storage._containerID.isEmpty {
try visitor.visitSingularStringField(value: _storage._containerID, fieldNumber: 1)
}
try { if let v = _storage._process {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if let v = _storage._memory {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try { if let v = _storage._cpu {
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
} }()
try { if let v = _storage._blockIo {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
} }()
if !_storage._networks.isEmpty {
try visitor.visitRepeatedMessageField(value: _storage._networks, fieldNumber: 6)
}
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_ContainerStats, rhs: Com_Apple_Containerization_Sandbox_V3_ContainerStats) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._containerID != rhs_storage._containerID {return false}
if _storage._process != rhs_storage._process {return false}
if _storage._memory != rhs_storage._memory {return false}
if _storage._cpu != rhs_storage._cpu {return false}
if _storage._blockIo != rhs_storage._blockIo {return false}
if _storage._networks != rhs_storage._networks {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_ProcessStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ProcessStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "current"),
2: .same(proto: "limit"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularUInt64Field(value: &self.current) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.limit) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.current != 0 {
try visitor.visitSingularUInt64Field(value: self.current, fieldNumber: 1)
}
if self.limit != 0 {
try visitor.visitSingularUInt64Field(value: self.limit, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_ProcessStats, rhs: Com_Apple_Containerization_Sandbox_V3_ProcessStats) -> Bool {
if lhs.current != rhs.current {return false}
if lhs.limit != rhs.limit {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_MemoryStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".MemoryStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "usage_bytes"),
2: .standard(proto: "limit_bytes"),
3: .standard(proto: "swap_usage_bytes"),
4: .standard(proto: "swap_limit_bytes"),
5: .standard(proto: "cache_bytes"),
6: .standard(proto: "kernel_stack_bytes"),
7: .standard(proto: "slab_bytes"),
8: .standard(proto: "page_faults"),
9: .standard(proto: "major_page_faults"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularUInt64Field(value: &self.usageBytes) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.limitBytes) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.swapUsageBytes) }()
case 4: try { try decoder.decodeSingularUInt64Field(value: &self.swapLimitBytes) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.cacheBytes) }()
case 6: try { try decoder.decodeSingularUInt64Field(value: &self.kernelStackBytes) }()
case 7: try { try decoder.decodeSingularUInt64Field(value: &self.slabBytes) }()
case 8: try { try decoder.decodeSingularUInt64Field(value: &self.pageFaults) }()
case 9: try { try decoder.decodeSingularUInt64Field(value: &self.majorPageFaults) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.usageBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.usageBytes, fieldNumber: 1)
}
if self.limitBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.limitBytes, fieldNumber: 2)
}
if self.swapUsageBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.swapUsageBytes, fieldNumber: 3)
}
if self.swapLimitBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.swapLimitBytes, fieldNumber: 4)
}
if self.cacheBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.cacheBytes, fieldNumber: 5)
}
if self.kernelStackBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.kernelStackBytes, fieldNumber: 6)
}
if self.slabBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.slabBytes, fieldNumber: 7)
}
if self.pageFaults != 0 {
try visitor.visitSingularUInt64Field(value: self.pageFaults, fieldNumber: 8)
}
if self.majorPageFaults != 0 {
try visitor.visitSingularUInt64Field(value: self.majorPageFaults, fieldNumber: 9)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_MemoryStats, rhs: Com_Apple_Containerization_Sandbox_V3_MemoryStats) -> Bool {
if lhs.usageBytes != rhs.usageBytes {return false}
if lhs.limitBytes != rhs.limitBytes {return false}
if lhs.swapUsageBytes != rhs.swapUsageBytes {return false}
if lhs.swapLimitBytes != rhs.swapLimitBytes {return false}
if lhs.cacheBytes != rhs.cacheBytes {return false}
if lhs.kernelStackBytes != rhs.kernelStackBytes {return false}
if lhs.slabBytes != rhs.slabBytes {return false}
if lhs.pageFaults != rhs.pageFaults {return false}
if lhs.majorPageFaults != rhs.majorPageFaults {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_CPUStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".CPUStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "usage_usec"),
2: .standard(proto: "user_usec"),
3: .standard(proto: "system_usec"),
4: .standard(proto: "throttling_periods"),
5: .standard(proto: "throttled_periods"),
6: .standard(proto: "throttled_time_usec"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularUInt64Field(value: &self.usageUsec) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.userUsec) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.systemUsec) }()
case 4: try { try decoder.decodeSingularUInt64Field(value: &self.throttlingPeriods) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.throttledPeriods) }()
case 6: try { try decoder.decodeSingularUInt64Field(value: &self.throttledTimeUsec) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.usageUsec != 0 {
try visitor.visitSingularUInt64Field(value: self.usageUsec, fieldNumber: 1)
}
if self.userUsec != 0 {
try visitor.visitSingularUInt64Field(value: self.userUsec, fieldNumber: 2)
}
if self.systemUsec != 0 {
try visitor.visitSingularUInt64Field(value: self.systemUsec, fieldNumber: 3)
}
if self.throttlingPeriods != 0 {
try visitor.visitSingularUInt64Field(value: self.throttlingPeriods, fieldNumber: 4)
}
if self.throttledPeriods != 0 {
try visitor.visitSingularUInt64Field(value: self.throttledPeriods, fieldNumber: 5)
}
if self.throttledTimeUsec != 0 {
try visitor.visitSingularUInt64Field(value: self.throttledTimeUsec, fieldNumber: 6)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_CPUStats, rhs: Com_Apple_Containerization_Sandbox_V3_CPUStats) -> Bool {
if lhs.usageUsec != rhs.usageUsec {return false}
if lhs.userUsec != rhs.userUsec {return false}
if lhs.systemUsec != rhs.systemUsec {return false}
if lhs.throttlingPeriods != rhs.throttlingPeriods {return false}
if lhs.throttledPeriods != rhs.throttledPeriods {return false}
if lhs.throttledTimeUsec != rhs.throttledTimeUsec {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_BlockIOStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".BlockIOStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "devices"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.devices) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.devices.isEmpty {
try visitor.visitRepeatedMessageField(value: self.devices, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_BlockIOStats, rhs: Com_Apple_Containerization_Sandbox_V3_BlockIOStats) -> Bool {
if lhs.devices != rhs.devices {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_BlockIOEntry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".BlockIOEntry"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "major"),
2: .same(proto: "minor"),
3: .standard(proto: "read_bytes"),
4: .standard(proto: "write_bytes"),
5: .standard(proto: "read_operations"),
6: .standard(proto: "write_operations"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularUInt64Field(value: &self.major) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.minor) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.readBytes) }()
case 4: try { try decoder.decodeSingularUInt64Field(value: &self.writeBytes) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.readOperations) }()
case 6: try { try decoder.decodeSingularUInt64Field(value: &self.writeOperations) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.major != 0 {
try visitor.visitSingularUInt64Field(value: self.major, fieldNumber: 1)
}
if self.minor != 0 {
try visitor.visitSingularUInt64Field(value: self.minor, fieldNumber: 2)
}
if self.readBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.readBytes, fieldNumber: 3)
}
if self.writeBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.writeBytes, fieldNumber: 4)
}
if self.readOperations != 0 {
try visitor.visitSingularUInt64Field(value: self.readOperations, fieldNumber: 5)
}
if self.writeOperations != 0 {
try visitor.visitSingularUInt64Field(value: self.writeOperations, fieldNumber: 6)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_BlockIOEntry, rhs: Com_Apple_Containerization_Sandbox_V3_BlockIOEntry) -> Bool {
if lhs.major != rhs.major {return false}
if lhs.minor != rhs.minor {return false}
if lhs.readBytes != rhs.readBytes {return false}
if lhs.writeBytes != rhs.writeBytes {return false}
if lhs.readOperations != rhs.readOperations {return false}
if lhs.writeOperations != rhs.writeOperations {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Com_Apple_Containerization_Sandbox_V3_NetworkStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".NetworkStats"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "interface"),
2: .same(proto: "receivedPackets"),
3: .same(proto: "transmittedPackets"),
4: .same(proto: "receivedBytes"),
5: .same(proto: "transmittedBytes"),
6: .same(proto: "receivedErrors"),
7: .same(proto: "transmittedErrors"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.interface) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.receivedPackets) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.transmittedPackets) }()
case 4: try { try decoder.decodeSingularUInt64Field(value: &self.receivedBytes) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.transmittedBytes) }()
case 6: try { try decoder.decodeSingularUInt64Field(value: &self.receivedErrors) }()
case 7: try { try decoder.decodeSingularUInt64Field(value: &self.transmittedErrors) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.interface.isEmpty {
try visitor.visitSingularStringField(value: self.interface, fieldNumber: 1)
}
if self.receivedPackets != 0 {
try visitor.visitSingularUInt64Field(value: self.receivedPackets, fieldNumber: 2)
}
if self.transmittedPackets != 0 {
try visitor.visitSingularUInt64Field(value: self.transmittedPackets, fieldNumber: 3)
}
if self.receivedBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.receivedBytes, fieldNumber: 4)
}
if self.transmittedBytes != 0 {
try visitor.visitSingularUInt64Field(value: self.transmittedBytes, fieldNumber: 5)
}
if self.receivedErrors != 0 {
try visitor.visitSingularUInt64Field(value: self.receivedErrors, fieldNumber: 6)
}
if self.transmittedErrors != 0 {
try visitor.visitSingularUInt64Field(value: self.transmittedErrors, fieldNumber: 7)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Com_Apple_Containerization_Sandbox_V3_NetworkStats, rhs: Com_Apple_Containerization_Sandbox_V3_NetworkStats) -> Bool {
if lhs.interface != rhs.interface {return false}
if lhs.receivedPackets != rhs.receivedPackets {return false}
if lhs.transmittedPackets != rhs.transmittedPackets {return false}
if lhs.receivedBytes != rhs.receivedBytes {return false}
if lhs.transmittedBytes != rhs.transmittedBytes {return false}
if lhs.receivedErrors != rhs.receivedErrors {return false}
if lhs.transmittedErrors != rhs.transmittedErrors {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
@@ -41,6 +41,9 @@ service SandboxContext {
// Close IO for a given process.
rpc CloseProcessStdin(CloseProcessStdinRequest) returns (CloseProcessStdinResponse);
// Get statistics for containers.
rpc ContainerStatistics(ContainerStatisticsRequest) returns (ContainerStatisticsResponse);
// Proxy a vsock port to a unix domain socket in the guest, or vice versa.
rpc ProxyVsock(ProxyVsockRequest) returns (ProxyVsockResponse);
// Stop a vsock proxy to a unix domain socket.
@@ -58,8 +61,6 @@ service SandboxContext {
rpc ConfigureDns(ConfigureDnsRequest) returns (ConfigureDnsResponse);
// Configure /etc/hosts.
rpc ConfigureHosts(ConfigureHostsRequest) returns (ConfigureHostsResponse);
// Get statistics about an interface.
rpc InterfaceStatistics(InterfaceStatisticsRequest) returns (InterfaceStatisticsResponse);
// Perform the sync syscall.
rpc Sync(SyncRequest) returns (SyncResponse);
@@ -276,19 +277,6 @@ message ConfigureHostsRequest {
message ConfigureHostsResponse {}
message InterfaceStatisticsRequest {
string interface = 1;
}
message InterfaceStatisticsResponse {
optional uint64 receivedPackets = 1;
optional uint64 transmittedPackets = 2;
optional uint64 receivedBytes = 3;
optional uint64 transmittedBytes = 4;
optional uint64 receivedErrors = 5;
optional uint64 transmittedErrors = 6;
}
message SyncRequest {}
message SyncResponse {}
@@ -298,3 +286,69 @@ message KillRequest {
}
message KillResponse { int32 result = 1; }
message ContainerStatisticsRequest {
repeated string container_ids = 1; // Empty = all containers
}
message ContainerStatisticsResponse {
repeated ContainerStats containers = 1;
}
message ContainerStats {
string container_id = 1;
ProcessStats process = 2;
MemoryStats memory = 3;
CPUStats cpu = 4;
BlockIOStats block_io = 5;
repeated NetworkStats networks = 6;
}
message ProcessStats {
uint64 current = 1;
uint64 limit = 2; // 0 or max value = unlimited
}
message MemoryStats {
uint64 usage_bytes = 1;
uint64 limit_bytes = 2;
uint64 swap_usage_bytes = 3;
uint64 swap_limit_bytes = 4;
uint64 cache_bytes = 5;
uint64 kernel_stack_bytes = 6;
uint64 slab_bytes = 7;
uint64 page_faults = 8;
uint64 major_page_faults = 9;
}
message CPUStats {
uint64 usage_usec = 1;
uint64 user_usec = 2;
uint64 system_usec = 3;
uint64 throttling_periods = 4;
uint64 throttled_periods = 5;
uint64 throttled_time_usec = 6;
}
message BlockIOStats {
repeated BlockIOEntry devices = 1;
}
message BlockIOEntry {
uint64 major = 1;
uint64 minor = 2;
uint64 read_bytes = 3;
uint64 write_bytes = 4;
uint64 read_operations = 5;
uint64 write_operations = 6;
}
message NetworkStats {
string interface = 1;
uint64 receivedPackets = 2;
uint64 transmittedPackets = 3;
uint64 receivedBytes = 4;
uint64 transmittedBytes = 5;
uint64 receivedErrors = 6;
uint64 transmittedErrors = 7;
}
@@ -68,7 +68,9 @@ public protocol VirtualMachineAgent: Sendable {
func routeAddDefault(name: String, gateway: String) async throws
func configureDNS(config: DNS, location: String) async throws
func configureHosts(config: Hosts, location: String) async throws
func interfaceStatistics(name: String) async throws -> InterfaceStatistics
// Container statistics
func containerStatistics(containerIDs: [String]) async throws -> [ContainerStatistics]
}
extension VirtualMachineAgent {
@@ -84,7 +86,7 @@ extension VirtualMachineAgent {
throw ContainerizationError(.unsupported, message: "writeFile")
}
public func interfaceStatistics(name: String) async throws -> InterfaceStatistics {
throw ContainerizationError(.unsupported, message: "interfaceStatistics")
public func containerStatistics(containerIDs: [String]) async throws -> [ContainerStatistics] {
throw ContainerizationError(.unsupported, message: "containerStatistics")
}
}
+57 -13
View File
@@ -89,21 +89,65 @@ extension Vminitd: VirtualMachineAgent {
})
}
/// Get statistics about an interface.
public func interfaceStatistics(name: String) async throws -> InterfaceStatistics {
let stats = try await client.interfaceStatistics(
/// Get statistics for containers. If `containerIDs` is empty returns stats for all containers
/// in the guest.
public func containerStatistics(containerIDs: [String]) async throws -> [ContainerStatistics] {
let response = try await client.containerStatistics(
.with {
$0.interface = name
$0.containerIds = containerIDs
})
return InterfaceStatistics(
name: name,
receivedPackets: stats.hasReceivedPackets ? stats.receivedPackets : nil,
transmittedPackets: stats.hasTransmittedPackets ? stats.transmittedPackets : nil,
receivedBytes: stats.hasReceivedBytes ? stats.receivedBytes : nil,
transmittedBytes: stats.hasTransmittedBytes ? stats.transmittedBytes : nil,
receivedErrors: stats.hasReceivedErrors ? stats.receivedErrors : nil,
transmittedErrors: stats.hasTransmittedErrors ? stats.transmittedErrors : nil
)
return response.containers.map { protoStats in
ContainerStatistics(
id: protoStats.containerID,
process: .init(
current: protoStats.process.current,
limit: protoStats.process.limit
),
memory: .init(
usageBytes: protoStats.memory.usageBytes,
limitBytes: protoStats.memory.limitBytes,
swapUsageBytes: protoStats.memory.swapUsageBytes,
swapLimitBytes: protoStats.memory.swapLimitBytes,
cacheBytes: protoStats.memory.cacheBytes,
kernelStackBytes: protoStats.memory.kernelStackBytes,
slabBytes: protoStats.memory.slabBytes,
pageFaults: protoStats.memory.pageFaults,
majorPageFaults: protoStats.memory.majorPageFaults
),
cpu: .init(
usageUsec: protoStats.cpu.usageUsec,
userUsec: protoStats.cpu.userUsec,
systemUsec: protoStats.cpu.systemUsec,
throttlingPeriods: protoStats.cpu.throttlingPeriods,
throttledPeriods: protoStats.cpu.throttledPeriods,
throttledTimeUsec: protoStats.cpu.throttledTimeUsec
),
blockIO: .init(
devices: protoStats.blockIo.devices.map { device in
.init(
major: device.major,
minor: device.minor,
readBytes: device.readBytes,
writeBytes: device.writeBytes,
readOperations: device.readOperations,
writeOperations: device.writeOperations
)
}
),
networks: protoStats.networks.map { network in
ContainerStatistics.NetworkStatistics(
interface: network.interface,
receivedPackets: network.receivedPackets,
transmittedPackets: network.transmittedPackets,
receivedBytes: network.receivedBytes,
transmittedBytes: network.transmittedBytes,
receivedErrors: network.receivedErrors,
transmittedErrors: network.transmittedErrors
)
}
)
}
}
/// Mount a filesystem in the sandbox's environment.
+1
View File
@@ -216,6 +216,7 @@ struct IntegrationSuite: AsyncParsableCommand {
"container manager": testContainerManagerCreate,
"container reuse": testContainerReuse,
"container /dev/console": testContainerDevConsole,
"container statistics": testContainerStatistics,
]
var passed = 0
+43
View File
@@ -206,6 +206,49 @@ extension IntegrationSuite {
}
}
func testContainerStatistics() async throws {
let id = "test-container-statistics"
let bs = try await bootstrap()
let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in
config.process.arguments = ["sleep", "infinity"]
}
do {
try await container.create()
try await container.start()
let stats = try await container.statistics()
guard stats.id == id else {
throw IntegrationError.assert(msg: "stats container ID '\(stats.id)' != '\(id)'")
}
guard stats.process.current > 0 else {
throw IntegrationError.assert(msg: "process count should be > 0, got \(stats.process.current)")
}
guard stats.memory.usageBytes > 0 else {
throw IntegrationError.assert(msg: "memory usage should be > 0, got \(stats.memory.usageBytes)")
}
guard stats.cpu.usageUsec > 0 else {
throw IntegrationError.assert(msg: "CPU usage should be > 0, got \(stats.cpu.usageUsec)")
}
print("Container statistics:")
print(" Processes: \(stats.process.current)")
print(" Memory: \(stats.memory.usageBytes) bytes")
print(" CPU: \(stats.cpu.usageUsec) usec")
print(" Networks: \(stats.networks.count) interfaces")
try await container.stop()
} catch {
try? await container.stop()
throw error
}
}
func testContainerStopIdempotency() async throws {
let id = "test-container-stop-idempotency"
@@ -223,6 +223,9 @@ struct Cgroup2Manager: Sendable {
private func parseSingleValue(_ content: String?) -> UInt64? {
guard let content = content, !content.isEmpty else { return nil }
if content == "max" {
return UInt64.max
}
return UInt64(content)
}
@@ -159,6 +159,10 @@ extension ManagedContainer {
try self.cgroupManager.delete(force: true)
}
func stats() throws -> Cgroup2Stats {
try self.cgroupManager.stats()
}
func getExecOrInit(execID: String) throws -> ManagedProcess {
if execID == self.id {
return self.initProcess
+117 -24
View File
@@ -907,44 +907,68 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid
return .init()
}
func interfaceStatistics(
request: Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsRequest,
func containerStatistics(
request: Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsRequest,
context: GRPC.GRPCAsyncServerCallContext
) async throws -> Com_Apple_Containerization_Sandbox_V3_InterfaceStatisticsResponse {
) async throws -> Com_Apple_Containerization_Sandbox_V3_ContainerStatisticsResponse {
log.debug(
"interfaceStatistics",
"containerStatistics",
metadata: [
"name": "\(request.interface)"
"container_ids": "\(request.containerIds)"
])
do {
let socket = try DefaultNetlinkSocket()
let session = NetlinkSession(socket: socket, log: log)
let responses = try session.linkGet(interface: request.interface, includeStats: true)
guard responses.count == 1 else {
throw ContainerizationError(
.internalError,
message: "linkGet returned invalid number of interfaces: \(responses.count)"
)
// Get all network interfaces (skip loopback)
let interfaces = try getNetworkInterfaces()
// Get containers to query
let containerIDs: [String]
if request.containerIds.isEmpty {
containerIDs = await Array(state.containers.keys)
} else {
containerIDs = request.containerIds
}
let stats = try responses[0].getStatistics()
return .with {
if let stats {
$0.receivedPackets = stats.rxPackets
$0.transmittedPackets = stats.txPackets
$0.receivedBytes = stats.rxBytes
$0.transmittedBytes = stats.txBytes
$0.receivedErrors = stats.rxErrors
$0.transmittedErrors = stats.txErrors
var containerStats: [Com_Apple_Containerization_Sandbox_V3_ContainerStats] = []
for containerID in containerIDs {
let container = try await state.get(container: containerID)
let cgStats = try await container.stats()
// Get network stats for all interfaces
let socket = try DefaultNetlinkSocket()
let session = NetlinkSession(socket: socket, log: log)
var networkStats: [Com_Apple_Containerization_Sandbox_V3_NetworkStats] = []
for interface in interfaces {
let responses = try session.linkGet(interface: interface, includeStats: true)
if responses.count == 1, let stats = try responses[0].getStatistics() {
networkStats.append(
.with {
$0.interface = interface
$0.receivedPackets = stats.rxPackets
$0.transmittedPackets = stats.txPackets
$0.receivedBytes = stats.rxBytes
$0.transmittedBytes = stats.txBytes
$0.receivedErrors = stats.rxErrors
$0.transmittedErrors = stats.txErrors
})
}
}
containerStats.append(mapStatsToProto(containerID: containerID, cgStats: cgStats, networkStats: networkStats))
}
return .with {
$0.containers = containerStats
}
} catch {
log.error(
"interfaceStatistics",
"containerStatistics",
metadata: [
"error": "\(error)"
])
throw GRPCStatus(code: .internalError, message: "interfaceStatistics: \(error)")
throw GRPCStatus(code: .internalError, message: "containerStatistics: \(error)")
}
}
@@ -958,6 +982,75 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid
return error
}
// NOTE: This is just crummy. It works because today the assumption is
// every NIC in the root net namespace is for the container(s), but if we
// ever supported individual containers having their own NICs/IPs then this
// logic needs to change. We only create ethernet devices today too, so that's
// what this filters for as well.
private func getNetworkInterfaces() throws -> [String] {
let netPath = URL(filePath: "/sys/class/net")
let interfaces = try FileManager.default.contentsOfDirectory(
at: netPath,
includingPropertiesForKeys: nil
)
return
interfaces
.map { $0.lastPathComponent }
.filter { $0.hasPrefix("eth") }
}
private func mapStatsToProto(
containerID: String,
cgStats: Cgroup2Stats,
networkStats: [Com_Apple_Containerization_Sandbox_V3_NetworkStats]
) -> Com_Apple_Containerization_Sandbox_V3_ContainerStats {
.with {
$0.containerID = containerID
$0.process = .with {
$0.current = cgStats.pids?.current ?? 0
$0.limit = cgStats.pids?.max ?? 0
}
$0.memory = .with {
$0.usageBytes = cgStats.memory?.usage ?? 0
$0.limitBytes = cgStats.memory?.usageLimit ?? 0
$0.swapUsageBytes = cgStats.memory?.swapUsage ?? 0
$0.swapLimitBytes = cgStats.memory?.swapLimit ?? 0
$0.cacheBytes = cgStats.memory?.file ?? 0
$0.kernelStackBytes = cgStats.memory?.kernelStack ?? 0
$0.slabBytes = cgStats.memory?.slab ?? 0
$0.pageFaults = cgStats.memory?.pgfault ?? 0
$0.majorPageFaults = cgStats.memory?.pgmajfault ?? 0
}
$0.cpu = .with {
$0.usageUsec = cgStats.cpu?.usageUsec ?? 0
$0.userUsec = cgStats.cpu?.userUsec ?? 0
$0.systemUsec = cgStats.cpu?.systemUsec ?? 0
$0.throttlingPeriods = cgStats.cpu?.nrPeriods ?? 0
$0.throttledPeriods = cgStats.cpu?.nrThrottled ?? 0
$0.throttledTimeUsec = cgStats.cpu?.throttledUsec ?? 0
}
$0.blockIo = .with {
$0.devices =
cgStats.io?.entries.map { entry in
.with {
$0.major = entry.major
$0.minor = entry.minor
$0.readBytes = entry.rbytes
$0.writeBytes = entry.wbytes
$0.readOperations = entry.rios
$0.writeOperations = entry.wios
}
} ?? []
}
$0.networks = networkStats
}
}
func sync(
request: Com_Apple_Containerization_Sandbox_V3_SyncRequest,
context: GRPC.GRPCAsyncServerCallContext