Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F34449190
plot-docker-stats.py
No One
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Authored By
JMeybohm
May 10 2021, 2:25 PM
2021-05-10 14:25:41 (UTC+0)
Size
3 KB
Referenced Files
None
Subscribers
None
plot-docker-stats.py
View Options
#!/bin/env python3
import
argparse
import
json
import
pandas
as
pd
import
plotly.graph_objects
as
go
from
plotly.subplots
import
make_subplots
def
calculate_CPU_usage
(
record
):
"""Return the used CPU delta (in ms) and CPU usage in percent since last tick"""
cpu_percent
=
0.0
cpu_delta
=
(
record
[
"cpu_stats"
][
"cpu_usage"
][
"total_usage"
]
-
record
[
"precpu_stats"
][
"cpu_usage"
][
"total_usage"
]
)
system_delta
=
(
record
[
"cpu_stats"
][
"system_cpu_usage"
]
-
record
[
"precpu_stats"
][
"system_cpu_usage"
]
)
cpu_count
=
record
[
"cpu_stats"
][
"online_cpus"
]
if
system_delta
>
0
and
cpu_delta
>
0
:
cpu_percent
=
(
cpu_delta
/
system_delta
)
*
cpu_count
*
100
if
cpu_delta
>
0
:
cpu_delta
=
cpu_delta
/
1000000
return
(
cpu_delta
,
cpu_percent
)
def
read_json
(
fileobj
):
j
=
[]
first_line
=
True
for
record
in
fileobj
:
# Skip the first line it does not have previous recordings
if
first_line
:
first_line
=
False
continue
try
:
record
=
json
.
loads
(
record
)
except
json
.
decoder
.
JSONDecodeError
:
# probably last line not completely flushed
continue
cpu_delta
,
cpu_percent
=
calculate_CPU_usage
(
record
)
tick
=
dict
(
read
=
record
[
"read"
])
tick
[
"cpu_delta"
]
=
cpu_delta
tick
[
"cpu_percent"
]
=
cpu_percent
# Calculate the time (in ms) the container was throttled since last tick
tick
[
"cpu_throttled_ms"
]
=
(
record
[
"cpu_stats"
][
"throttling_data"
][
"throttled_time"
]
-
record
[
"precpu_stats"
][
"throttling_data"
][
"throttled_time"
]
)
/
1000000
j
.
append
(
tick
)
return
j
def
plot
(
df
,
title
=
"foo"
,
output
=
None
):
fig
=
make_subplots
(
rows
=
2
,
cols
=
1
,
shared_xaxes
=
True
,
subplot_titles
=
(
"CPU %"
,
"CPU (trottled) ms"
)
)
fig
.
add_trace
(
go
.
Scatter
(
x
=
df
[
"read"
],
y
=
df
[
"cpu_percent"
],
name
=
"CPU %"
),
row
=
1
,
col
=
1
,
)
fig
.
add_trace
(
go
.
Scatter
(
x
=
df
[
"read"
],
y
=
df
[
"cpu_delta"
],
name
=
"CPU ms"
),
row
=
2
,
col
=
1
,
)
fig
.
add_trace
(
go
.
Scatter
(
x
=
df
[
"read"
],
y
=
df
[
"cpu_throttled_ms"
],
name
=
"throttled ms"
),
row
=
2
,
col
=
1
,
)
fig
.
update_xaxes
(
title_text
=
"Time"
)
fig
.
update_yaxes
(
title_text
=
"%"
,
range
=
[
0
,
100
],
row
=
1
,
col
=
1
)
fig
.
update_yaxes
(
title_text
=
"ms"
,
row
=
2
,
col
=
1
)
fig
.
update_layout
(
title_text
=
title
)
if
output
is
None
:
fig
.
show
()
else
:
fig
.
write_html
(
output
)
if
__name__
==
"__main__"
:
"""
Generate the input file with something like:
curl -s --unix-socket /var/run/docker.sock \
"http://localhost/containers/${CONTAINER_ID}/stats?stream=1" |
jq -c '{read: .read, cpu_stats: .cpu_stats, precpu_stats: .precpu_stats}'
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Plot docker stats CPU usage data"
)
parser
.
add_argument
(
"input"
,
type
=
argparse
.
FileType
(
"r"
))
parser
.
add_argument
(
"--out"
,
type
=
argparse
.
FileType
(
"w"
),
required
=
False
)
args
=
parser
.
parse_args
()
j
=
read_json
(
args
.
input
)
df
=
pd
.
DataFrame
.
from_dict
(
j
)
plot
(
df
,
args
.
input
.
name
,
args
.
out
)
File Metadata
Details
Attached
Mime Type
text/plain; charset=utf-8
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9069971
Default Alt Text
plot-docker-stats.py (3 KB)
Attached To
Mode
P15857 plot-docker-stats.py
Attached
Detach File
Event Timeline
Log In to Comment