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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ a [`Stream`](https://github.com/reactphp/stream) instance instead:
$stream = $client->imageCreateStream();
$stream = $client->imagePushStream();
$stream = $client->eventsStream();
$stream = $client->containerStatsStream($container);
```

The resulting stream will emit the following events:
Expand Down
35 changes: 35 additions & 0 deletions examples/stats.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

// this example shows how the `containerStatsStream()` method can be used show live container stats.
// demonstrates the JSON streaming API, individual stats events will be printed as they happen.

use Clue\React\Docker\Client;

require __DIR__ . '/../vendor/autoload.php';

$container = isset($argv[1]) ? $argv[1] : 'asd';
echo 'Monitoring "' . $container . '" (pass as argument to this example)' . PHP_EOL;

$loop = React\EventLoop\Factory::create();
$client = new Client($loop);

$stream = $client->containerStatsStream($container);

$stream->on('data', function ($progress) {
//echo 'progress: '. json_encode($progress, JSON_PRETTY_PRINT) . PHP_EOL;

$memory = $progress['memory_stats']['usage'] / $progress['memory_stats']['limit'] * 100;
$sent = $received = 0;
foreach ($progress['networks'] as $stats) {
$sent += $stats['tx_bytes'];
$received += $stats['rx_bytes'];
}

echo round($memory, 3) . '% memory and ' . $received . '/' . $sent . ' bytes network I/O' . PHP_EOL;
});
$stream->on('error', 'printf');
$stream->on('close', function () {
echo 'stream closed' . PHP_EOL;
});

$loop->run();
55 changes: 55 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,61 @@ public function containerExportStream($container)
);
}

/**
* Returns a container’s resource usage statistics.
*
* This is a JSON API endpoint that resolves with a single stats info.
*
* If you want to monitor live stats events as they happen, you
* should consider using `imageStatsStream()` instead.
*
* @param string $container container ID
* @return PromiseInterface Promise<array> JSON stats
* @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerStats
* @since 0.3.0 Available as of Docker Engine API v1.19 (Docker v1.7), use `containerStatsStream()` on legacy versions
* @see self::containerStatsStream()
*/
public function containerStats($container)
{
return $this->browser->get(
$this->uri->expand(
'/containers/{container}/stats{?stream}',
array(
'container' => $container,
'stream' => 0
)
)
)->then(array($this->parser, 'expectJson'));
}

/**
* Returns a live stream of a container’s resource usage statistics.
*
* The resulting stream will emit the following events:
* - data: for *each* element in the stats stream
* - error: once if an error occurs, will close() stream then
* - close: once the stream ends (either finished or after "error")
*
* @param string $container container ID
* @return ReadableStreamInterface JSON stats stream
* @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerStats
* @since 0.3.0 Available as of Docker Engine API v1.17 (Docker v1.5)
* @see self::containerStats()
*/
public function containerStatsStream($container)
{
return $this->streamingParser->parseJsonStream(
$this->browser->withOptions(array('streaming' => true))->get(
$this->uri->expand(
'/containers/{container}/stats',
array(
'container' => $container
)
)
)
);
}

/**
* Resize the TTY of container id
*
Expand Down
17 changes: 17 additions & 0 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,23 @@ public function testContainerRemoveVolumeForce()
$this->expectPromiseResolveWith('', $this->client->containerRemove(123, true, true));
}

public function testContainerStats()
{
$this->expectRequestFlow('GET', '/containers/123/stats?stream=0', $this->createResponse(), 'expectJson');

$this->expectPromiseResolveWith('', $this->client->containerStats(123));
}

public function testContainerStatsStream()
{
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('GET', '/containers/123/stats', $this->createResponse(''));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));

$this->assertSame($stream, $this->client->containerStatsStream('123'));
}

public function testContainerResize()
{
$this->expectRequestFlow('POST', '/containers/123/resize?w=800&h=600', $this->createResponse(), 'expectEmpty');
Expand Down