|
1 | 1 | package container |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bytes" |
4 | 5 | "context" |
5 | 6 | "fmt" |
6 | 7 | "io" |
@@ -264,31 +265,40 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions) |
264 | 265 | // so we unlikely hit this code in practice. |
265 | 266 | daemonOSType = dockerCLI.ServerInfo().OSType |
266 | 267 | } |
| 268 | + |
| 269 | + // Buffer to store formatted stats text. |
| 270 | + // Once formatted, it will be printed in one write to avoid screen flickering. |
| 271 | + var statsTextBuffer bytes.Buffer |
| 272 | + |
267 | 273 | statsCtx := formatter.Context{ |
268 | | - Output: dockerCLI.Out(), |
| 274 | + Output: &statsTextBuffer, |
269 | 275 | Format: NewStatsFormat(format, daemonOSType), |
270 | 276 | } |
271 | | - cleanScreen := func() { |
272 | | - if !options.NoStream { |
273 | | - _, _ = fmt.Fprint(dockerCLI.Out(), "\033[2J") |
274 | | - _, _ = fmt.Fprint(dockerCLI.Out(), "\033[H") |
275 | | - } |
276 | | - } |
277 | 277 |
|
278 | 278 | var err error |
279 | 279 | ticker := time.NewTicker(500 * time.Millisecond) |
280 | 280 | defer ticker.Stop() |
281 | 281 | for range ticker.C { |
282 | | - cleanScreen() |
283 | 282 | var ccStats []StatsEntry |
284 | 283 | cStats.mu.RLock() |
285 | 284 | for _, c := range cStats.cs { |
286 | 285 | ccStats = append(ccStats, c.GetStatistics()) |
287 | 286 | } |
288 | 287 | cStats.mu.RUnlock() |
| 288 | + |
| 289 | + if !options.NoStream { |
| 290 | + // Start by clearing the screen and moving the cursor to the top-left |
| 291 | + _, _ = fmt.Fprint(&statsTextBuffer, "\033[2J\033[H") |
| 292 | + } |
| 293 | + |
289 | 294 | if err = statsFormatWrite(statsCtx, ccStats, daemonOSType, !options.NoTrunc); err != nil { |
290 | 295 | break |
291 | 296 | } |
| 297 | + |
| 298 | + _, _ = fmt.Fprint(dockerCLI.Out(), statsTextBuffer.String()) |
| 299 | + |
| 300 | + statsTextBuffer.Reset() |
| 301 | + |
292 | 302 | if len(cStats.cs) == 0 && !showAll { |
293 | 303 | break |
294 | 304 | } |
|
0 commit comments