Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
fb93c969
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,发现更多精彩内容 >>
提交
fb93c969
编写于
1月 21, 2018
作者:
N
nicolargo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Ok but miss some extended stats (see line 348)
上级
229e8f36
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
95 addition
and
299 deletion
+95
-299
glances/amps_list.py
glances/amps_list.py
+1
-2
glances/globals.py
glances/globals.py
+1
-0
glances/logs.py
glances/logs.py
+1
-1
glances/processes.py
glances/processes.py
+92
-296
未找到文件。
glances/amps_list.py
浏览文件 @
fb93c969
...
...
@@ -105,8 +105,7 @@ class AmpsList(object):
def
update
(
self
):
"""Update the command result attributed."""
# Search application monitored processes by a regular expression
processlist
=
glances_processes
.
getalllist
()
logger
.
info
(
processlist
)
processlist
=
glances_processes
.
getlist
()
# Iter upon the AMPs dict
for
k
,
v
in
iteritems
(
self
.
get
()):
if
not
v
.
enable
():
...
...
glances/globals.py
浏览文件 @
fb93c969
...
...
@@ -25,6 +25,7 @@ import sys
# Operating system flag
# Note: Somes libs depends of OS
# Note2: Included in PsUtil 4.0 or higher
BSD
=
sys
.
platform
.
find
(
'bsd'
)
!=
-
1
LINUX
=
sys
.
platform
.
startswith
(
'linux'
)
MACOS
=
sys
.
platform
.
startswith
(
'darwin'
)
...
...
glances/logs.py
浏览文件 @
fb93c969
...
...
@@ -109,7 +109,7 @@ class GlancesLogs(object):
If 'item' is not a 'new one', update the existing item.
If event < peak_time the the alert is not setoff.
"""
proc_list
=
proc_list
or
glances_processes
.
get
all
list
()
proc_list
=
proc_list
or
glances_processes
.
getlist
()
# Add or update the log
item_index
=
self
.
__itemexist__
(
item_type
)
...
...
glances/processes.py
浏览文件 @
fb93c969
...
...
@@ -20,7 +20,7 @@
import
operator
import
os
from
glances.compat
import
iteritems
,
itervalues
,
listitems
from
glances.compat
import
iteritems
,
itervalues
,
listitems
,
iterkeys
from
glances.globals
import
BSD
,
LINUX
,
MACOS
,
SUNOS
,
WINDOWS
from
glances.timer
import
Timer
,
getTimeSinceLastUpdate
from
glances.filter
import
GlancesFilter
...
...
@@ -29,16 +29,6 @@ from glances.logger import logger
import
psutil
def
is_kernel_thread
(
proc
):
"""Return True if proc is a kernel thread, False instead."""
try
:
return
os
.
getpgid
(
proc
.
pid
)
==
0
# Python >= 3.3 raises ProcessLookupError, which inherits OSError
except
OSError
:
# return False is process is dead
return
False
class
GlancesProcesses
(
object
):
"""Get processed stats using the psutil library."""
...
...
@@ -66,7 +56,6 @@ class GlancesProcesses(object):
# Init stats
self
.
auto_sort
=
True
self
.
_sort_key
=
'cpu_percent'
self
.
allprocesslist
=
[]
self
.
processlist
=
[]
self
.
reset_processcount
()
...
...
@@ -94,12 +83,27 @@ class GlancesProcesses(object):
self
.
reset_max_values
()
def
reset_processcount
(
self
):
"""Reset the global process count"""
self
.
processcount
=
{
'total'
:
0
,
'running'
:
0
,
'sleeping'
:
0
,
'thread'
:
0
,
'pid_max'
:
None
}
def
update_processcount
(
self
,
plist
):
"""Update the global process count from the current processes list"""
# Update the maximum process ID (pid) number
self
.
processcount
[
'pid_max'
]
=
self
.
pid_max
# For each key in the processcount dict
# count the number of processes with the same status
for
k
in
iterkeys
(
self
.
processcount
):
self
.
processcount
[
k
]
=
len
(
list
(
filter
(
lambda
v
:
v
[
'status'
]
is
k
,
plist
)))
# Compute thread
self
.
processcount
[
'thread'
]
=
sum
(
i
[
'num_threads'
]
for
i
in
plist
)
# Compute total
self
.
processcount
[
'total'
]
=
len
(
plist
)
def
enable
(
self
):
"""Enable process stats."""
self
.
disable_tag
=
False
...
...
@@ -224,110 +228,6 @@ class GlancesProcesses(object):
for
k
in
self
.
_max_values_list
:
self
.
_max_values
[
k
]
=
0.0
def
__get_mandatory_stats
(
self
,
proc
,
procstat
):
"""
Get mandatory_stats: for all processes.
Needed for the sorting/filter step.
Stats grabbed inside this method:
* 'name', 'cpu_times', 'status', 'ppid'
* 'username', 'cpu_percent', 'memory_percent'
"""
procstat
[
'mandatory_stats'
]
=
True
# Name, cpu_times, status and ppid stats are in the same /proc file
# Optimisation fir issue #958
try
:
procstat
.
update
(
proc
.
as_dict
(
attrs
=
[
'name'
,
'cpu_times'
,
'status'
,
'ppid'
],
ad_value
=
''
))
except
(
psutil
.
NoSuchProcess
,
psutil
.
AccessDenied
):
# Try/catch for issue #432 (process no longer exist)
# Try/catch for issue #1120 (only see on Macos)
return
None
else
:
procstat
[
'status'
]
=
str
(
procstat
[
'status'
])[:
1
].
upper
()
try
:
procstat
.
update
(
proc
.
as_dict
(
attrs
=
[
'username'
,
'cpu_percent'
,
'memory_percent'
],
ad_value
=
''
))
except
(
psutil
.
NoSuchProcess
,
psutil
.
AccessDenied
):
# Try/catch for issue #432 (process no longer exist)
return
None
if
procstat
[
'cpu_percent'
]
==
''
or
procstat
[
'memory_percent'
]
==
''
:
# Do not display process if we cannot get the basic
# cpu_percent or memory_percent stats
return
None
# Compute the maximum value for cpu_percent and memory_percent
for
k
in
self
.
_max_values_list
:
if
procstat
[
k
]
>
self
.
get_max_values
(
k
):
self
.
set_max_values
(
k
,
procstat
[
k
])
# Process command line (cached with internal cache)
if
procstat
[
'pid'
]
not
in
self
.
cmdline_cache
:
# Patch for issue #391
try
:
self
.
cmdline_cache
[
procstat
[
'pid'
]]
=
proc
.
cmdline
()
except
(
AttributeError
,
EnvironmentError
,
UnicodeDecodeError
,
psutil
.
AccessDenied
,
psutil
.
NoSuchProcess
):
self
.
cmdline_cache
[
procstat
[
'pid'
]]
=
""
procstat
[
'cmdline'
]
=
self
.
cmdline_cache
[
procstat
[
'pid'
]]
# Process IO
# procstat['io_counters'] is a list:
# [read_bytes, write_bytes, read_bytes_old, write_bytes_old, io_tag]
# If io_tag = 0 > Access denied (display "?")
# If io_tag = 1 > No access denied (display the IO rate)
# Availability: all platforms except macOS and Illumos/Solaris
try
:
# Get the process IO counters
proc_io
=
proc
.
io_counters
()
io_new
=
[
proc_io
.
read_bytes
,
proc_io
.
write_bytes
]
except
(
psutil
.
AccessDenied
,
psutil
.
NoSuchProcess
,
NotImplementedError
):
# Access denied to process IO (no root account)
# NoSuchProcess (process die between first and second grab)
# Put 0 in all values (for sort) and io_tag = 0 (for display)
procstat
[
'io_counters'
]
=
[
0
,
0
]
+
[
0
,
0
]
io_tag
=
0
except
AttributeError
:
return
procstat
else
:
# For IO rate computation
# Append saved IO r/w bytes
try
:
procstat
[
'io_counters'
]
=
io_new
+
self
.
io_old
[
procstat
[
'pid'
]]
except
KeyError
:
procstat
[
'io_counters'
]
=
io_new
+
[
0
,
0
]
# then save the IO r/w bytes
self
.
io_old
[
procstat
[
'pid'
]]
=
io_new
io_tag
=
1
# Append the IO tag (for display)
procstat
[
'io_counters'
]
+=
[
io_tag
]
return
procstat
def
__get_standard_stats
(
self
,
proc
,
procstat
):
"""
Get standard_stats: only for displayed processes.
Stats grabbed inside this method:
* nice and memory_info
"""
procstat
[
'standard_stats'
]
=
True
# Process nice and memory_info (issue #926)
try
:
procstat
.
update
(
proc
.
as_dict
(
attrs
=
[
'nice'
,
'memory_info'
]))
except
psutil
.
NoSuchProcess
:
pass
return
procstat
def
__get_extended_stats
(
self
,
proc
,
procstat
):
"""
Get extended stats, only for top processes (see issue #403).
...
...
@@ -377,175 +277,12 @@ class GlancesProcesses(object):
return
procstat
def
__get_process_stats
(
self
,
proc
,
mandatory_stats
=
True
,
standard_stats
=
True
,
extended_stats
=
False
):
"""Get stats of a running processes."""
# Process ID (always)
procstat
=
proc
.
as_dict
(
attrs
=
[
'pid'
])
if
mandatory_stats
:
procstat
=
self
.
__get_mandatory_stats
(
proc
,
procstat
)
if
procstat
is
not
None
and
standard_stats
:
procstat
=
self
.
__get_standard_stats
(
proc
,
procstat
)
if
procstat
is
not
None
and
extended_stats
and
not
self
.
disable_extended_tag
:
procstat
=
self
.
__get_extended_stats
(
proc
,
procstat
)
return
procstat
def
update
(
self
):
"""Update the processes stats."""
# Reset the stats
self
.
processlist
=
[]
self
.
reset_processcount
()
# Do not process if disable tag is set
if
self
.
disable_tag
:
return
# Get the time since last update
time_since_update
=
getTimeSinceLastUpdate
(
'process_disk'
)
# Reset the max dict
self
.
reset_max_values
()
# Update the maximum process ID (pid) number
self
.
processcount
[
'pid_max'
]
=
self
.
pid_max
# Build an internal dict with only mandatories stats (sort keys)
processdict
=
{}
excluded_processes
=
set
()
for
proc
in
psutil
.
process_iter
():
# Ignore kernel threads if needed
if
self
.
no_kernel_threads
and
not
WINDOWS
and
is_kernel_thread
(
proc
):
continue
# If self.max_processes is None: Only retrieve mandatory stats
# Else: retrieve mandatory and standard stats
s
=
self
.
__get_process_stats
(
proc
,
mandatory_stats
=
True
,
standard_stats
=
self
.
max_processes
is
None
)
# Check if s is note None (issue #879)
# ignore the 'idle' process on Windows and *BSD
# ignore the 'kernel_task' process on macOS
# waiting for upstream patch from psutil
if
(
s
is
None
or
BSD
and
s
[
'name'
]
==
'idle'
or
WINDOWS
and
s
[
'name'
]
==
'System Idle Process'
or
MACOS
and
s
[
'name'
]
==
'kernel_task'
):
continue
# Continue to the next process if it has to be filtered
if
self
.
_filter
.
is_filtered
(
s
):
excluded_processes
.
add
(
proc
)
continue
# Ok add the process to the list
processdict
[
proc
]
=
s
# Update processcount (global statistics)
try
:
self
.
processcount
[
str
(
proc
.
status
())]
+=
1
except
KeyError
:
# Key did not exist, create it
try
:
self
.
processcount
[
str
(
proc
.
status
())]
=
1
except
psutil
.
NoSuchProcess
:
pass
except
psutil
.
NoSuchProcess
:
pass
else
:
self
.
processcount
[
'total'
]
+=
1
# Update thread number (global statistics)
try
:
self
.
processcount
[
'thread'
]
+=
proc
.
num_threads
()
except
Exception
:
pass
if
self
.
_enable_tree
:
self
.
process_tree
=
ProcessTreeNode
.
build_tree
(
processdict
,
self
.
sort_key
,
self
.
sort_reverse
,
self
.
no_kernel_threads
,
excluded_processes
)
for
i
,
node
in
enumerate
(
self
.
process_tree
):
# Only retreive stats for visible processes (max_processes)
if
self
.
max_processes
is
not
None
and
i
>=
self
.
max_processes
:
break
# add standard stats
new_stats
=
self
.
__get_process_stats
(
node
.
process
,
mandatory_stats
=
False
,
standard_stats
=
True
,
extended_stats
=
False
)
if
new_stats
is
not
None
:
node
.
stats
.
update
(
new_stats
)
# Add a specific time_since_update stats for bitrate
node
.
stats
[
'time_since_update'
]
=
time_since_update
else
:
# Process optimization
# Only retreive stats for visible processes (max_processes)
if
self
.
max_processes
is
not
None
:
# Sort the internal dict and cut the top N (Return a list of tuple)
# tuple=key (proc), dict (returned by __get_process_stats)
try
:
processiter
=
sorted
(
iteritems
(
processdict
),
key
=
lambda
x
:
x
[
1
][
self
.
sort_key
],
reverse
=
self
.
sort_reverse
)
except
(
KeyError
,
TypeError
)
as
e
:
logger
.
error
(
"Cannot sort process list by {}: {}"
.
format
(
self
.
sort_key
,
e
))
logger
.
error
(
'{}'
.
format
(
listitems
(
processdict
)[
0
]))
# Fallback to all process (issue #423)
processloop
=
iteritems
(
processdict
)
first
=
False
else
:
processloop
=
processiter
[
0
:
self
.
max_processes
]
first
=
True
else
:
# Get all processes stats
processloop
=
iteritems
(
processdict
)
first
=
False
for
i
in
processloop
:
# Already existing mandatory stats
procstat
=
i
[
1
]
if
self
.
max_processes
is
not
None
:
# Update with standard stats
# and extended stats but only for TOP (first) process
s
=
self
.
__get_process_stats
(
i
[
0
],
mandatory_stats
=
False
,
standard_stats
=
True
,
extended_stats
=
first
)
if
s
is
None
:
continue
procstat
.
update
(
s
)
# Add a specific time_since_update stats for bitrate
procstat
[
'time_since_update'
]
=
time_since_update
# Update process list
self
.
processlist
.
append
(
procstat
)
# Next...
first
=
False
# Build the all processes list used by the AMPs
self
.
allprocesslist
=
[
p
for
p
in
itervalues
(
processdict
)]
# Clean internals caches if timeout is reached
if
self
.
cache_timer
.
finished
():
self
.
username_cache
=
{}
self
.
cmdline_cache
=
{}
# Restart the timer
self
.
cache_timer
.
reset
()
def
update_NEW
(
self
):
"""Update the processes stats."""
# Reset the stats
self
.
processlist
=
[]
self
.
reset_processcount
()
# Do not process if disable tag is set
if
self
.
disable_tag
:
return
...
...
@@ -557,20 +294,84 @@ class GlancesProcesses(object):
mandatories_attr
=
[
'cmdline'
,
'cpu_percent'
,
'cpu_times'
,
'memory_info'
,
'memory_percent'
,
'name'
,
'nice'
,
'pid'
,
'ppid'
,
'status'
,
'username'
]
# io_counters is not available on macOS and Illumos/Solaris
if
not
MACOS
and
not
SUNOS
:
'ppid'
,
'status'
,
'username'
,
'status'
,
'num_threads'
,
'gids'
]
# io_counters availability: Linux, BSD, Windows, AIX
if
LINUX
or
BSD
or
WINDOWS
:
mandatories_attr
+=
[
'io_counters'
]
# and build the processes stats list
self
.
processlist
=
[
p
.
info
for
p
in
sorted
(
psutil
.
process_iter
(
attrs
=
mandatories_attr
,
ad_value
=
None
),
key
=
lambda
p
:
p
.
info
[
'cpu_percent'
])]
# Update the maximum process ID (pid) number
self
.
processcount
[
'pid_max'
]
=
self
.
pid_max
# and build the processes stats list
self
.
processlist
=
[
p
.
info
for
p
in
psutil
.
process_iter
(
attrs
=
mandatories_attr
,
ad_value
=
None
)
# OS specifics processes filter
if
not
(
BSD
and
p
.
info
[
'name'
]
==
'idle'
)
and
not
(
WINDOWS
and
p
.
info
[
'name'
]
==
'System Idle Process'
)
and
not
(
MACOS
and
p
.
info
[
'name'
]
==
'kernel_task'
)
and
# Kernel threads filter
not
(
self
.
no_kernel_threads
and
LINUX
and
p
.
info
[
'gids'
].
real
==
0
)
and
# User filter
not
(
self
.
_filter
.
is_filtered
(
p
.
info
))
]
# Sort the processes list by the current sort_key
self
.
processlist
=
sorted
(
self
.
processlist
,
key
=
lambda
p
:
p
[
self
.
sort_key
],
reverse
=
True
)
# Update the processcount
self
.
update_processcount
(
self
.
processlist
)
# Loop over processes and add metadata
first
=
True
for
proc
in
self
.
processlist
:
if
first
and
not
self
.
disable_extended_tag
:
# Get extended stats, only for top processes (see issue #403).
# - cpu_affinity (Linux, Windows, FreeBSD)
# - ionice (Linux and Windows > Vista)
# - memory_full_info (Linux)
# - num_ctx_switches (not available on Illumos/Solaris)
# - num_fds (Unix-like)
# - num_handles (Windows)
# - num_threads (not available on *BSD)
# - memory_maps (only swap, Linux)
# https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
# - connections (TCP and UDP)
extended
=
{}
try
:
top_process
=
psutil
.
Process
(
proc
[
'pid'
])
extended_stats
=
[
'cpu_affinity'
,
'ionice'
,
'memory_full_info'
,
'num_ctx_switches'
,
'num_fds'
,
'num_threads'
]
if
WINDOWS
:
extended_stats
+=
[
'num_handles'
]
extended
=
top_process
.
as_dict
(
attrs
=
extended_stats
)
# !!! TODO
# if LINUX:
# try:
# procstat['memory_swap'] = sum([v.swap for v in proc.memory_maps()])
# except psutil.NoSuchProcess:
# pass
# except (psutil.AccessDenied, TypeError, NotImplementedError):
# # NotImplementedError: /proc/${PID}/smaps file doesn't exist
# # on kernel < 2.6.14 or CONFIG_MMU kernel configuration option
# # is not enabled (see psutil #533/glances #413).
# # XXX: Remove TypeError once we'll drop psutil < 3.0.0.
# procstat['memory_swap'] = None
# try:
# procstat['tcp'] = len(proc.connections(kind="tcp"))
# procstat['udp'] = len(proc.connections(kind="udp"))
# except psutil.AccessDenied:
# procstat['tcp'] = None
# procstat['udp'] = None
except
(
psutil
.
NoSuchProcess
,
ValueError
,
AttributeError
)
as
e
:
logger
.
error
(
'Can not grab extended stats ({})'
.
format
(
e
))
extended
[
'extended_stats'
]
=
False
else
:
logger
.
debug
(
'Grab extended stats for process {}'
.
format
(
proc
[
'pid'
]))
extended
[
'extended_stats'
]
=
True
proc
.
update
(
extended
)
first
=
False
# Time since last update (for disk_io rate computation)
proc
[
'time_since_update'
]
=
time_since_update
...
...
@@ -598,23 +399,18 @@ class GlancesProcesses(object):
else
:
proc
[
'io_counters'
]
=
[
0
,
0
]
+
[
0
,
0
]
io_tag
=
0
# Append the IO tag (for display)
proc
[
'io_counters'
]
+=
[
io_tag
]
# Compute the maximum value for keys in self._max_values_list
# Compute max
# Compute the maximum value for keys in self._max_values_list (CPU, MEM)
for
k
in
self
.
_max_values_list
:
self
.
set_max_values
(
k
,
max
(
i
[
k
]
for
i
in
self
.
processlist
))
if
self
.
processlist
!=
[]:
self
.
set_max_values
(
k
,
max
(
i
[
k
]
for
i
in
self
.
processlist
))
def
getcount
(
self
):
"""Get the number of processes."""
return
self
.
processcount
def
getalllist
(
self
):
"""Get the allprocesslist."""
return
self
.
allprocesslist
def
getlist
(
self
,
sortedby
=
None
):
"""Get the processlist."""
return
self
.
processlist
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录