Skip to content

Commit 21e189c

Browse files
committed
Merge branch 'nir0s-add-stats-api-support'
2 parents 1565464 + 1f1e399 commit 21e189c

File tree

7 files changed

+208
-1
lines changed

7 files changed

+208
-1
lines changed

docker/client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,22 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
869869
res = self._post_json(url, data=start_config)
870870
self._raise_for_status(res)
871871

872+
def stats(self, container):
873+
if utils.compare_version('1.17', self._version) < 0:
874+
raise errors.InvalidVersion(
875+
'Stats retrieval is not supported in API < 1.17!')
876+
877+
if isinstance(container, dict):
878+
container = container.get('Id')
879+
url = self._url("/containers/{0}/stats".format(container))
880+
return self._stream_helper(self._get(url, stream=True))
881+
872882
def stop(self, container, timeout=10):
873883
if isinstance(container, dict):
874884
container = container.get('Id')
875885
params = {'t': timeout}
876886
url = self._url("/containers/{0}/stop".format(container))
887+
877888
res = self._post(url, params=params,
878889
timeout=(timeout + self.timeout))
879890
self._raise_for_status(res)

docs/api.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,27 @@ from. Optionally a single string joining container id's with commas
708708
None
709709
```
710710

711+
## stats
712+
713+
The Docker API parallel to the `docker stats` command.
714+
This will stream statistics for a specific container.
715+
716+
**Params**:
717+
718+
* container (str): The container to start
719+
720+
```python
721+
>>> from docker import Client
722+
>>> cli = Client(base_url='tcp://127.0.0.1:2375')
723+
>>> stats_obj = cli.stats('elasticsearch')
724+
>>> for stat in stats:
725+
>>> print(stat)
726+
{"read":"2015-02-11T21:47:30.49388286+02:00","network":{"rx_bytes":666052,"rx_packets":4409 ...
727+
...
728+
...
729+
...
730+
```
731+
711732
## stop
712733

713734
Stops a container. Similar to the `docker stop` command.

docs/change_log.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Change Log
22
==========
33

4+
45
0.7.2
56
-----
67

tests/fake_api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import fake_stat
16+
1517
CURRENT_VERSION = 'v1.17'
1618

1719
FAKE_CONTAINER_ID = '3cc2351ab11b'
@@ -337,6 +339,11 @@ def post_fake_tag_image():
337339
return status_code, response
338340

339341

342+
def get_fake_stats():
343+
status_code = 200
344+
response = fake_stat.OBJ
345+
return status_code, response
346+
340347
# Maps real api url to fake response callback
341348
prefix = 'http+unix://var/run/docker.sock'
342349
fake_responses = {
@@ -376,6 +383,8 @@ def post_fake_tag_image():
376383
post_fake_execute,
377384
'{1}/{0}/exec/3cc2351ab11b/start'.format(CURRENT_VERSION, prefix):
378385
post_fake_execute_start,
386+
'{1}/{0}/containers/3cc2351ab11b/stats'.format(CURRENT_VERSION, prefix):
387+
get_fake_stats,
379388
'{1}/{0}/containers/3cc2351ab11b/stop'.format(CURRENT_VERSION, prefix):
380389
post_fake_stop_container,
381390
'{1}/{0}/containers/3cc2351ab11b/kill'.format(CURRENT_VERSION, prefix):

tests/fake_stat.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
OBJ = {
2+
"read": "2015-02-11T19:20:46.667237763+02:00",
3+
"network": {
4+
"rx_bytes": 567224,
5+
"rx_packets": 3773,
6+
"rx_errors": 0,
7+
"rx_dropped": 0,
8+
"tx_bytes": 1176,
9+
"tx_packets": 13,
10+
"tx_errors": 0,
11+
"tx_dropped": 0
12+
},
13+
"cpu_stats": {
14+
"cpu_usage": {
15+
"total_usage": 157260874053,
16+
"percpu_usage": [
17+
52196306950,
18+
24118413549,
19+
53292684398,
20+
27653469156
21+
],
22+
"usage_in_kernelmode": 37140000000,
23+
"usage_in_usermode": 62140000000
24+
},
25+
"system_cpu_usage": 3.0881377e+14,
26+
"throttling_data": {
27+
"periods": 0,
28+
"throttled_periods": 0,
29+
"throttled_time": 0
30+
}
31+
},
32+
"memory_stats": {
33+
"usage": 179314688,
34+
"max_usage": 258166784,
35+
"stats": {
36+
"active_anon": 90804224,
37+
"active_file": 2195456,
38+
"cache": 3096576,
39+
"hierarchical_memory_limit": 1.844674407371e+19,
40+
"inactive_anon": 85516288,
41+
"inactive_file": 798720,
42+
"mapped_file": 2646016,
43+
"pgfault": 101034,
44+
"pgmajfault": 1207,
45+
"pgpgin": 115814,
46+
"pgpgout": 75613,
47+
"rss": 176218112,
48+
"rss_huge": 12582912,
49+
"total_active_anon": 90804224,
50+
"total_active_file": 2195456,
51+
"total_cache": 3096576,
52+
"total_inactive_anon": 85516288,
53+
"total_inactive_file": 798720,
54+
"total_mapped_file": 2646016,
55+
"total_pgfault": 101034,
56+
"total_pgmajfault": 1207,
57+
"total_pgpgin": 115814,
58+
"total_pgpgout": 75613,
59+
"total_rss": 176218112,
60+
"total_rss_huge": 12582912,
61+
"total_unevictable": 0,
62+
"total_writeback": 0,
63+
"unevictable": 0,
64+
"writeback": 0
65+
},
66+
"failcnt": 0,
67+
"limit": 8039038976
68+
},
69+
"blkio_stats": {
70+
"io_service_bytes_recursive": [
71+
{
72+
"major": 8,
73+
"minor": 0,
74+
"op": "Read",
75+
"value": 72843264
76+
},
77+
{
78+
"major": 8,
79+
"minor": 0,
80+
"op": "Write",
81+
"value": 4096
82+
},
83+
{
84+
"major": 8,
85+
"minor": 0,
86+
"op": "Sync",
87+
"value": 4096
88+
},
89+
{
90+
"major": 8,
91+
"minor": 0,
92+
"op": "Async",
93+
"value": 72843264
94+
},
95+
{
96+
"major": 8,
97+
"minor": 0,
98+
"op": "Total",
99+
"value": 72847360
100+
}
101+
],
102+
"io_serviced_recursive": [
103+
{
104+
"major": 8,
105+
"minor": 0,
106+
"op": "Read",
107+
"value": 10581
108+
},
109+
{
110+
"major": 8,
111+
"minor": 0,
112+
"op": "Write",
113+
"value": 1
114+
},
115+
{
116+
"major": 8,
117+
"minor": 0,
118+
"op": "Sync",
119+
"value": 1
120+
},
121+
{
122+
"major": 8,
123+
"minor": 0,
124+
"op": "Async",
125+
"value": 10581
126+
},
127+
{
128+
"major": 8,
129+
"minor": 0,
130+
"op": "Total",
131+
"value": 10582
132+
}
133+
],
134+
"io_queue_recursive": [
135+
136+
],
137+
"io_service_time_recursive": [
138+
139+
],
140+
"io_wait_time_recursive": [
141+
142+
],
143+
"io_merged_recursive": [
144+
145+
],
146+
"io_time_recursive": [
147+
148+
],
149+
"sectors_recursive": [
150+
151+
]
152+
}
153+
}

tests/integration_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from test import Cleanup
3030

3131
# FIXME: missing tests for
32-
# export; history; import_image; insert; port; push; tag; get; load
32+
# export; history; import_image; insert; port; push; tag; get; load; stats;
3333

3434
DEFAULT_BASE_URL = os.environ.get('DOCKER_HOST')
3535

tests/test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,18 @@ def test_inspect_container(self):
16721672
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
16731673
)
16741674

1675+
def test_container_stats(self):
1676+
try:
1677+
self.client.stats(fake_api.FAKE_CONTAINER_ID)
1678+
except Exception as e:
1679+
self.fail('Command should not raise exception: {0}'.format(e))
1680+
1681+
fake_request.assert_called_with(
1682+
url_prefix + 'containers/3cc2351ab11b/stats',
1683+
timeout=60,
1684+
stream=True
1685+
)
1686+
16751687
##################
16761688
# IMAGES TESTS #
16771689
##################

0 commit comments

Comments
 (0)