Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 60 additions & 10 deletions Sources/Containerization/ContainerStatistics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,29 @@
/// 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 var process: ProcessStatistics?
public var memory: MemoryStatistics?
public var cpu: CPUStatistics?
public var blockIO: BlockIOStatistics?
public var networks: [NetworkStatistics]?
public var memoryEvents: MemoryEventStatistics?

public init(
id: String,
process: ProcessStatistics,
memory: MemoryStatistics,
cpu: CPUStatistics,
blockIO: BlockIOStatistics,
networks: [NetworkStatistics]
process: ProcessStatistics? = nil,
memory: MemoryStatistics? = nil,
cpu: CPUStatistics? = nil,
blockIO: BlockIOStatistics? = nil,
networks: [NetworkStatistics]? = nil,
memoryEvents: MemoryEventStatistics? = nil
) {
self.id = id
self.process = process
self.memory = memory
self.cpu = cpu
self.blockIO = blockIO
self.networks = networks
self.memoryEvents = memoryEvents
}

/// Process statistics for a container.
Expand Down Expand Up @@ -174,4 +177,51 @@ public struct ContainerStatistics: Sendable {
self.transmittedErrors = transmittedErrors
}
}

/// Memory event counters from cgroup2's memory.events file.
public struct MemoryEventStatistics: Sendable {
/// Number of times the cgroup was reclaimed due to low memory.
public var low: UInt64
/// Number of times the cgroup exceeded its high memory limit.
public var high: UInt64
/// Number of times the cgroup hit its max memory limit.
public var max: UInt64
/// Number of times the cgroup triggered OOM.
public var oom: UInt64
/// Number of processes killed by OOM killer.
public var oomKill: UInt64

public init(low: UInt64, high: UInt64, max: UInt64, oom: UInt64, oomKill: UInt64) {
self.low = low
self.high = high
self.max = max
self.oom = oom
self.oomKill = oomKill
}
}
}

/// Categories of statistics that can be requested.
public struct StatCategory: OptionSet, Sendable {
public let rawValue: Int

public init(rawValue: Int) {
self.rawValue = rawValue
}

/// Process statistics (pids.current, pids.max).
public static let process = StatCategory(rawValue: 1 << 0)
/// Memory usage statistics.
public static let memory = StatCategory(rawValue: 1 << 1)
/// CPU usage statistics.
public static let cpu = StatCategory(rawValue: 1 << 2)
/// Block I/O statistics.
public static let blockIO = StatCategory(rawValue: 1 << 3)
/// Network interface statistics.
public static let network = StatCategory(rawValue: 1 << 4)
/// Memory event counters (OOM kills, pressure events, etc.).
public static let memoryEvents = StatCategory(rawValue: 1 << 5)

/// All available statistics categories.
public static let all: StatCategory = [.process, .memory, .cpu, .blockIO, .network, .memoryEvents]
}
4 changes: 2 additions & 2 deletions Sources/Containerization/LinuxContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -778,12 +778,12 @@ extension LinuxContainer {
}

/// Get statistics for the container.
public func statistics() async throws -> ContainerStatistics {
public func statistics(categories: StatCategory = .all) async throws -> ContainerStatistics {
try await self.state.withLock {
let state = try $0.startedState("statistics")

let stats = try await state.vm.withAgent { agent in
let allStats = try await agent.containerStatistics(containerIDs: [self.id])
let allStats = try await agent.containerStatistics(containerIDs: [self.id], categories: categories)
guard let containerStats = allStats.first else {
throw ContainerizationError(
.notFound,
Expand Down
4 changes: 2 additions & 2 deletions Sources/Containerization/LinuxPod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -727,15 +727,15 @@ extension LinuxPod {
}

/// Get statistics for containers in the pod.
public func statistics(containerIDs: [String]? = nil) async throws -> [ContainerStatistics] {
public func statistics(containerIDs: [String]? = nil, categories: StatCategory = .all) async throws -> [ContainerStatistics] {
let (createdState, ids) = try await self.state.withLock { state in
let createdState = try state.phase.createdState("statistics")
let ids = containerIDs ?? Array(state.containers.keys)
return (createdState, ids)
}

let stats = try await createdState.vm.withAgent { agent in
try await agent.containerStatistics(containerIDs: ids)
try await agent.containerStatistics(containerIDs: ids, categories: categories)
}

return stats
Expand Down
Loading