Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
34a500e3
G
glances
项目概览
蜕变的菜鸟
/
glances
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
glances
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
34a500e3
编写于
3月 31, 2016
作者:
N
nicolargo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810)
上级
4e9cf18c
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
175 addition
and
66 deletion
+175
-66
NEWS
NEWS
+1
-0
conf/glances.conf
conf/glances.conf
+5
-0
docs/_static/cpu-wide.png
docs/_static/cpu-wide.png
+0
-0
docs/aoa/cpu.rst
docs/aoa/cpu.rst
+16
-2
docs/man/glances.1
docs/man/glances.1
+1
-1
glances/plugins/glances_cpu.py
glances/plugins/glances_cpu.py
+138
-54
glances/plugins/glances_diskio.py
glances/plugins/glances_diskio.py
+1
-1
glances/plugins/glances_load.py
glances/plugins/glances_load.py
+1
-1
glances/plugins/glances_plugin.py
glances/plugins/glances_plugin.py
+4
-0
glances/plugins/glances_quicklook.py
glances/plugins/glances_quicklook.py
+8
-7
未找到文件。
NEWS
浏览文件 @
34a500e3
...
...
@@ -7,6 +7,7 @@ Version 2.7
Enhancements and new features:
* CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810)
* [Folders] Differentiate permission issue and non-existence of a directory (issue #828)
* [Web UI] add cpu name in quicklook plugin (issue #825)
...
...
conf/glances.conf
浏览文件 @
34a500e3
...
...
@@ -28,6 +28,11 @@ steal_careful=50
steal_warning
=
70
steal_critical
=
90
#steal_log=True
# Context switch limit per core / second
# For example, if you have 2 Core, critical limit will be 28000/sec
ctx_switches_careful
=
10000
ctx_switches_warning
=
12000
ctx_switches_critical
=
14000
[
percpu
]
# Define CPU thresholds in %
...
...
docs/_static/cpu-wide.png
查看替换文件 @
4e9cf18c
浏览文件 @
34a500e3
14.8 KB
|
W:
|
H:
29.6 KB
|
W:
|
H:
2-up
Swipe
Onion skin
docs/aoa/cpu.rst
浏览文件 @
34a500e3
...
...
@@ -3,8 +3,8 @@
CPU
===
The CPU stats are shown as a percentage
and for the configured refresh
time. The total CPU usage is displayed on the first line.
The CPU stats are shown as a percentage
or value and for the configured
refresh
time. The total CPU usage is displayed on the first line.
.. image:: ../_static/cpu.png
...
...
@@ -13,6 +13,20 @@ displayed.
.. image:: ../_static/cpu-wide.png
CPU stats description:
* user: percent time spent in user space
* system: percent time spent in kernel space
* idle: percent of CPU used by any program
* nice: percent time occupied by user level processes with a positive nice value
* irq: percent time spent servicing/handling hardware/software interrupts
* iowait: percent time spent in wait (on disk)
* steal: percent time in involuntary wait by virtual cpu while hypervisor is servicing another processor/virtual machine
* ctx_sw: number of context switches (voluntary + involuntary) per second
* inter: number of interrupts per second
* sw_inter: number of software interrupts per second. Always set to 0 on Windows and SunOS.
* syscal: number of system calls per second. Do not displayed on Linux (always 0).
To switch to per-CPU stats, just hit the ``1`` key:
.. image:: ../_static/per-cpu.png
...
...
docs/man/glances.1
浏览文件 @
34a500e3
.\" Man page generated from reStructuredText.
.
.TH "GLANCES" "1" "March
28
, 2016" "2.7_BETA" "Glances"
.TH "GLANCES" "1" "March
31
, 2016" "2.7_BETA" "Glances"
.SH NAME
glances \- An eye on your system
.
...
...
glances/plugins/glances_cpu.py
浏览文件 @
34a500e3
...
...
@@ -19,8 +19,11 @@
"""CPU plugin."""
from
glances.timer
import
getTimeSinceLastUpdate
from
glances.compat
import
iterkeys
from
glances.cpu_percent
import
cpu_percent
from
glances.globals
import
LINUX
from
glances.plugins.glances_core
import
Plugin
as
CorePlugin
from
glances.plugins.glances_plugin
import
GlancesPlugin
import
psutil
...
...
@@ -65,6 +68,12 @@ class Plugin(GlancesPlugin):
# Init stats
self
.
reset
()
# Call CorePlugin in order to display the core number
try
:
self
.
nb_log_core
=
CorePlugin
(
args
=
self
.
args
).
update
()[
"log"
]
except
Exception
:
self
.
nb_log_core
=
1
def
reset
(
self
):
"""Reset/init the stats."""
self
.
stats
=
{}
...
...
@@ -75,61 +84,11 @@ class Plugin(GlancesPlugin):
# Reset stats
self
.
reset
()
# Grab CPU stats using psutil's cpu_percent and cpu_times_percent
# methods
# Grab stats into self.stats
if
self
.
input_method
==
'local'
:
# Get all possible values for CPU stats: user, system, idle,
# nice (UNIX), iowait (Linux), irq (Linux, FreeBSD), steal (Linux 2.6.11+)
# The following stats are returned by the API but not displayed in the UI:
# softirq (Linux), guest (Linux 2.6.24+), guest_nice (Linux 3.2.0+)
self
.
stats
[
'total'
]
=
cpu_percent
.
get
()
cpu_times_percent
=
psutil
.
cpu_times_percent
(
interval
=
0.0
)
for
stat
in
[
'user'
,
'system'
,
'idle'
,
'nice'
,
'iowait'
,
'irq'
,
'softirq'
,
'steal'
,
'guest'
,
'guest_nice'
]:
if
hasattr
(
cpu_times_percent
,
stat
):
self
.
stats
[
stat
]
=
getattr
(
cpu_times_percent
,
stat
)
self
.
update_local
()
elif
self
.
input_method
==
'snmp'
:
# Update stats using SNMP
if
self
.
short_system_name
in
(
'windows'
,
'esxi'
):
# Windows or VMWare ESXi
# You can find the CPU utilization of windows system by querying the oid
# Give also the number of core (number of element in the table)
try
:
cpu_stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
self
.
short_system_name
],
bulk
=
True
)
except
KeyError
:
self
.
reset
()
# Iter through CPU and compute the idle CPU stats
self
.
stats
[
'nb_log_core'
]
=
0
self
.
stats
[
'idle'
]
=
0
for
c
in
cpu_stats
:
if
c
.
startswith
(
'percent'
):
self
.
stats
[
'idle'
]
+=
float
(
cpu_stats
[
'percent.3'
])
self
.
stats
[
'nb_log_core'
]
+=
1
if
self
.
stats
[
'nb_log_core'
]
>
0
:
self
.
stats
[
'idle'
]
=
self
.
stats
[
'idle'
]
/
self
.
stats
[
'nb_log_core'
]
self
.
stats
[
'idle'
]
=
100
-
self
.
stats
[
'idle'
]
self
.
stats
[
'total'
]
=
100
-
self
.
stats
[
'idle'
]
else
:
# Default behavor
try
:
self
.
stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
self
.
short_system_name
])
except
KeyError
:
self
.
stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
'default'
])
if
self
.
stats
[
'idle'
]
==
''
:
self
.
reset
()
return
self
.
stats
# Convert SNMP stats to float
for
key
in
iterkeys
(
self
.
stats
):
self
.
stats
[
key
]
=
float
(
self
.
stats
[
key
])
self
.
stats
[
'total'
]
=
100
-
self
.
stats
[
'idle'
]
self
.
update_snmp
()
# Update the history list
self
.
update_stats_history
()
...
...
@@ -139,6 +98,96 @@ class Plugin(GlancesPlugin):
return
self
.
stats
def
update_local
(
self
):
"""Update CPU stats using PSUtil."""
# Grab CPU stats using psutil's cpu_percent and cpu_times_percent
# Get all possible values for CPU stats: user, system, idle,
# nice (UNIX), iowait (Linux), irq (Linux, FreeBSD), steal (Linux 2.6.11+)
# The following stats are returned by the API but not displayed in the UI:
# softirq (Linux), guest (Linux 2.6.24+), guest_nice (Linux 3.2.0+)
self
.
stats
[
'total'
]
=
cpu_percent
.
get
()
cpu_times_percent
=
psutil
.
cpu_times_percent
(
interval
=
0.0
)
for
stat
in
[
'user'
,
'system'
,
'idle'
,
'nice'
,
'iowait'
,
'irq'
,
'softirq'
,
'steal'
,
'guest'
,
'guest_nice'
]:
if
hasattr
(
cpu_times_percent
,
stat
):
self
.
stats
[
stat
]
=
getattr
(
cpu_times_percent
,
stat
)
# Additionnal CPU stats (number of events / not as a %)
# ctx_switches: number of context switches (voluntary + involuntary) per second
# interrupts: number of interrupts per second
# soft_interrupts: number of software interrupts per second. Always set to 0 on Windows and SunOS.
# syscalls: number of system calls since boot. Always set to 0 on Linux.
try
:
cpu_stats
=
psutil
.
cpu_stats
()
except
AttributeError
:
# cpu_stats only available with PSUtil 4.1 or +
pass
else
:
# By storing time data we enable Rx/s and Tx/s calculations in the
# XML/RPC API, which would otherwise be overly difficult work
# for users of the API
time_since_update
=
getTimeSinceLastUpdate
(
'cpu'
)
# Previous CPU stats are stored in the cpu_stats_old variable
if
not
hasattr
(
self
,
'cpu_stats_old'
):
# First call, we init the cpu_stats_old var
self
.
cpu_stats_old
=
cpu_stats
else
:
for
stat
in
cpu_stats
.
_fields
:
self
.
stats
[
stat
]
=
getattr
(
cpu_stats
,
stat
)
-
getattr
(
self
.
cpu_stats_old
,
stat
)
self
.
stats
[
'time_since_update'
]
=
time_since_update
# Core number is needed to compute the CTX switch limit
self
.
stats
[
'cpucore'
]
=
self
.
nb_log_core
# Save stats to compute next step
self
.
cpu_stats_old
=
cpu_stats
def
update_snmp
(
self
):
"""Update CPU stats using SNMP."""
# Update stats using SNMP
if
self
.
short_system_name
in
(
'windows'
,
'esxi'
):
# Windows or VMWare ESXi
# You can find the CPU utilization of windows system by querying the oid
# Give also the number of core (number of element in the table)
try
:
cpu_stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
self
.
short_system_name
],
bulk
=
True
)
except
KeyError
:
self
.
reset
()
# Iter through CPU and compute the idle CPU stats
self
.
stats
[
'nb_log_core'
]
=
0
self
.
stats
[
'idle'
]
=
0
for
c
in
cpu_stats
:
if
c
.
startswith
(
'percent'
):
self
.
stats
[
'idle'
]
+=
float
(
cpu_stats
[
'percent.3'
])
self
.
stats
[
'nb_log_core'
]
+=
1
if
self
.
stats
[
'nb_log_core'
]
>
0
:
self
.
stats
[
'idle'
]
=
self
.
stats
[
'idle'
]
/
self
.
stats
[
'nb_log_core'
]
self
.
stats
[
'idle'
]
=
100
-
self
.
stats
[
'idle'
]
self
.
stats
[
'total'
]
=
100
-
self
.
stats
[
'idle'
]
else
:
# Default behavor
try
:
self
.
stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
self
.
short_system_name
])
except
KeyError
:
self
.
stats
=
self
.
get_stats_snmp
(
snmp_oid
=
snmp_oid
[
'default'
])
if
self
.
stats
[
'idle'
]
==
''
:
self
.
reset
()
return
self
.
stats
# Convert SNMP stats to float
for
key
in
iterkeys
(
self
.
stats
):
self
.
stats
[
key
]
=
float
(
self
.
stats
[
key
])
self
.
stats
[
'total'
]
=
100
-
self
.
stats
[
'idle'
]
def
update_views
(
self
):
"""Update stats views."""
# Call the father's method
...
...
@@ -153,8 +202,12 @@ class Plugin(GlancesPlugin):
for
key
in
[
'steal'
,
'total'
]:
if
key
in
self
.
stats
:
self
.
views
[
key
][
'decoration'
]
=
self
.
get_alert
(
self
.
stats
[
key
],
header
=
key
)
# Alert only but depend on Core number
for
key
in
[
'ctx_switches'
]:
if
key
in
self
.
stats
:
self
.
views
[
key
][
'decoration'
]
=
self
.
get_alert
(
self
.
stats
[
key
],
maximum
=
100
*
self
.
stats
[
'cpucore'
],
header
=
key
)
# Optional
for
key
in
[
'nice'
,
'irq'
,
'iowait'
,
'steal'
]:
for
key
in
[
'nice'
,
'irq'
,
'iowait'
,
'steal'
,
'ctx_switches'
,
'interrupts'
,
'soft_interrupts'
,
'syscalls'
]:
if
key
in
self
.
stats
:
self
.
views
[
key
][
'optional'
]
=
True
...
...
@@ -171,6 +224,7 @@ class Plugin(GlancesPlugin):
# If user stat is not here, display only idle / total CPU usage (for
# exemple on Windows OS)
idle_tag
=
'user'
not
in
self
.
stats
# Header
msg
=
'{0:8}'
.
format
(
'CPU'
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
"TITLE"
))
...
...
@@ -187,6 +241,15 @@ class Plugin(GlancesPlugin):
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'nice'
,
option
=
'optional'
)))
msg
=
'{0:>5}%'
.
format
(
self
.
stats
[
'nice'
])
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'nice'
,
option
=
'optional'
)))
# ctx_switches
if
'ctx_switches'
in
self
.
stats
:
msg
=
' {0:8}'
.
format
(
'ctx_sw:'
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'ctx_switches'
,
option
=
'optional'
)))
msg
=
'{0:>5}'
.
format
(
int
(
self
.
stats
[
'ctx_switches'
]
//
self
.
stats
[
'time_since_update'
]))
ret
.
append
(
self
.
curse_add_line
(
msg
,
self
.
get_views
(
key
=
'ctx_switches'
,
option
=
'decoration'
),
optional
=
self
.
get_views
(
key
=
'ctx_switches'
,
option
=
'optional'
)))
# New line
ret
.
append
(
self
.
curse_new_line
())
# User CPU
...
...
@@ -207,6 +270,13 @@ class Plugin(GlancesPlugin):
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'irq'
,
option
=
'optional'
)))
msg
=
'{0:>5}%'
.
format
(
self
.
stats
[
'irq'
])
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'irq'
,
option
=
'optional'
)))
# interrupts
if
'interrupts'
in
self
.
stats
:
msg
=
' {0:8}'
.
format
(
'inter:'
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'interrupts'
,
option
=
'optional'
)))
msg
=
'{0:>5}'
.
format
(
int
(
self
.
stats
[
'interrupts'
]
//
self
.
stats
[
'time_since_update'
]))
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'interrupts'
,
option
=
'optional'
)))
# New line
ret
.
append
(
self
.
curse_new_line
())
# System CPU
...
...
@@ -229,6 +299,13 @@ class Plugin(GlancesPlugin):
ret
.
append
(
self
.
curse_add_line
(
msg
,
self
.
get_views
(
key
=
'iowait'
,
option
=
'decoration'
),
optional
=
self
.
get_views
(
key
=
'iowait'
,
option
=
'optional'
)))
# soft_interrupts
if
'soft_interrupts'
in
self
.
stats
:
msg
=
' {0:8}'
.
format
(
'sw_int:'
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'soft_interrupts'
,
option
=
'optional'
)))
msg
=
'{0:>5}'
.
format
(
int
(
self
.
stats
[
'soft_interrupts'
]
//
self
.
stats
[
'time_since_update'
]))
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'soft_interrupts'
,
option
=
'optional'
)))
# New line
ret
.
append
(
self
.
curse_new_line
())
# Idle CPU
...
...
@@ -245,6 +322,13 @@ class Plugin(GlancesPlugin):
ret
.
append
(
self
.
curse_add_line
(
msg
,
self
.
get_views
(
key
=
'steal'
,
option
=
'decoration'
),
optional
=
self
.
get_views
(
key
=
'steal'
,
option
=
'optional'
)))
# syscalls
# syscalls: number of system calls since boot. Always set to 0 on Linux. (do not display)
if
'syscalls'
in
self
.
stats
and
not
LINUX
:
msg
=
' {0:8}'
.
format
(
'syscal:'
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'syscalls'
,
option
=
'optional'
)))
msg
=
'{0:>5}'
.
format
(
int
(
self
.
stats
[
'syscalls'
]
//
self
.
stats
[
'time_since_update'
]))
ret
.
append
(
self
.
curse_add_line
(
msg
,
optional
=
self
.
get_views
(
key
=
'syscalls'
,
option
=
'optional'
)))
# Return the message with decoration
return
ret
glances/plugins/glances_diskio.py
浏览文件 @
34a500e3
...
...
@@ -81,7 +81,7 @@ class Plugin(GlancesPlugin):
# Previous disk IO stats are stored in the diskio_old variable
if
not
hasattr
(
self
,
'diskio_old'
):
# First call, we init the
network
_old var
# First call, we init the
diskio
_old var
try
:
self
.
diskio_old
=
diskiocounters
except
(
IOError
,
UnboundLocalError
):
...
...
glances/plugins/glances_load.py
浏览文件 @
34a500e3
...
...
@@ -62,7 +62,7 @@ class Plugin(GlancesPlugin):
try
:
self
.
nb_log_core
=
CorePlugin
(
args
=
self
.
args
).
update
()[
"log"
]
except
Exception
:
self
.
nb_log_core
=
0
self
.
nb_log_core
=
1
def
reset
(
self
):
"""Reset/init the stats."""
...
...
glances/plugins/glances_plugin.py
浏览文件 @
34a500e3
...
...
@@ -403,6 +403,8 @@ class GlancesPlugin(object):
except
KeyError
:
return
'DEFAULT'
logger
.
debug
(
"{0} => ret = {1}"
.
format
(
stat_name
,
ret
))
# Manage log
log_str
=
""
if
self
.
__get_limit_log
(
stat_name
=
stat_name
,
default_action
=
log
):
...
...
@@ -455,6 +457,8 @@ class GlancesPlugin(object):
# Exemple: network_careful
limit
=
self
.
_limits
[
self
.
plugin_name
+
'_'
+
criticity
]
# logger.debug("{0} {1} value is {2}".format(stat_name, criticity, limit))
# Return the limit
return
limit
...
...
glances/plugins/glances_quicklook.py
浏览文件 @
34a500e3
...
...
@@ -113,13 +113,14 @@ class Plugin(GlancesPlugin):
bar
=
Bar
(
max_width
)
# Build the string message
if
'cpu_name'
in
self
.
stats
:
msg
=
'{0} - {1:.2f}/{2:.2f}GHz'
.
format
(
self
.
stats
[
'cpu_name'
],
self
.
_hz_to_ghz
(
self
.
stats
[
'cpu_hz_current'
]),
self
.
_hz_to_ghz
(
self
.
stats
[
'cpu_hz'
]))
if
len
(
msg
)
-
6
<=
max_width
:
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
if
'cpu_name'
in
self
.
stats
and
'cpu_hz_current'
in
self
.
stats
and
'cpu_hz'
in
self
.
stats
:
msg_name
=
'{0} - '
.
format
(
self
.
stats
[
'cpu_name'
])
msg_freq
=
'{0:.2f}/{1:.2f}GHz'
.
format
(
self
.
_hz_to_ghz
(
self
.
stats
[
'cpu_hz_current'
]),
self
.
_hz_to_ghz
(
self
.
stats
[
'cpu_hz'
]))
if
len
(
msg_name
+
msg_freq
)
-
6
<=
max_width
:
ret
.
append
(
self
.
curse_add_line
(
msg_name
))
ret
.
append
(
self
.
curse_add_line
(
msg_freq
))
ret
.
append
(
self
.
curse_new_line
())
for
key
in
[
'cpu'
,
'mem'
,
'swap'
]:
if
key
==
'cpu'
and
args
.
percpu
:
for
cpu
in
self
.
stats
[
'percpu'
]:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录