Skip to content

Commit 5b7f854

Browse files
authored
Merge pull request #52 from clue-labs/stats
Add `containerStats()` and `containerStatsStream()` methods
2 parents 8fae025 + 0ae405f commit 5b7f854

4 files changed

Lines changed: 108 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ a [`Stream`](https://github.com/reactphp/stream) instance instead:
321321
$stream = $client->imageCreateStream();
322322
$stream = $client->imagePushStream();
323323
$stream = $client->eventsStream();
324+
$stream = $client->containerStatsStream($container);
324325
```
325326

326327
The resulting stream will emit the following events:

examples/stats.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
// this example shows how the `containerStatsStream()` method can be used show live container stats.
4+
// demonstrates the JSON streaming API, individual stats events will be printed as they happen.
5+
6+
use Clue\React\Docker\Client;
7+
8+
require __DIR__ . '/../vendor/autoload.php';
9+
10+
$container = isset($argv[1]) ? $argv[1] : 'asd';
11+
echo 'Monitoring "' . $container . '" (pass as argument to this example)' . PHP_EOL;
12+
13+
$loop = React\EventLoop\Factory::create();
14+
$client = new Client($loop);
15+
16+
$stream = $client->containerStatsStream($container);
17+
18+
$stream->on('data', function ($progress) {
19+
//echo 'progress: '. json_encode($progress, JSON_PRETTY_PRINT) . PHP_EOL;
20+
21+
$memory = $progress['memory_stats']['usage'] / $progress['memory_stats']['limit'] * 100;
22+
$sent = $received = 0;
23+
foreach ($progress['networks'] as $stats) {
24+
$sent += $stats['tx_bytes'];
25+
$received += $stats['rx_bytes'];
26+
}
27+
28+
echo round($memory, 3) . '% memory and ' . $received . '/' . $sent . ' bytes network I/O' . PHP_EOL;
29+
});
30+
$stream->on('error', 'printf');
31+
$stream->on('close', function () {
32+
echo 'stream closed' . PHP_EOL;
33+
});
34+
35+
$loop->run();

src/Client.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,61 @@ public function containerExportStream($container)
344344
);
345345
}
346346

347+
/**
348+
* Returns a container’s resource usage statistics.
349+
*
350+
* This is a JSON API endpoint that resolves with a single stats info.
351+
*
352+
* If you want to monitor live stats events as they happen, you
353+
* should consider using `imageStatsStream()` instead.
354+
*
355+
* @param string $container container ID
356+
* @return PromiseInterface Promise<array> JSON stats
357+
* @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerStats
358+
* @since 0.3.0 Available as of Docker Engine API v1.19 (Docker v1.7), use `containerStatsStream()` on legacy versions
359+
* @see self::containerStatsStream()
360+
*/
361+
public function containerStats($container)
362+
{
363+
return $this->browser->get(
364+
$this->uri->expand(
365+
'/containers/{container}/stats{?stream}',
366+
array(
367+
'container' => $container,
368+
'stream' => 0
369+
)
370+
)
371+
)->then(array($this->parser, 'expectJson'));
372+
}
373+
374+
/**
375+
* Returns a live stream of a container’s resource usage statistics.
376+
*
377+
* The resulting stream will emit the following events:
378+
* - data: for *each* element in the stats stream
379+
* - error: once if an error occurs, will close() stream then
380+
* - close: once the stream ends (either finished or after "error")
381+
*
382+
* @param string $container container ID
383+
* @return ReadableStreamInterface JSON stats stream
384+
* @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerStats
385+
* @since 0.3.0 Available as of Docker Engine API v1.17 (Docker v1.5)
386+
* @see self::containerStats()
387+
*/
388+
public function containerStatsStream($container)
389+
{
390+
return $this->streamingParser->parseJsonStream(
391+
$this->browser->withOptions(array('streaming' => true))->get(
392+
$this->uri->expand(
393+
'/containers/{container}/stats',
394+
array(
395+
'container' => $container
396+
)
397+
)
398+
)
399+
);
400+
}
401+
347402
/**
348403
* Resize the TTY of container id
349404
*

tests/ClientTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,23 @@ public function testContainerRemoveVolumeForce()
287287
$this->expectPromiseResolveWith('', $this->client->containerRemove(123, true, true));
288288
}
289289

290+
public function testContainerStats()
291+
{
292+
$this->expectRequestFlow('GET', '/containers/123/stats?stream=0', $this->createResponse(), 'expectJson');
293+
294+
$this->expectPromiseResolveWith('', $this->client->containerStats(123));
295+
}
296+
297+
public function testContainerStatsStream()
298+
{
299+
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();
300+
301+
$this->expectRequest('GET', '/containers/123/stats', $this->createResponse(''));
302+
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
303+
304+
$this->assertSame($stream, $this->client->containerStatsStream('123'));
305+
}
306+
290307
public function testContainerResize()
291308
{
292309
$this->expectRequestFlow('POST', '/containers/123/resize?w=800&h=600', $this->createResponse(), 'expectEmpty');

0 commit comments

Comments
 (0)