@@ -103,6 +103,17 @@ private func formatByteSize(_ value: Int) -> String? {
103 return ByteCountFormatter.string(fromByteCount: Int64(value), countStyle: .file)
103 return ByteCountFormatter.string(fromByteCount: Int64(value), countStyle: .file)
106+/// Normalizes a byte count that arrived as a JSON *string*. A bare numeric string
107+/// (e.g. "1048576") is a raw byte count and is formatted like the numeric branches
108+/// so identical sizes render consistently ("1 MB") regardless of whether the server
109+/// quoted the value; an already-formatted string (e.g. "1.2 GB") is passed through
111+private func formatByteSize(_ value: String) -> String {
112+ let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
113+ if let n = Int(trimmed) { return formatByteSize(n) ?? value }
106struct StreamStats: Codable, Sendable {
117struct StreamStats: Codable, Sendable {
107 let ingestion: IngestionStats?
118 let ingestion: IngestionStats?
108 let storage: StorageStats?
119 let storage: StorageStats?
@@ -123,7 +134,7 @@ struct StreamStats: Codable, Sendable {
123 self.lifetime_count = try? container.decode(Int.self, forKey: .lifetime_count)
134 self.lifetime_count = try? container.decode(Int.self, forKey: .lifetime_count)
124 // Handle size as string or number
135 // Handle size as string or number
125 if let s = try? container.decode(String.self, forKey: .size) {
136 if let s = try? container.decode(String.self, forKey: .size) {
126− self.size = s
137+ self.size = formatByteSize(s)
127 } else if let n = try? container.decode(Int.self, forKey: .size) {
138 } else if let n = try? container.decode(Int.self, forKey: .size) {
128 self.size = formatByteSize(n)
139 self.size = formatByteSize(n)
129 } else if let d = try? container.decode(Double.self, forKey: .size) {
140 } else if let d = try? container.decode(Double.self, forKey: .size) {
@@ -132,7 +143,7 @@ struct StreamStats: Codable, Sendable {
132 self.size = nil
143 self.size = nil
134 if let s = try? container.decode(String.self, forKey: .lifetime_size) {
145 if let s = try? container.decode(String.self, forKey: .lifetime_size) {
135− self.lifetime_size = s
146+ self.lifetime_size = formatByteSize(s)
136 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
147 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
137 self.lifetime_size = formatByteSize(n)
148 self.lifetime_size = formatByteSize(n)
138 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {
149 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {
@@ -156,7 +167,7 @@ struct StreamStats: Codable, Sendable {
156 let container = try decoder.container(keyedBy: CodingKeys.self)
167 let container = try decoder.container(keyedBy: CodingKeys.self)
157 self.type = try? container.decode(String.self, forKey: .type)
168 self.type = try? container.decode(String.self, forKey: .type)
158 if let s = try? container.decode(String.self, forKey: .size) {
169 if let s = try? container.decode(String.self, forKey: .size) {
159− self.size = s
170+ self.size = formatByteSize(s)
160 } else if let n = try? container.decode(Int.self, forKey: .size) {
171 } else if let n = try? container.decode(Int.self, forKey: .size) {
161 self.size = formatByteSize(n)
172 self.size = formatByteSize(n)
162 } else if let d = try? container.decode(Double.self, forKey: .size) {
173 } else if let d = try? container.decode(Double.self, forKey: .size) {
@@ -165,7 +176,7 @@ struct StreamStats: Codable, Sendable {
165 self.size = nil
176 self.size = nil
167 if let s = try? container.decode(String.self, forKey: .lifetime_size) {
178 if let s = try? container.decode(String.self, forKey: .lifetime_size) {
168− self.lifetime_size = s
179+ self.lifetime_size = formatByteSize(s)
169 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
180 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
170 self.lifetime_size = formatByteSize(n)
181 self.lifetime_size = formatByteSize(n)
171 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {
182 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {